热补丁填充是否始终为16的倍数?多余填充字节能否被shellcode安全使用?
提问内容
我使用/hotpatch和/FUNCTIONPADMIN:195编译选项生成了Windows可执行文件,该配置会在main()函数起始位置前添加195字节的填充。
// Windows x86 无 null 字节 WinExec 启动计算器 shellcode char shellcode[195] = "\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b" "\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3" "\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24" "\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14" "\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18" "\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74" "\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41" "\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52" "\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51" "\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff" "\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f" "\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2" "\x52\xff\xd0"; int main(int argc, char* argv[]) { char (*jmp)() = (char*)&main - sizeof(shellcode); jmp(); }
我将上述shellcode写入了main()起始地址前195字节的二进制镜像区域中。反汇编后发现实际存在13字节的额外0xCC填充:
00401000: CC CC CC CC CC CC CC CC CC CC CC CC CC 89 E5 83 IIIIIIIIIIIII%†Ÿ 00401010: EC 20 31 DB 64 8B 5B 30 8B 5B 0C 8B 5B 1C 8B 1B 1Ud<[0<[.<[.<. 00401020: 8B 1B 8B 43 08 89 45 FC 8B 58 3C 01 C3 8B 5B 78 <.<C.%E<X<.A<[x 00401030: 01 C3 8B 7B 20 01 C7 89 7D F8 8B 4B 24 01 C1 89 .A<{ .€%}o<K$.A% 00401040: 4D F4 8B 53 1C 01 C2 89 55 F0 8B 53 14 89 55 EC M“<S..A%Ud<S.%U 00401050: EB 32 31 C0 8B 55 EC 8B 7D F8 8B 75 18 31 C9 FC ‰21A<U<}o<u.1 00401060: 8B 3C 87 03 7D FC 66 83 C1 08 F3 A6 74 05 40 39 <<Ø.}fŸA.¢Ýt.@9 00401070: D0 72 E4 8B 4D F4 8B 55 F0 66 8B 04 41 8B 04 82 Dr„<M“<Udf<.A<., 00401080: 03 45 FC C3 BA 78 78 65 63 C1 EA 08 52 68 57 69 .EA§xxecAˆ.RhWi 00401090: 6E 45 89 65 18 E8 B8 FF FF FF 31 C9 51 68 2E 65 nE%e.Š,˜˜˜1Qh.e 004010A0: 78 65 68 63 61 6C 63 89 E3 41 51 53 FF D0 31 C9 xehcalc%aAQS˜D1 004010B0: B9 01 65 73 73 C1 E9 08 51 68 50 72 6F 63 68 45 1.essA‚.QhProchE 004010C0: 78 69 74 89 65 18 E8 87 FF FF FF 31 D2 52 FF D0 xit%e.ŠØ˜˜˜1OR˜D _main: 004010D0: 66 90 xchg ax,ax ; 热补丁机制的一部分 004010D2: 55 push ebp 004010D3: 8B EC mov ebp,esp 004010D5: 51 push ecx 004010D6: B8 D0 10 40 00 mov eax,offset _main 004010DB: 2D C3 00 00 00 sub eax,0C3h 004010E0: 89 45 FC mov dword ptr [ebp-4],eax 004010E3: FF 55 FC call dword ptr [ebp-4] 004010E6: 33 C0 xor eax,eax 004010E8: 8B E5 mov esp,ebp 004010EA: 5D pop ebp 004010EB: C3 ret
如果热补丁填充始终为16的倍数,那么这些额外的字节是否可以被shellcode安全使用?
运行该可执行文件可正常启动Windows计算器,运行效果见截图:
解答
这13字节的额外0xCC填充完全可以被shellcode安全使用,具体说明如下:
/FUNCTIONPADMIN选项本身就会把用户指定的填充长度向上对齐到16字节边界,你指定的195字节向上取16的倍数为208字节,差值正好是你观测到的13字节,这部分内存和你原本申请的195字节属于同一块链接器预留的热补丁专属内存区域,属性为可读可执行,不会被程序其他逻辑占用。- 你当前的195字节shellcode刚好占用了这块208字节预留区的尾部空间,前面的13字节属于同一块预留内存的未使用部分,只要后续写入的shellcode总长度不超过208字节,使用这部分空间不会出现内存越界问题。
- 注意:这个对齐逻辑仅在使用相同版本MSVC编译器、保留
/hotpatch和/FUNCTIONPADMIN:195配置的前提下稳定,如果更换编译环境或修改编译参数,需要重新测算对齐后的总预留空间大小,避免shellcode越界。
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

