首页 > 解决方案 > Hot Patching 填充是否总是 16 的倍数?

问题描述

使用选项/hotpatch/FUNCTIONPADMIN:195创建了一个 Windows 可执行文件,它将 195 字节的填充添加到 main() 的开头。

// Windows x86 null-free WinExec Calc.exe 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“&lt;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„&lt;M“&lt;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     ; part of hot patching method.
  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 计算器:
shellcode_calc_exe

标签: cwindowsassemblyvisual-c++hotpatching

解决方案


如果热补丁填充始终是 16 的倍数,shellcode 可以安全地使用任何额外的字节吗?

,因为前一个函数的大小可能会有所不同。

f函数具有偏移量0x00401000,并且g位于之后。with/FUNCTIONPADMIN g会有偏移量0x00401000 + <f size> + <at least 195>。是在 16 字节边界上对齐<at least 195>的最小可能值。g如果<f size>是 13,则<at least 195>等于 195,并且没有额外的填充。

当前的 MSVC 填充0xCC是一字节int 3指令。这可用于检查填充是否正确大小,以及是否尚未被另一个热补丁使用。


推荐阅读