#!/usr/bin/env ruby
# this line imports the libpcap ruby bindings
require 'pcaplet'
# create a sniffer that grabs the first 1500 bytes of each packet
$network = Pcaplet.new('-s 1500')
def has_nonprint? n
# figure out if the string has non-printable characters
n.each_byte {|x| return false if x < 32 or x > 126}
end
def aim_msg_parse p
# figure out how many text characters are in the screen name
name_length = p.tcp_data[26..26].unpack("c")
# extract the screen name from the packet
name = p.tcp_data[27..(27 + name_length[0])]
# filter out all other text
p.tcp_data[85..-1][/<[^>]+>(.*)<\//]
msg = $1.gsub(/<[^>]+>/,"").strip
# make sure that it is an actual message and then return it
return [name, msg] if msg and not has_nonprint?(name) and
name =~ /^[a-zA-Z]/ and not name.include?("/")
# if it isn't really a text message, return nothing
nil
rescue
end
# make a filter to capture all packets sent to port 80 on a remote server
$www_filter = Pcap::Filter.new('tcp and dst port 80', $network.capture)
# make a filter to capture all packets sent from port 5190 on a remote server
$aim_recv_filter = Pcap::Filter.new('tcp and src port 5190', $network.capture)
# make a filter to capture all packets sent to port 5190 on a remote server
$aim_send_filter = Pcap::Filter.new('tcp and dst port 5190', $network.capture)
# add all the filters
$network.add_filter($aim_recv_filter | $aim_send_filter | $www_filter)
for p in $network
# if the packet matches the www filter and the regexp...
if $www_filter =~ p and p.tcp_data =~ /GET(.*)HTTP.*Host:([^\r\n]*)/xm
# print the local IP of the requestor and the requested URL
puts "#{p.src} - http://#{$2.strip}#{$1.strip}"
# if the packet matches the incoming AIM filter...
elsif $aim_recv_filter =~ p
# parse the packet and extract the sn/message
name, msg = aim_msg_parse p
# display the local IP, the screen name of the user and the message
puts "(<-) <#{p.dst}> from #{name}: #{msg}" if name and msg
# if the packet matches the outgoing AIM filter...
elsif $aim_send_filter =~ p
# parse the packet and extract the sn/message
name, msg = aim_msg_parse p
# display the local IP, the screen name of the user and the message
puts "(->) <#{p.src}> to #{name}: #{msg}" if name and msg
end
end