Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/scanner/h323/h323_version.rb
Views: 11783
##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])22end2324def run_host(ip)2526remote_display = nil27remote_product_id = nil28remote_version_id = nil29remote_vendor_id = nil30remote_protocol = nil3132begin3334# Wrap this in a timeout to prevent dead services from35# hanging this thread.36Timeout.timeout( call_timeout) do3738connect3940caller_name = "SYSTEM\x00"41h323_id = Rex::Text.rand_text_alpha(3)42vendor_id = Rex::Text.rand_text_alpha(32)43caller_host = Rex::Socket.source_address( ip )44caller_port = rand( 32768 ) + 3000045callee_host = rhost46callee_port = rport47conf_guid = Rex::Text.rand_text(16)48call_guid = Rex::Text.rand_text(16)4950pkt_setup = h323_setup_call({51:caller_name => caller_name,52:h323_id => h323_id,53:vendor_id => vendor_id,54:callee_host => callee_host,55:callee_port => callee_port,56:caller_host => caller_host,57:caller_port => caller_port,58:conf_guid => conf_guid,59:call_guid => call_guid60})6162res = sock.put(pkt_setup) rescue nil63if not res64disconnect65return66end6768cnt = 069while( true )70info = read_packet71break if not info7273# The remote side of the call disconnected us74break if info[:type] == @@H323_STATUS_RELEASE_COMPLETE7576remote_display = info[40].strip if info[40]77remote_product_id = info[:product_id].strip if info[:product_id]78remote_version_id = info[:version_id].strip if info[:version_id]79remote_protocol = info[:protocol_version].strip if info[:protocol_version]8081if info[:vendor_id] and [nil, "Unknown"].include?( remote_vendor_id )82remote_vendor_id = info[:vendor_id].strip83end8485# Diagnostics86# print_status("Host: #{rhost}:#{rport} => #{info.inspect}")8788# The remote side of the call was connected (kill it)89break if info[:type] == @@H323_STATUS_CONNECT9091# Exit if we already received 5 packets from the server92break if (cnt +=1) > 59394end9596# Make sure the call was shut down cleanly97pkt_release = h323_release_call({98:caller_name => caller_name,99:call_guid => call_guid100})101sock.put(pkt_release) rescue nil102103# End timeout block104end105106rescue ::Timeout::Error107rescue ::Interrupt108raise $!109rescue ::Rex::ConnectionError, ::IOError, ::Errno::ECONNRESET, ::Errno::ENOPROTOOPT110rescue ::Exception111print_error("#{rhost}:#{rport} #{$!.class} #{$!} #{$!.backtrace}")112ensure113disconnect114end115116if remote_vendor_id117remote_product_id = remote_product_id.to_s.gsub(/[^\x20-\x7e]/, '')118remote_version_id = remote_version_id.to_s.gsub(/[^\x20-\x7e]/, '')119120banner = "Protocol: #{ remote_protocol } VendorID: #{ remote_vendor_id } "121122if remote_version_id and remote_version_id.length > 0123banner << "VersionID: #{ remote_version_id } "124end125126if remote_product_id and remote_product_id.length > 0127banner << "ProductID: #{ remote_product_id } "128end129130if remote_display and remote_display.length > 0131remote_display = remote_display.to_s.gsub(/[^\x20-\x7e]/, '')132banner << "DisplayName: #{ remote_display }"133end134135print_good("#{rhost}:#{rport} #{banner}")136report_service(:host => rhost, :port => rport, :name => "h323", :info => banner)137end138139end140141def read_packet142begin143::Timeout.timeout( read_timeout ) do144ver = sock.read(2)145return if not (ver and ver == "\x03\x00")146147bin = sock.read(2)148return if not bin149150len = [ bin.unpack("n")[0] - 4, 0 ].max151return if len == 0152153bin = sock.read(len)154return if not bin155156f_desc, cref_len = bin.unpack("CC")157cref_val = bin[2, cref_len]158f_type = bin[2 + cref_len, 1].unpack("C")[0]159160return { :type => f_type, :call_ref => cref_val }.merge( read_ies(f_type, bin[ 2 + cref_len + 1, bin.length] ) )161end162rescue ::Timeout::Error163end164nil165end166167def read_ies(mtype, data)168r = { }169i = 0170171while( i < (data.length - 1) )172ie_type = data[i, 1].unpack("C")[0]173break if not ie_type174175ie_len = 0176ie_data = ""177178case ie_type179when @@H225_IE_USER_USER180ie_len = data[i+1, 2].unpack("n")[0]181break if not ie_len182183ie_data = data[i+3, ie_len]184break if not ie_data185186i = i + 3 + ie_len187else188ie_len = data[i+1, 1].unpack("C")[0]189break if not ie_len190191ie_data = data[i+2, ie_len]192break if not ie_data193194i = i + 2 + ie_len195end196197r[ ie_type ] = ie_data198199if ie_type == @@H225_IE_USER_USER200r.merge!( ( read_user_user(mtype, ie_data) rescue {} ) )201end202end203r204end205206207# This provides a weak method of decoding USER-USER PDUs. These are208# actually PER-encoded ASN.1, but we take a few shortcuts since PER209# encoding is such a pain.210def read_user_user(mtype, data)211r = {}212213# Identify the embedded version (2/3/4/5/6 commonly found)214i = data.index("\x00\x08\x91\x4a\x00")215return r if not i216217# Store the protocol version218pver = data[i + 5, 1].unpack("C")[0]219220r[:protocol_version] = pver.to_s221222# Bump the index over the version223i+= 6224225# print_line( Rex::Text.to_hex_dump( data[i, 32] ) )226227# Set a placeholder VendorID so this system will be reported228r[:vendor_id] = "Unknown"229230# We use the version offset to identify the destination block location231# This changes slightly based on the type of packet we receive232case mtype233when @@H323_STATUS_ALERTING, @@H323_STATUS_PROCEEDING234235if pver == 2 and data[i, 2] == "\x20\x00"236r[ :vendor_id ] = "0x%.8x" % ( data[i + 2, 4].unpack("N")[0] rescue 0 )237return r238end239240# Find the offset to the VendorID241if data[i + 1, 1] != "\xc0"242i+= 7243end244245# Stop processing if we can't identify a VendorID246return r if data[i + 1, 1] != "\xc0"247248# Otherwise just add 2 to the offset of the version249i += 2250251when @@H323_STATUS_CONNECT252253# Bail early in some corner cases254return r if data[i, 1] == "\x00"255256# Find the offset to the VendorID257if data[i + 1, 1] != "\xc0"258i+= 7259end260261# Stop processing if we can't identify a VendorID262return r if data[i + 1, 1] != "\xc0"263264i += 2265266return r267else268return r269end270271# Extract the manufacturer ID272r[ :vendor_id ] = "0x%.8x" % ( data[i, 4].unpack("N")[0] rescue 0 )273i+= 4274275# No Product ID / Version ID in versions less than 3 (unless special cased above)276return r if pver < 3277278# Get the product_id length (-1)279product_id_length = data[i, 1].unpack("C")[0] + 1280i+= 1281282# Extract the product ID283r[ :product_id ] = data[i, product_id_length]284i+= product_id_length285286# Get the version ID length (-1)287version_id_length = data[i, 1].unpack("C")[0] + 1288i+= 1289290# Extract the version ID291r[ :version_id ] = data[i, version_id_length]292293# Thats it for now294295r296end297298def read_timeout29910300end301302def call_timeout30330304end305306307@@H225_IE_BEARER_CAP = 0x04308@@H225_IE_DISPLAY = 0x28309@@H225_IE_USER_USER = 0x7e # Yes, really User-user310311312@@H323_STATUS_ALERTING = 0x01313@@H323_STATUS_PROCEEDING = 0x02314@@H323_STATUS_SETUP = 0x05315@@H323_STATUS_SETUP_ACK = 0x0D316@@H323_STATUS_CONNECT = 0x07317@@H323_STATUS_RELEASE_COMPLETE = 0x5a318@@H323_STATUS_FACILITY = 0x62319320321def encap_tpkt(ver,data)322[ ver, 0, data.length + 4 ].pack("CCn") + data323end324325def encap_q225(desc, cref_value, msg_type, data)326[ desc, cref_value.length, cref_value, msg_type].pack("CCA*C") + data327end328329def encap_q225_standard(msg_type, data)330encap_q225(0x08, [0x733f].pack("n"), msg_type, data)331end332333def encap_q225_setup(data)334encap_q225_standard(0x05, data)335end336337def encap_q225_release(data)338encap_q225_standard(0x5a, data)339end340341def create_ie_byte(ie_type, data)342[ie_type, data.length].pack("CC") + data343end344345def create_ie_short(ie_type, data)346[ie_type, data.length].pack("Cn") + data347end348349def create_ie_bearer_capability(cap = 0x00038893)350create_ie_byte( @@H225_IE_BEARER_CAP, [cap].pack("N")[0,3] )351end352353def create_ie_display(name = "DEBUG\x00")354create_ie_byte( @@H225_IE_DISPLAY, name )355end356357def create_ie_user_user(data)358create_ie_short( @@H225_IE_USER_USER, data )359end360361#362# This is ugly. Doing it properly requires a PER capable ASN.1 encoder, which is overkill for this task363#364def create_user_info(opts = {})365h323_id = opts[:h323_id]366vendor_id = opts[:vendor_id]367callee_host = opts[:callee_host]368callee_port = opts[:callee_port]369caller_host = opts[:caller_host]370caller_port = opts[:caller_port]371conf_guid = opts[:conf_guid]372call_guid = opts[:call_guid]373374buff = "\x05" # Protocol descriminator: X.208/X.209 coded user information375376buff << "\x20\xa8\x06\x00\x08\x91\x4a\x00\x06\x01\x40\x02"377378# H323-ID379buff << h323_id.unpack("C*").pack("n*")380381buff << "\x22\xc0\x09\x00\x00\x3d\x02\x00\x00\x00\x21"382383# VENDOR: 32 + 2 null bytes384buff << [vendor_id].pack("Z32") + "\x00\x00"385386buff << "\x00"387388# Remote IP + Remote Port389buff << ( ::Rex::Socket.addr_aton( callee_host ) + [ callee_port.to_i ].pack("n") )390391buff << "\x00"392393# Conference GUID394buff << conf_guid395396buff << "\x00\xc5\x1d\x80\x04\x07\x00"397398# Local IP + Port399buff << ( ::Rex::Socket.addr_aton( caller_host ) + [ caller_port.to_i ].pack("n") )400401buff << "\x11\x00"402403# Call GUID404buff << call_guid405406buff <<407"\x82\x49\x10\x47\x40\x00\x00\x06\x04\x01\x00\x4c\x10\xb5" +408"\x00\x00\x26\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31" +409"\x36\x30\x30\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62" +410"\x72\x3d\x6f\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80" +411"\x12\x1c\x40\x01\x00" +412413Rex::Socket.addr_aton( caller_host ) +414415"\x13\xc6\x00" +416417Rex::Socket.addr_aton( caller_host ) +418419"\x13\xc7\x90\x3c\x00\x00\x64\x0c\x10\xb5\x00\x00\x26\x25" +420"\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30\x30" +421"\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f\x66" +422"\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x0b\x0d\x40\x01" +423"\x00" +424425Rex::Socket.addr_aton( caller_host ) +426427"\x13\xc7\x48\x31\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09" +428"\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20" +429"\x57\x69\x64\x65\x36\x80\x12\x1c\x40\x01\x00" +430431Rex::Socket.addr_aton( caller_host ) +432433"\x13\xc6\x00" +434435Rex::Socket.addr_aton( caller_host ) +436437"\x13\xc7\xa0\x26\x00\x00\x65\x0c\x10\x09\x00\x00\x3d\x0f" +438"\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65" +439"\x36\x80\x0b\x0d\x40\x01\x00" +440441Rex::Socket.addr_aton( caller_host ) +442443"\x13\xc7\x50\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x60\x13" +444"\x80\x11\x1c\x00\x01\x00" +445446Rex::Socket.addr_aton( caller_host ) +447448"\x13\xc6\x00" +449450Rex::Socket.addr_aton( caller_host ) +451452"\x13\xc7\x13\x00\x00\x66\x0c\x60\x13\x80\x0b\x0d\x00\x01" +453"\x00" +454455Rex::Socket.addr_aton( caller_host ) +456457"\x13\xc7\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x20\x13" +458"\x80\x11\x1c\x00\x01\x00" +459460Rex::Socket.addr_aton( caller_host ) +461462"\x13\xc6\x00" +463464Rex::Socket.addr_aton( caller_host ) +465466"\x13\xc7\x13\x00\x00\x67\x0c\x20\x13\x80\x0b\x0d\x00\x01" +467"\x00" +468469Rex::Socket.addr_aton( caller_host ) +470471"\x13\xc7\x00\x23\x40\x00\x00\x06\x04\x01\x00\x48\x78\x00" +472"\x4a\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +473474Rex::Socket.addr_aton( caller_host ) +475476"\x13\xc8\x00" +477478Rex::Socket.addr_aton( caller_host ) +479480"\x13\xc9\x19\x00\x00\x68\x08\x78\x00\x4a\xff\x00\x80\x01" +481"\x00\x80\x0b\x0d\x00\x02\x00" +482483Rex::Socket.addr_aton( caller_host ) +484485"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x68\x4a" +486"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +487488Rex::Socket.addr_aton( caller_host ) +489490"\x13\xc8\x00" +491492Rex::Socket.addr_aton( caller_host ) +493494"\x13\xc9\x18\x00\x00\x69\x08\x68\x4a\xff\x00\x80\x01\x00" +495"\x80\x0b\x0d\x00\x02\x00" +496497Rex::Socket.addr_aton( caller_host ) +498499"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x70\x4a" +500"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +501502Rex::Socket.addr_aton( caller_host ) +503504"\x13\xc8\x00" +505506Rex::Socket.addr_aton( caller_host ) +507508"\x13\xc9\x18\x00\x00\x6a\x08\x70\x4a\xff\x00\x80\x01\x00" +509"\x80\x0b\x0d\x00\x02\x00" +510511Rex::Socket.addr_aton( caller_host ) +512513"\x13\xc9\x00\x2c\x40\x00\x00\x06\x04\x01\x00\x48\xee\x00" +514"\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x17\x1c\x20\x02" +515"\x00" +516517Rex::Socket.addr_aton( caller_host ) +518519"\x13\xc8\x00" +520521Rex::Socket.addr_aton( caller_host ) +522523"\x13\xc9\x80\x04\x48\x08\x8d\x44\x22\x00\x00\x6b\x08\xee" +524"\x00\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x11\x0d\x20" +525"\x02\x00" +526527Rex::Socket.addr_aton( caller_host ) +528529"\x13\xc9\x40\x00\x04\x48\x08\x8d\x44\x01\x00\x01\x00\x01" +530"\x00\x01\x00\x80\xfa\x02\x80\xef\x02\x70\x01\x06\x00\x08" +531"\x81\x75\x00\x0d\x80\x1a\x80\x01\xf4\x00\x01\x00\x00\x01" +532"\x00\x00\x01\x00\x04\x02\x05\x00\x48\x08\x8d\x44\x06\x60" +533"\x01\x00\x01\x80\x0b\x80\x00\x00\x20\x20\xb5\x00\x00\x26" +534"\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30" +535"\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f" +536"\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x00\x01\x20" +537"\x20\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73" +538"\x34\x20\x57\x69\x64\x65\x36\x80\x00\x02\x20\xc0\xef\x80" +539"\x00\x03\x20\x40\xef\x80\x00\x04\x08\xf0\x00\x4a\xff\x00" +540"\x80\x01\x00\x80\x00\x05\x08\xd0\x4a\xff\x00\x80\x01\x00" +541"\x80\x00\x06\x08\xe0\x4a\xff\x00\x80\x01\x00\x80\x00\x07" +542"\x09\xdc\x00\x00\x40\x9f\xff\x20\x50\x40\x01\x00\x80\x00" +543"\x08\x83\x01\x50\x80\x00\x09\x83\x01\x10\x80\x00\x0a\x83" +544"\x01\x40\x80\x00\x0b\x8a\x0c\x14\x0a\x30\x2d\x31\x36\x2c" +545"\x33\x32\x2c\x33\x36\x00\x80\x01\x03\x03\x00\x00\x00\x01" +546"\x00\x02\x00\x03\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00" +547"\x00\x08\x02\x00\x09\x00\x0a\x00\x0b\x07\x01\x00\x32\x80" +548"\x96\x61\x41\x02\x80\x01\x80"549550buff551end552553def create_user_release_info(call_guid)554"\x05" +555"\x25\x80\x06\x00\x08\x91\x4a\x00\x05\x01\x11\x00" +556call_guid +557"\x02\x80\x01\x00"558end559560def h323_release_call(opts = {})561caller_name = opts[:caller_name]562call_guid = opts[:call_guid]563564encap_tpkt(3,565encap_q225_release(566create_ie_display(caller_name) +567create_ie_user_user(568create_user_release_info(call_guid )569)570)571)572end573574def h323_setup_call(opts = {})575caller_name = opts[:caller_name]576h323_id = opts[:h323_id]577vendor_id = opts[:vendor_id]578callee_host = opts[:callee_host]579callee_port = opts[:callee_port]580caller_host = opts[:caller_host]581caller_port = opts[:caller_port]582conf_guid = opts[:conf_guid]583call_guid = opts[:call_guid]584585encap_tpkt(3,586encap_q225_setup(587create_ie_bearer_capability() +588create_ie_display(caller_name) +589create_ie_user_user(590create_user_info({591:h323_id => h323_id,592:vendor_id => vendor_id,593:callee_host => callee_host,594:callee_port => callee_port,595:caller_host => caller_host,596:caller_port => caller_port,597:conf_guid => conf_guid,598:call_guid => call_guid599})600)601)602)603end604end605606607