Thomas Whitton
2013/01/10
The idea behind using scripting to analyse and modify packet data is that tools can created for a very specific task that other people may not have thought up yet.
We can't always rely on someone having the exact same problem and creating an opensource tool for the job.
And with using a scripting language the tool can probably be a couple of lines of code, plus everyone knows at least one scripting language (right?).
For 99% of your packet analysis Wireshark does a pretty damn good job
A couple of cases in which it might be preferable to use a scripting language:
There are some cool tools available for packet modification, however, none are feature rich and as widely used as wireshark.
They are all for very specific tasks, where as we might like to do something very different.
import dpkt
from dpkt.asn1 import decode
from dpkt.ip import IP
from dpkt.icmp import ICMP
from ipaddr import *
def pcap_test():
with open("test.pcap") as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
if type(eth.data) == dpkt.ip.IP:
src = IPAddress(Bytes(ip.src))
dst = IPAddress(Bytes(ip.dst))
print str(src) + " -> " + str(dst)
tcp = ip.data
port = tcp.dport
print "%s, %d" % (port, len(tcp.data))
if tcp.dport == 80 and len(tcp.data) > 0:
http = dpkt.http.Request(tcp.data)
def creation_test():
ip = IP(src=v4_int_to_packed(IPAddress("5.6.7.8")._ip), dst=v4_int_to_packed(IPAddress("1.2.3.4")._ip), p=1)
print ip.v # 4
print ip.src # '\x01\x02\x03\x04'
print ip.data # ''
icmp = ICMP(type=8, data=ICMP.Echo(id=123, seq=1, data='foobar'))
print icmp # ICMP(type=8, data=Echo(id=123, seq=1, data='foobar'))
print len(icmp) # 15
ip.data = icmp
ip.len += len(ip.data)
print ip
# IP(src='\x01\x02\x03\x04', dst='\x05\x06\x07\x08', len=34, p=1, data=ICMP(type=8, data=Echo(id=123, seq=1, data='foobar')))
pkt = str(ip)
print pkt # 'E\x00\x00"\x00\x00\x00\x00@\x01j\xc8\x01\x02\x03\x04\x05\x06\x07\x08\x08\x00\xc0?\x00{\x00\x01foobar'
print IP(pkt) # IP(src='\x01\x02\x03\x04', dst='\x05\x06\x07\x08', sum=27336, len=34, p=1, data=ICMP(sum=49215, type=8, data=Echo(id=123, seq=1, data='foobar')))
def asn1_test():
s = '0\x82\x02Q\x02\x01\x0bc\x82\x02J\x04xcn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US\n\x01\x00\n\x01\x03\x02\x01\x00\x02\x01\x00\x01\x01\x00\x87\x0bobjectclass0\x82\x01\xb0\x04\rmemberOfGroup\x04\x03acl\x04\x02cn\x04\x05title\x04\rpostalAddress\x05\x0ftelephoneNumber\x04\x04mail\x04\x06member\x04\thomePhone\x04\x11homePostalAddress\x04\x0bobjectClass\x04\x0bdescription\x04\x18facsimileTelephoneNumber\x04\x05pager\x04\x03uid\x04\x0cuserPassword\x04\x08joinable\x04\x10associatedDomain\x04\x05owner\x04\x0erfc822ErrorsTo\x04\x08ErrorsTo\x04\x10rfc822RequestsTo\x04\nRequestsTo\x04\tmoderator\x04\nlabeledURL\x04\nonVacation\x04\x0fvacationMessage\x04\x05drink\x04\x0elastModifiedBy\x04\x10lastModifiedTime\x04\rmodifiersname\x04\x0fmodifytimestamp\x04\x0ccreatorsname\x04\x0fcreatetimestamp'
print decode(s) # [(48, [(2, 11), (99, [(4, 'cn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US'), (10, '\x00'), (10, '\x03'), (2, 0), (2, 0), (1, '\x00'), (135, 'objectclass'), (48, [(4, 'memberOfGroup'), (4, 'acl'), (4, 'cn'), (4, 'title'), (4, 'postalAddress'), (4, 'telephoneNumber'), (4, 'mail'), (4, 'member'), (4, 'homePhone'), (4, 'homePostalAddress'), (4, 'objectClass'), (4, 'description'), (4, 'facsimileTelephoneNumber'), (4, 'pager'), (4, 'uid'), (4, 'userPassword'), (4, 'joinable'), (4, 'associatedDomain'), (4, 'owner'), (4, 'rfc822ErrorsTo'), (4, 'ErrorsTo'), (4, 'rfc822RequestsTo'), (4, 'RequestsTo'), (4, 'moderator'), (4, 'labeledURL'), (4, 'onVacation'), (4, 'vacationMessage'), (4, 'drink'), (4, 'lastModifiedBy'), (4, 'lastModifiedTime'), (4, 'modifiersname'), (4, 'modifytimestamp'), (4, 'creatorsname'), (4, 'createtimestamp')])])])]
from scapy.all import *
def pcap_test():
pkts = rdpcap("test.pcap")
pkts[0][IP].src = '1.8.3.5'
del(pkts[0][TCP].chksum)
del(pkts[0][IP].chksum)
pkts[0].show2()
wrpcap("result.pcap", pkts[0])
def show_test():
# requires root privelages
pkts = sniff(iface="wlan0", filter="icmp", count=10)
print len(pkts)
pkts[0].show()
def sniff_test():
# requires root privelages
# same filter expression used by wireshark capture filters and tcpdump
pkts = sniff(iface="wlan0", filter="icmp", count=10)
pkts = sniff(iface="wlan0", filter="tcp and host 192.168.1.8", count=10, prn=pkt_print)
def pkt_print(pkt):
hexdump(pkt)
print pkt[IP].src + "->" + pkt[IP].dst
def create_test():
a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n"
a=Ether()/IP(dst="www.slashdot.org")/TCP()/Raw(load="x")
def send_test():
send(IP(dst="1.2.3.4")/ICMP())
sendp(rdpcap("test.pcap")) # tcpreplay
# inter is sleep time between packets and loop > 0 means carry on until keyboard interupt
sendp("I'm travelling on Ethernet", iface="eth1", loop=1, inter=0.2)
# fuzz randomises default values
send(IP(dst="target")/fuzz(UDP()/NTP(version=4)),loop=1)
def sending_and_receiving_test():
p1=sr1(IP(dst="www.slashdot.org")/ICMP()/"XXXXXXXXXXX")
p=sr(IP(dst="www.slashdot.org")/ICMP()/"XXXXXXXXXXX")
def filter_test():
pkts = rdpcap("test.pcap")
pkts.filter(lambda x: TCP in x)
require 'packetfu'
include PacketFu
iface = "wlan0"
def sniff_test(iface)
# requires root privelages
cap = Capture.new(:iface => iface, :start => true)
cap.stream.each do |p|
pkt = Packet.parse p
if pkt.is_ip?
next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
puts "%-15s -> %-15s %-4d %s" % packet_info
end
end
end
def creation_test()
pkt = TCPPacket.new
pkt.ip_saddr = "1.2.3.4"
pkt.tcp_spot = "80"
pkt.recalc
end
def send_test()
pkt = IPPacket.new
pkt.ip_id = 0xbabe
pkt.ip_saddr = "10.20.30.40"
pkt.ip_daddr = "10.1.2.3"
pkt.payload = "hello"
pkt.recalc
3.times { pkt.to_w("wlan0") }
end
def hex_test()
pkt = TCPPacket.new
pkt.ip_saddr = "1.2.3.4"
pkt.tcp_sport = "80"
pkt.recalc
pkt.tcp_recalc
# prints out the hex of the packet
puts pkt.inspect_hex
end
def read_and_write_pcap_test()
# use as singleton
pfile = PcapFile.new
pkts = pfile.read_packets("test.pcap")
pfile.array_to_file(:filename => "result.pcap", :array => pkts)
end