生成骨架 Shellcode 并分配内存¶
使用与清单 7-2 相同的方法,你可以为这个洞穴生成 shellcode,如清单 7-8 所示。
BYTE codeCave[31] = {
0x60, // PUSHAD
0x9C, // PUSHFD
0x68, 0x00, 0x00, 0x00, 0x00, // PUSH 0
0xB8, 0x00, 0x00, 0x00, 0x00, // MOV EAX, 0x0
0xFF, 0xD0, // CALL EAX
0x83, 0xC4, 0x08, // ADD ESP, 0x08
0x9D, // POPFD
0x61, // POPAD
0x68, 0x00, 0x00, 0x00, 0x00, // PUSH 0
0xC3 // RETN
};
// 这里需要添加一些代码,把线程的 EIP 放入 threadContext.Eip
memcpy(&codeCave[3], &remoteString, 4);
memcpy(&codeCave[8], ×, 4);
memcpy(&codeCave[13], &func, 4);
memcpy(&codeCave[25], &threadContext.Eip, 4);
清单 7-8:创建线程劫持 shellcode 数组
与清单 7-3 一样,用 memcpy() 把变量放入骨架。与那个清单不同,有两个变量不能马上复制;times 和 func 立即可知,但 remoteString 是分配的结果,threadContext.Eip 只有在线程冻结后才会知道。在冻结线程之前分配内存也是合理的,因为你不想让线程冻结超过必要时间。
int stringlen = strlen(string) + 1;
int cavelen = sizeof(codeCave);
int fulllen = stringlen + cavelen;
auto remoteString =
VirtualAllocEx(process, 0, fulllen,
MEM_COMMIT, PAGE_EXECUTE);
auto remoteCave =
(LPVOID)((DWORD)remoteString + stringlen);
分配代码与线程注入相同,所以你可以复用同一段代码。