cwindowsassemblyvisual-c++hotpatching

Is the Hot Patching padding always a multiple of 16?


Created a Windows executable with options /hotpatch and /FUNCTIONPADMIN:195 which adds 195 bytes of padding to the beginning of 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();
}

The shellcode was written into the binary image 195 bytes prior to the start of main().
Upon disassembling, it shows there are 13 bytes of extra padding (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     ; 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

If the hot patch padding is always a multiple of 16, can any extra bytes be safely used by the shellcode?

Running the executable, starts the Windows Calculator:
shellcode_calc_exe


Solution

  • If the hot patch padding is always a multiple of 16, can any extra bytes be safely used by the shellcode?

    No, because the size of the previous function may vary.

    f function has the offset 0x00401000, and g is located afterwards. With /FUNCTIONPADMIN g will have the offset 0x00401000 + <f size> + <at least 195>. <at least 195> is the smallest possible value to make g aligned on 16 bytes boundary. If <f size> is 13, then <at least 195> equals to 195, and there's no extra padding.

    Current MSVC pads with 0xCC which is one-byte int 3 instruction. This can be used for checking if the padding is the right size, and if it isn't used already by another hotpatch.