Path: blob/master/modules/auxiliary/scanner/h323/h323_version.rb
19567 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Tcp7include Msf::Auxiliary::Scanner8include Msf::Auxiliary::Report910def initialize11super(12'Name' => 'H.323 Version Scanner',13'Description' => 'Detect H.323 Version.',14'Author' => 'hdm',15'License' => MSF_LICENSE16)1718register_options(19[20Opt::RPORT(1720),21]22)23end2425def run_host(ip)26remote_display = nil27remote_product_id = nil28remote_version_id = nil29remote_vendor_id = nil30remote_protocol = nil3132begin33# Wrap this in a timeout to prevent dead services from34# hanging this thread.35Timeout.timeout(call_timeout) do36connect3738caller_name = "SYSTEM\x00"39h323_id = Rex::Text.rand_text_alpha(3)40vendor_id = Rex::Text.rand_text_alpha(32)41caller_host = Rex::Socket.source_address(ip)42caller_port = rand(32768) + 3000043callee_host = rhost44callee_port = rport45conf_guid = Rex::Text.rand_text(16)46call_guid = Rex::Text.rand_text(16)4748pkt_setup = h323_setup_call({49:caller_name => caller_name,50:h323_id => h323_id,51:vendor_id => vendor_id,52:callee_host => callee_host,53:callee_port => callee_port,54:caller_host => caller_host,55:caller_port => caller_port,56:conf_guid => conf_guid,57:call_guid => call_guid58})5960res = sock.put(pkt_setup) rescue nil61if not res62disconnect63return64end6566cnt = 067while (true)68info = read_packet69break if not info7071# The remote side of the call disconnected us72break if info[:type] == @@H323_STATUS_RELEASE_COMPLETE7374remote_display = info[40].strip if info[40]75remote_product_id = info[:product_id].strip if info[:product_id]76remote_version_id = info[:version_id].strip if info[:version_id]77remote_protocol = info[:protocol_version].strip if info[:protocol_version]7879if info[:vendor_id] and [nil, "Unknown"].include?(remote_vendor_id)80remote_vendor_id = info[:vendor_id].strip81end8283# Diagnostics84# print_status("Host: #{rhost}:#{rport} => #{info.inspect}")8586# The remote side of the call was connected (kill it)87break if info[:type] == @@H323_STATUS_CONNECT8889# Exit if we already received 5 packets from the server90break if (cnt += 1) > 59192end9394# Make sure the call was shut down cleanly95pkt_release = h323_release_call({96:caller_name => caller_name,97:call_guid => call_guid98})99sock.put(pkt_release) rescue nil100101# End timeout block102end103rescue ::Timeout::Error104rescue ::Interrupt105raise $!106rescue ::Rex::ConnectionError, ::IOError, ::Errno::ECONNRESET, ::Errno::ENOPROTOOPT107rescue ::Exception108print_error("#{rhost}:#{rport} #{$!.class} #{$!} #{$!.backtrace}")109ensure110disconnect111end112113if remote_vendor_id114remote_product_id = remote_product_id.to_s.gsub(/[^\x20-\x7e]/, '')115remote_version_id = remote_version_id.to_s.gsub(/[^\x20-\x7e]/, '')116117banner = "Protocol: #{remote_protocol} VendorID: #{remote_vendor_id} "118119if remote_version_id and remote_version_id.length > 0120banner << "VersionID: #{remote_version_id} "121end122123if remote_product_id and remote_product_id.length > 0124banner << "ProductID: #{remote_product_id} "125end126127if remote_display and remote_display.length > 0128remote_display = remote_display.to_s.gsub(/[^\x20-\x7e]/, '')129banner << "DisplayName: #{remote_display}"130end131132print_good("#{rhost}:#{rport} #{banner}")133report_service(:host => rhost, :port => rport, :name => "h323", :info => banner)134end135end136137def read_packet138begin139::Timeout.timeout(read_timeout) do140ver = sock.read(2)141return if not (ver and ver == "\x03\x00")142143bin = sock.read(2)144return if not bin145146len = [ bin.unpack("n")[0] - 4, 0 ].max147return if len == 0148149bin = sock.read(len)150return if not bin151152f_desc, cref_len = bin.unpack("CC")153cref_val = bin[2, cref_len]154f_type = bin[2 + cref_len, 1].unpack("C")[0]155156return { :type => f_type, :call_ref => cref_val }.merge(read_ies(f_type, bin[2 + cref_len + 1, bin.length]))157end158rescue ::Timeout::Error159end160nil161end162163def read_ies(mtype, data)164r = {}165i = 0166167while (i < (data.length - 1))168ie_type = data[i, 1].unpack("C")[0]169break if not ie_type170171ie_len = 0172ie_data = ""173174case ie_type175when @@H225_IE_USER_USER176ie_len = data[i + 1, 2].unpack("n")[0]177break if not ie_len178179ie_data = data[i + 3, ie_len]180break if not ie_data181182i = i + 3 + ie_len183else184ie_len = data[i + 1, 1].unpack("C")[0]185break if not ie_len186187ie_data = data[i + 2, ie_len]188break if not ie_data189190i = i + 2 + ie_len191end192193r[ie_type] = ie_data194195if ie_type == @@H225_IE_USER_USER196r.merge!((read_user_user(mtype, ie_data) rescue {}))197end198end199r200end201202# This provides a weak method of decoding USER-USER PDUs. These are203# actually PER-encoded ASN.1, but we take a few shortcuts since PER204# encoding is such a pain.205def read_user_user(mtype, data)206r = {}207208# Identify the embedded version (2/3/4/5/6 commonly found)209i = data.index("\x00\x08\x91\x4a\x00")210return r if not i211212# Store the protocol version213pver = data[i + 5, 1].unpack("C")[0]214215r[:protocol_version] = pver.to_s216217# Bump the index over the version218i += 6219220# print_line( Rex::Text.to_hex_dump( data[i, 32] ) )221222# Set a placeholder VendorID so this system will be reported223r[:vendor_id] = "Unknown"224225# We use the version offset to identify the destination block location226# This changes slightly based on the type of packet we receive227case mtype228when @@H323_STATUS_ALERTING, @@H323_STATUS_PROCEEDING229230if pver == 2 and data[i, 2] == "\x20\x00"231r[:vendor_id] = "0x%.8x" % (data[i + 2, 4].unpack("N")[0] rescue 0)232return r233end234235# Find the offset to the VendorID236if data[i + 1, 1] != "\xc0"237i += 7238end239240# Stop processing if we can't identify a VendorID241return r if data[i + 1, 1] != "\xc0"242243# Otherwise just add 2 to the offset of the version244i += 2245246when @@H323_STATUS_CONNECT247248# Bail early in some corner cases249return r if data[i, 1] == "\x00"250251# Find the offset to the VendorID252if data[i + 1, 1] != "\xc0"253i += 7254end255256# Stop processing if we can't identify a VendorID257return r if data[i + 1, 1] != "\xc0"258259i += 2260261return r262else263return r264end265266# Extract the manufacturer ID267r[:vendor_id] = "0x%.8x" % (data[i, 4].unpack("N")[0] rescue 0)268i += 4269270# No Product ID / Version ID in versions less than 3 (unless special cased above)271return r if pver < 3272273# Get the product_id length (-1)274product_id_length = data[i, 1].unpack("C")[0] + 1275i += 1276277# Extract the product ID278r[:product_id] = data[i, product_id_length]279i += product_id_length280281# Get the version ID length (-1)282version_id_length = data[i, 1].unpack("C")[0] + 1283i += 1284285# Extract the version ID286r[:version_id] = data[i, version_id_length]287288# Thats it for now289290r291end292293def read_timeout29410295end296297def call_timeout29830299end300301@@H225_IE_BEARER_CAP = 0x04302@@H225_IE_DISPLAY = 0x28303@@H225_IE_USER_USER = 0x7e # Yes, really User-user304305@@H323_STATUS_ALERTING = 0x01306@@H323_STATUS_PROCEEDING = 0x02307@@H323_STATUS_SETUP = 0x05308@@H323_STATUS_SETUP_ACK = 0x0D309@@H323_STATUS_CONNECT = 0x07310@@H323_STATUS_RELEASE_COMPLETE = 0x5a311@@H323_STATUS_FACILITY = 0x62312313def encap_tpkt(ver, data)314[ ver, 0, data.length + 4 ].pack("CCn") + data315end316317def encap_q225(desc, cref_value, msg_type, data)318[ desc, cref_value.length, cref_value, msg_type].pack("CCA*C") + data319end320321def encap_q225_standard(msg_type, data)322encap_q225(0x08, [0x733f].pack("n"), msg_type, data)323end324325def encap_q225_setup(data)326encap_q225_standard(0x05, data)327end328329def encap_q225_release(data)330encap_q225_standard(0x5a, data)331end332333def create_ie_byte(ie_type, data)334[ie_type, data.length].pack("CC") + data335end336337def create_ie_short(ie_type, data)338[ie_type, data.length].pack("Cn") + data339end340341def create_ie_bearer_capability(cap = 0x00038893)342create_ie_byte(@@H225_IE_BEARER_CAP, [cap].pack("N")[0, 3])343end344345def create_ie_display(name = "DEBUG\x00")346create_ie_byte(@@H225_IE_DISPLAY, name)347end348349def create_ie_user_user(data)350create_ie_short(@@H225_IE_USER_USER, data)351end352353#354# This is ugly. Doing it properly requires a PER capable ASN.1 encoder, which is overkill for this task355#356def create_user_info(opts = {})357h323_id = opts[:h323_id]358vendor_id = opts[:vendor_id]359callee_host = opts[:callee_host]360callee_port = opts[:callee_port]361caller_host = opts[:caller_host]362caller_port = opts[:caller_port]363conf_guid = opts[:conf_guid]364call_guid = opts[:call_guid]365366buff = "\x05" # Protocol descriminator: X.208/X.209 coded user information367368buff << "\x20\xa8\x06\x00\x08\x91\x4a\x00\x06\x01\x40\x02"369370# H323-ID371buff << h323_id.unpack("C*").pack("n*")372373buff << "\x22\xc0\x09\x00\x00\x3d\x02\x00\x00\x00\x21"374375# VENDOR: 32 + 2 null bytes376buff << [vendor_id].pack("Z32") + "\x00\x00"377378buff << "\x00"379380# Remote IP + Remote Port381buff << (::Rex::Socket.addr_aton(callee_host) + [ callee_port.to_i ].pack("n"))382383buff << "\x00"384385# Conference GUID386buff << conf_guid387388buff << "\x00\xc5\x1d\x80\x04\x07\x00"389390# Local IP + Port391buff << (::Rex::Socket.addr_aton(caller_host) + [ caller_port.to_i ].pack("n"))392393buff << "\x11\x00"394395# Call GUID396buff << call_guid397398buff <<399"\x82\x49\x10\x47\x40\x00\x00\x06\x04\x01\x00\x4c\x10\xb5" +400"\x00\x00\x26\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31" +401"\x36\x30\x30\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62" +402"\x72\x3d\x6f\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80" +403"\x12\x1c\x40\x01\x00" +404Rex::Socket.addr_aton(caller_host) +405"\x13\xc6\x00" +406Rex::Socket.addr_aton(caller_host) +407"\x13\xc7\x90\x3c\x00\x00\x64\x0c\x10\xb5\x00\x00\x26\x25" +408"\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30\x30" +409"\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f\x66" +410"\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x0b\x0d\x40\x01" +411"\x00" +412Rex::Socket.addr_aton(caller_host) +413"\x13\xc7\x48\x31\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09" +414"\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20" +415"\x57\x69\x64\x65\x36\x80\x12\x1c\x40\x01\x00" +416Rex::Socket.addr_aton(caller_host) +417"\x13\xc6\x00" +418Rex::Socket.addr_aton(caller_host) +419"\x13\xc7\xa0\x26\x00\x00\x65\x0c\x10\x09\x00\x00\x3d\x0f" +420"\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65" +421"\x36\x80\x0b\x0d\x40\x01\x00" +422Rex::Socket.addr_aton(caller_host) +423"\x13\xc7\x50\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x60\x13" +424"\x80\x11\x1c\x00\x01\x00" +425Rex::Socket.addr_aton(caller_host) +426"\x13\xc6\x00" +427Rex::Socket.addr_aton(caller_host) +428"\x13\xc7\x13\x00\x00\x66\x0c\x60\x13\x80\x0b\x0d\x00\x01" +429"\x00" +430Rex::Socket.addr_aton(caller_host) +431"\x13\xc7\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x20\x13" +432"\x80\x11\x1c\x00\x01\x00" +433Rex::Socket.addr_aton(caller_host) +434"\x13\xc6\x00" +435Rex::Socket.addr_aton(caller_host) +436"\x13\xc7\x13\x00\x00\x67\x0c\x20\x13\x80\x0b\x0d\x00\x01" +437"\x00" +438Rex::Socket.addr_aton(caller_host) +439"\x13\xc7\x00\x23\x40\x00\x00\x06\x04\x01\x00\x48\x78\x00" +440"\x4a\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +441Rex::Socket.addr_aton(caller_host) +442"\x13\xc8\x00" +443Rex::Socket.addr_aton(caller_host) +444"\x13\xc9\x19\x00\x00\x68\x08\x78\x00\x4a\xff\x00\x80\x01" +445"\x00\x80\x0b\x0d\x00\x02\x00" +446Rex::Socket.addr_aton(caller_host) +447"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x68\x4a" +448"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +449Rex::Socket.addr_aton(caller_host) +450"\x13\xc8\x00" +451Rex::Socket.addr_aton(caller_host) +452"\x13\xc9\x18\x00\x00\x69\x08\x68\x4a\xff\x00\x80\x01\x00" +453"\x80\x0b\x0d\x00\x02\x00" +454Rex::Socket.addr_aton(caller_host) +455"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x70\x4a" +456"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +457Rex::Socket.addr_aton(caller_host) +458"\x13\xc8\x00" +459Rex::Socket.addr_aton(caller_host) +460"\x13\xc9\x18\x00\x00\x6a\x08\x70\x4a\xff\x00\x80\x01\x00" +461"\x80\x0b\x0d\x00\x02\x00" +462Rex::Socket.addr_aton(caller_host) +463"\x13\xc9\x00\x2c\x40\x00\x00\x06\x04\x01\x00\x48\xee\x00" +464"\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x17\x1c\x20\x02" +465"\x00" +466Rex::Socket.addr_aton(caller_host) +467"\x13\xc8\x00" +468Rex::Socket.addr_aton(caller_host) +469"\x13\xc9\x80\x04\x48\x08\x8d\x44\x22\x00\x00\x6b\x08\xee" +470"\x00\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x11\x0d\x20" +471"\x02\x00" +472Rex::Socket.addr_aton(caller_host) +473"\x13\xc9\x40\x00\x04\x48\x08\x8d\x44\x01\x00\x01\x00\x01" +474"\x00\x01\x00\x80\xfa\x02\x80\xef\x02\x70\x01\x06\x00\x08" +475"\x81\x75\x00\x0d\x80\x1a\x80\x01\xf4\x00\x01\x00\x00\x01" +476"\x00\x00\x01\x00\x04\x02\x05\x00\x48\x08\x8d\x44\x06\x60" +477"\x01\x00\x01\x80\x0b\x80\x00\x00\x20\x20\xb5\x00\x00\x26" +478"\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30" +479"\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f" +480"\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x00\x01\x20" +481"\x20\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73" +482"\x34\x20\x57\x69\x64\x65\x36\x80\x00\x02\x20\xc0\xef\x80" +483"\x00\x03\x20\x40\xef\x80\x00\x04\x08\xf0\x00\x4a\xff\x00" +484"\x80\x01\x00\x80\x00\x05\x08\xd0\x4a\xff\x00\x80\x01\x00" +485"\x80\x00\x06\x08\xe0\x4a\xff\x00\x80\x01\x00\x80\x00\x07" +486"\x09\xdc\x00\x00\x40\x9f\xff\x20\x50\x40\x01\x00\x80\x00" +487"\x08\x83\x01\x50\x80\x00\x09\x83\x01\x10\x80\x00\x0a\x83" +488"\x01\x40\x80\x00\x0b\x8a\x0c\x14\x0a\x30\x2d\x31\x36\x2c" +489"\x33\x32\x2c\x33\x36\x00\x80\x01\x03\x03\x00\x00\x00\x01" +490"\x00\x02\x00\x03\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00" +491"\x00\x08\x02\x00\x09\x00\x0a\x00\x0b\x07\x01\x00\x32\x80" +492"\x96\x61\x41\x02\x80\x01\x80"493494buff495end496497def create_user_release_info(call_guid)498"\x05" +499"\x25\x80\x06\x00\x08\x91\x4a\x00\x05\x01\x11\x00" +500call_guid +501"\x02\x80\x01\x00"502end503504def h323_release_call(opts = {})505caller_name = opts[:caller_name]506call_guid = opts[:call_guid]507508encap_tpkt(3,509encap_q225_release(510create_ie_display(caller_name) +511create_ie_user_user(512create_user_release_info(call_guid)513)514))515end516517def h323_setup_call(opts = {})518caller_name = opts[:caller_name]519h323_id = opts[:h323_id]520vendor_id = opts[:vendor_id]521callee_host = opts[:callee_host]522callee_port = opts[:callee_port]523caller_host = opts[:caller_host]524caller_port = opts[:caller_port]525conf_guid = opts[:conf_guid]526call_guid = opts[:call_guid]527528encap_tpkt(3,529encap_q225_setup(530create_ie_bearer_capability() +531create_ie_display(caller_name) +532create_ie_user_user(533create_user_info({534:h323_id => h323_id,535:vendor_id => vendor_id,536:callee_host => callee_host,537:callee_port => callee_port,538:caller_host => caller_host,539:caller_port => caller_port,540:conf_guid => conf_guid,541:call_guid => call_guid542})543)544))545end546end547548549