Skip to content

Commit 234ef56

Browse files
committed
Land rapid7#9299, Add arch to MS17-010 detection
2 parents be4f923 + 3cd287d commit 234ef56

File tree

3 files changed

+83
-60
lines changed

3 files changed

+83
-60
lines changed

lib/msf/core/exploit/dcerpc.rb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,70 @@ def dcerpc_call(function, stub = '', timeout=nil, do_recv=true)
143143
end
144144
end
145145

146+
# XXX: Copypasta from exploit/windows/smb/ms17_010_eternalblue
147+
#
148+
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
149+
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
150+
def dcerpc_getarch
151+
ret = nil
152+
153+
connect_timeout = (datastore['ConnectTimeout'] || 10).to_i
154+
read_timeout = (datastore['DCERPC::ReadTimeout'] || 10).to_i
155+
156+
pkt = Rex::Proto::DCERPC::Packet.make_bind(
157+
# Abstract Syntax: EPMv4 V3.0
158+
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
159+
# Transfer Syntax[1]: 64bit NDR V1
160+
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
161+
).first
162+
163+
begin
164+
nsock = Rex::Socket::Tcp.create(
165+
'PeerHost' => rhost,
166+
'PeerPort' => 135,
167+
'Proxies' => proxies,
168+
'Timeout' => connect_timeout,
169+
'Context' => {
170+
'Msf' => framework,
171+
'MsfExploit' => self
172+
}
173+
)
174+
rescue Rex::ConnectionError => e
175+
vprint_error(e.to_s)
176+
return nil
177+
end
178+
179+
nsock.put(pkt)
180+
181+
begin
182+
res = nsock.get_once(60, read_timeout)
183+
rescue EOFError
184+
vprint_error('DCE/RPC socket returned EOFError')
185+
return nil
186+
end
187+
188+
disconnect(nsock)
189+
190+
begin
191+
resp = Rex::Proto::DCERPC::Response.new(res)
192+
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
193+
vprint_error(e.to_s)
194+
return nil
195+
end
196+
197+
# Ack result: Acceptance (0)
198+
if resp.ack_result.first == 0
199+
ret = ARCH_X64
200+
end
201+
# Ack result: Provider rejection (2)
202+
# Ack reason: Proposed transfer syntaxes not supported (2)
203+
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
204+
ret = ARCH_X86
205+
end
206+
207+
ret
208+
end
209+
146210
# Convert a standard ASCII string to 16-bit Unicode
147211
def unicode(str)
148212
Rex::Text.to_unicode(str)

modules/auxiliary/scanner/smb/smb_ms17_010.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
##
55

66
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Exploit::Remote::DCERPC
78
include Msf::Exploit::Remote::SMB::Client
89
include Msf::Exploit::Remote::SMB::Client::Authenticated
910

@@ -50,7 +51,8 @@ def initialize(info = {})
5051

5152
register_options(
5253
[
53-
OptBool.new('CHECK_DOPU', [true, 'Check for DOUBLEPULSAR on vulnerable hosts', true])
54+
OptBool.new('CHECK_DOPU', [true, 'Check for DOUBLEPULSAR on vulnerable hosts', true]),
55+
OptBool.new('CHECK_ARCH', [true, 'Check for architecture on vulnerable hosts', true])
5456
])
5557
end
5658

@@ -76,12 +78,23 @@ def run_host(ip)
7678
vprint_status("Received #{status} with FID = 0")
7779

7880
if status == "STATUS_INSUFF_SERVER_RESOURCES"
79-
print_good("Host is likely VULNERABLE to MS17-010! (#{simple.client.peer_native_os})")
81+
os = simple.client.peer_native_os
82+
83+
if datastore['CHECK_ARCH']
84+
case dcerpc_getarch
85+
when ARCH_X86
86+
os << ' x86 (32-bit)'
87+
when ARCH_X64
88+
os << ' x64 (64-bit)'
89+
end
90+
end
91+
92+
print_good("Host is likely VULNERABLE to MS17-010! - #{os}")
8093
report_vuln(
8194
host: ip,
8295
name: self.name,
8396
refs: self.references,
84-
info: 'STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$ -- (#{simple.client.peer_native_os})'
97+
info: "STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$ - #{os}"
8598
)
8699

87100
# vulnerable to MS17-010, check for DoublePulsar infection

modules/exploits/windows/smb/ms17_010_eternalblue.rb

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class MetasploitModule < Msf::Exploit::Remote
1111
Rank = AverageRanking
1212

13-
include Msf::Exploit::Remote::Tcp
13+
include Msf::Exploit::Remote::DCERPC
1414

1515
def initialize(info = {})
1616
super(update_info(info,
@@ -267,63 +267,9 @@ def verify_target(os)
267267
return ret
268268
end
269269

270-
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
271-
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
272270
def verify_arch
273-
ret = false
274-
275-
return true if !datastore['VerifyArch']
276-
277-
pkt = Rex::Proto::DCERPC::Packet.make_bind(
278-
# Abstract Syntax: EPMv4 V3.0
279-
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
280-
# Transfer Syntax[1]: 64bit NDR V1
281-
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
282-
).first
283-
284-
begin
285-
sock = connect(false,
286-
'RHOST' => rhost,
287-
'RPORT' => 135
288-
)
289-
rescue Rex::ConnectionError => e
290-
print_error(e.to_s)
291-
return false
292-
end
293-
294-
sock.put(pkt)
295-
296-
begin
297-
res = sock.get_once(60)
298-
rescue EOFError
299-
print_error('DCE/RPC socket returned EOFError')
300-
return false
301-
end
302-
303-
disconnect(sock)
304-
305-
begin
306-
resp = Rex::Proto::DCERPC::Response.new(res)
307-
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
308-
print_error(e.to_s)
309-
return false
310-
end
311-
312-
case target_arch.first
313-
when ARCH_X64
314-
# Ack result: Acceptance (0)
315-
if resp.ack_result.first == 0
316-
ret = true
317-
end
318-
when ARCH_X86
319-
# Ack result: Provider rejection (2)
320-
# Ack reason: Proposed transfer syntaxes not supported (2)
321-
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
322-
ret = true
323-
end
324-
end
325-
326-
ret
271+
return true unless datastore['VerifyArch']
272+
(dcerpc_getarch == target_arch.first) ? true : false
327273
end
328274

329275
def print_core_buffer(os)

0 commit comments

Comments
 (0)