#!/usr/bin/env ruby # aim.rb # Extracts AIM message data from a pcap file (evidence.pcap) and prints to screen # By: Aaron Allen # August 25, 2009 require 'pcaplet' # Open up our pcap file $evidence = Pcaplet.new('-r evidence.pcap') # Takes a string of binary data from a reassembled AIM packet and parses out the relevant screenname and msg text def packetParse p # Check channel value to ensure we are dealing with an IM message if p[25..25].unpack("C")[0] == 1 # Find the length of the screenname snLength = p[26..26].unpack("c") # Find the screenname sn = p[27..(27 + snLength[0])] # Check to see if we are receiving a message if p[9..9].unpack("c")[0] == 7 # The receiving message will always be contained 26 bytes after the screenname msgStart = 27 + snLength[0] + 26 # We must be sending a message elsif p[9..9].unpack("c")[0] == 6 # The packet contains the recipients screenname, so let's just rename the sender to 'sender' sn = "Sender" msgStart = 27 + snLength[0] + 20 # This isn't an IM packet, so exit else return nil end # Pull the message out of the packet data msg = p[msgStart..(p.length-4)] # Strip out any unprintable binary data msg = msg.gsub(/[^[:print:]]/, '') return [sn, msg] end end # Look for packets that are sent to the AIM server $send_filter = Pcap::Filter.new('dst host 64.12.24.50', $evidence.capture) # Look for packets coming from the AIM server $recv_filter = Pcap::Filter.new('src host 64.12.24.50', $evidence.capture) # add all the filters $evidence.add_filter($send_filter | $recv_filter) for p in $evidence if p.tcp_data # Look for the flapHeader startMarker and frameType of 2 if (p.tcp_data[0..0] == "*") and (p.tcp_data[1..1].unpack("C")[0] == 2) # Get payloadLength from header data and check to see if the current packet contains entire payload payloadLength = p.tcp_data[5..5].unpack("C")[0] if p.tcp_data.length >= payloadLength sn, msg = packetParse p.tcp_data else # The remainder of the payload is in the next packet, put data from this packet in string 'reassembled' reassembled = p.tcp_data end # The current packet is a continuation of an AIM payload, proceed with reassembly elsif reassembled # Make sure we don't select data from a new AIM payload in the same packet reassembled += p.tcp_data[/.+[\*$]/] sn, msg = packetParse reassembled reassembled = nil end # Print the message puts "From #{sn}: #{msg}" if sn and msg end end