Skip to content

Commit 2135567

Browse files
committed
Land rapid7#2765 - Added Poison Ivy Command and Control Scanner
2 parents 8a1f701 + 0a07bbd commit 2135567

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
7+
require 'msf/core'
8+
9+
class Metasploit3 < Msf::Auxiliary
10+
11+
include Msf::Exploit::Remote::Tcp
12+
include Msf::Auxiliary::Report
13+
include Msf::Auxiliary::Scanner
14+
15+
def initialize
16+
super(
17+
'Name' => 'Poison Ivy C&C Scanner',
18+
'Description' => %q{
19+
Enumerate Poison Ivy C&C on ports 3460,80,8080 and 443. Adaptation of iTrust Python script.
20+
},
21+
'References' =>
22+
[
23+
['URL', 'www.malware.lu/Pro/RAP002_APT1_Technical_backstage.1.0.pdf'],
24+
],
25+
'Author' => ['SeawolfRN'],
26+
'License' => MSF_LICENSE
27+
)
28+
29+
register_options(
30+
[
31+
OptString.new('PORTS', [true, "Ports to Check","80,8080,443,3460"]),
32+
OptInt.new('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]),
33+
OptInt.new('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10])
34+
], self.class)
35+
36+
deregister_options('RPORT')
37+
38+
end
39+
40+
41+
def run_host(ip)
42+
43+
timeout = datastore['TIMEOUT'].to_i
44+
45+
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
46+
47+
if ports.empty?
48+
raise Msf::OptionValidateError.new(['PORTS'])
49+
end
50+
51+
while(ports.length > 0)
52+
t = []
53+
r = []
54+
begin
55+
1.upto(datastore['CONCURRENCY']) do
56+
this_port = ports.shift
57+
break if not this_port
58+
t << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port|
59+
begin
60+
s = connect(false,
61+
{
62+
'RPORT' => port,
63+
'RHOST' => ip,
64+
'ConnectTimeout' => (timeout / 1000.0)
65+
}
66+
)
67+
r << [ip,port,"open",'Unknown']
68+
s.puts("\x00"*0x100,0) #Send 0x100 zeros, wait for answer
69+
data = s.get_once(0x100)
70+
if data.length == 0x100
71+
data = s.get_once(0x4)
72+
if data == "\xD0\x15\x00\x00" #Signature for PIVY C&C
73+
print_status("#{ip}:#{port} - C&C Server Found")
74+
r << [ip,port,"open",'Poison Ivy C&C']
75+
end
76+
end
77+
rescue ::Rex::ConnectionRefused
78+
vprint_status("#{ip}:#{port} - TCP closed")
79+
r << [ip,port,"closed",'']
80+
rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error
81+
rescue ::Rex::Post::Meterpreter::RequestError
82+
raise $!
83+
ensure
84+
disconnect(s) rescue nil
85+
end
86+
end
87+
end
88+
t.each {|x| x.join }
89+
90+
rescue ::Timeout::Error
91+
ensure
92+
t.each {|x| x.kill rescue nil }
93+
end
94+
95+
r.each do |res|
96+
report_service(:host => res[0], :port => res[1], :state => res[2], :name=> res[3])
97+
end
98+
end
99+
end
100+
101+
end

0 commit comments

Comments
 (0)