|
| 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