Path: blob/master/modules/auxiliary/scanner/netbios/nbname.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report7include Msf::Auxiliary::UDPScanner89def initialize10super(11'Name' => 'NetBIOS Information Discovery',12'Description' => 'Discover host information through NetBIOS',13'Author' => 'hdm',14'License' => MSF_LICENSE15)1617register_options(18[19Opt::RPORT(137)20]21)22end2324def scanner_prescan(batch)25print_status("Sending NetBIOS requests to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")26@results = {}27end2829def scan_host(ip)30scanner_send(create_netbios_status(ip), ip, datastore['RPORT'])31end3233def scanner_postscan(batch)34cnt = 03536# Perform a second pass based on responsive hosts37@results.keys.each do |ip|38next if not @results[ip][:name]3940scanner_send(create_netbios_lookup(@results[ip][:name]), ip, datastore['RPORT'])41cnt += 142end4344# Wait for the final replies to trickle in45scanner_recv(10) if cnt > 04647@results.keys.each do |ip|48host = @results[ip]49user = ""50os = "Windows"5152if (host[:user] and host[:mac] != "00:00:00:00:00:00")53user = " User:#{host[:user]}"54end5556if (host[:mac] == "00:00:00:00:00:00")57os = "Unix"58end5960names = ""61if (host[:names])62names = " Names:(" + host[:names].map { |n| n[0] }.uniq.join(", ") + ")"63end6465addrs = ""66if (host[:addrs])67addrs = "Addresses:(" + host[:addrs].map { |n| n[0] }.uniq.join(", ") + ")"68end6970if (host[:mac] != "00:00:00:00:00:00")71report_host(:host => ip, :mac => host[:mac])72else73report_host(:host => ip)74end7576extra = ""7778virtual = nil79case host[:mac]80when /^00:13:07/i81virtual = 'ParaVirtual'82when /^(00:1C:14|00:50:56|00:05:69|00:0c:29)/i83virtual = 'VMWare'84when /^00:1C:42/85virtual = "Parallels"86when /^00:18:51/87virtual = "SWsoft Virtuozzo"88when /^00:21:F6/i89virtual = 'Virtual Iron'90when /^00:16:3e/91virtual = 'Xen'92when /^(54:52:00|DE:AD:BE)/93virtual = 'QEMU (unofficial)'94when /^00:24:0B/i95virtual = 'Virtual Computer Inc'96end9798if (virtual)99extra = "Virtual Machine:#{virtual}"100report_note(101:host => ip,102:type => 'host.virtual_machine',103:data => { :vendor => virtual, :method => 'netbios' }104)105end106107if (host[:addrs])108aliases = []109host[:addrs].map { |n| n[0] }.uniq.each do |addr|110next if addr == ip111112aliases << addr113end114115if not aliases.empty?116report_note(117:host => ip,118:proto => 'udp',119:port => 137,120:type => 'netbios.addresses',121:data => { :addresses => aliases }122)123end124end125126print_good("#{ip} [#{host[:name]}] OS:#{os}#{user}#{names} #{addrs} Mac:#{host[:mac]} #{extra}")127end128end129130def scanner_process(data, shost, sport)131head = data.slice!(0, 12)132133xid, flags, quests, answers, auths, adds = head.unpack('n6')134135return if quests != 0136return if answers == 0137138qname = data.slice!(0, 34)139rtype, rclass, rttl, rlen = data.slice!(0, 10).unpack('nnNn')140buff = data.slice!(0, rlen)141142names = []143144hname = nil145uname = nil146147@results[shost] ||= {}148149case rtype150when 0x21151rcnt = buff.slice!(0, 1).unpack("C")[0]1521.upto(rcnt) do153tname = buff.slice!(0, 15).gsub(/\x00.*/, '').strip154ttype = buff.slice!(0, 1).unpack("C")[0]155tflag = buff.slice!(0, 2).unpack('n')[0]156names << [ tname, ttype, tflag ]157hname = tname if ttype == 0x20158uname = tname if ttype == 0x03159end160maddr = buff.slice!(0, 6).unpack("C*").map { |c| "%.2x" % c }.join(":")161162@results[shost][:names] = names163@results[shost][:mac] = maddr164165if (!hname and @results[shost][:names].length > 0)166@results[shost][:name] = @results[shost][:names][0][0]167end168169@results[shost][:name] = hname if hname170@results[shost][:user] = uname if uname171172inf = ''173names.each do |name|174inf << name[0]175inf << ":<%.2x>" % name[1]176if (name[2] & 0x8000 == 0)177inf << ":U :"178else179inf << ":G :"180end181end182inf << maddr183184report_service(185:host => shost,186:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,187:host_name => (hname) ? hname.downcase : nil,188:port => datastore['RPORT'],189:proto => 'udp',190:name => 'netbios',191:info => inf192)193194when 0x201951.upto(rlen / 6.0) do196tflag = buff.slice!(0, 2).unpack('n')[0]197taddr = buff.slice!(0, 4).unpack("C*").join(".")198names << [ taddr, tflag ]199end200@results[shost][:addrs] = names201end202end203204def create_netbios_status(ip)205data =206[rand(0xffff)].pack('n') +207"\x00\x00\x00\x01\x00\x00\x00\x00" +208"\x00\x00\x20\x43\x4b\x41\x41\x41" +209"\x41\x41\x41\x41\x41\x41\x41\x41" +210"\x41\x41\x41\x41\x41\x41\x41\x41" +211"\x41\x41\x41\x41\x41\x41\x41\x41" +212"\x41\x41\x41\x00\x00\x21\x00\x01"213214return data215end216217def create_netbios_lookup(name)218name = [name].pack("A15") + "\x00"219220data =221[rand(0xffff)].pack('n') +222"\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +223"\x20" +224Rex::Proto::SMB::Utils.nbname_encode(name) +225"\x00" +226"\x00\x20\x00\x01"227228return data229end230end231232233