Prezi

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in the manual

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

PacketFu by Example

A PacketFu primer, presented at SharkFest 2011
by Tod Beardsley on 13 June 2011

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of PacketFu by Example

Interface Goals Conversational Interface Inline Docs Interactive Sensible Defaults PacketFu::Utils.whoami? TCPPacket.new >> Utils.whoami?
=> {:iface=>"eth0", :pcapfile=>"/tmp/out.pcap", :eth_saddr=>"00:26:22:96:0f:07", :eth_src=>"\x00&\"\x96\x0F\a", :ip_saddr=>"192.168.11.70", :ip_src=>3232238406, :ip_src_bin=>"\xC0\xA8\vF", :eth_dst=>"\x00\x1C\x10\xCCW\x8A", :eth_daddr=>"00:1c:10:cc:57:8a"} packetfu-shell.rb $ rvmsudo irb -r packetfu-shell.rb >> pkt = TCPPacket.new
=> [..packet dissection output...]
>> pkt.ip_saddr = "1.2.3.4"
=> "1.2.3.4"
>> pkt.ip_daddr = "10.20.30.40"
=> "10.20.30.40"
>> pkt.tcp_sport = 1025
=> 1025
>> pkt.tcp_dport = 80
=> 80
>> pkt.recalc
=> #<struct ...> Testing Strategies Tests as Examples with Test::Unit RSpec --format=documentation test$ rspec --format=documentation ethpacket_spec.rb

PacketFu::EthPacket when read from a pcap file
is a regular ethernet packet
should be an EthPacket kind of packet
should have a dest mac address
should have a source mac address
should have a payload in its first header
size
should == 78
an EthPacket's first header
should be 64 bytes
EthHeader struct members
members
should include :eth_dst
members
should include :eth_src
members
should include :eth_proto
members
should include :body
isn't a regular Ethernet packet
should not be an EthPacket

Finished in 0.01863 seconds
11 examples, 0 failures def test_tcp_option
t = TcpOption.new
assert_equal("\x00", t.to_s)
t = TcpOption.new(:kind => 2, :optlen => 4, :value => 1024)
assert_equal("\x02\x04\x04\x00", t.to_s)
t = TcpOption.new(:kind => 0xf0, :optlen => 6, :value => 1024)
assert_equal("\xf0\x06\x00\x00\x04\x00", t.to_s)
t = TcpOption.new(:kind => 0xf0, :optlen => 6, :value => "1024")
assert_equal("\xf0\x061024", t.to_s)
t = TcpOption.new(:kind => 0xf0, :optlen => 6, :value => nil)
assert_equal("\xf0\x06", t.to_s)
t = TcpOption.new(:kind => 0xf1, :optlen => 10, :value => "a1b2c3d4e5")
assert_equal("\xf1\x0aa1b2c3d4e5", t.to_s)
end Design Patterns Inheritance and Composition Delegation >> pkt.ip_saddr
=> "1.2.3.4" when /^([a-zA-Z0-9]+)_.+/
ptype = $1
if PacketFu.packet_prefixes.index(ptype)
self.instance_variable_get("@#{ptype}_header").send(sym,*args, &block)
else
super
end
end Down the stack with method_missing() >> pkt.ip_header.methods.include? :ip_saddr
=> true
>> pkt.ip_header.ip_saddr
=> "1.2.3.4"
>> pkt.ip_color
NoMethodError: undefined method `ip_color' for #<PacketFu::IPHeader...> Instance methods Uninstantiated classes and modules have methods, too >> ICMPPacket.layer
=> 3
>> ARPPacket.layer
=> 2
>> InvalidPacket.layer
=> 0 Get Started! TCPPacket < Packet @interface
@headers
@flavor #read()
#clone
#to_w()
...etc... #initialize()
TCPPacket.can_parse?()
#tcp_calc_sum
...etc... @eth_header
@ip_header
@tcp_header :eth_dst
:eth_src
:eth_proto
:body :ip_v
:ip_hl
...etc...
:body :tcp_src
:tcp_dst
...etc...
:body :oui
:nic :oui
:nic :value
:endian
:width
:default :b5 - :b0
:local
:multicast
:oui :n1
:n2
:n3 >> tcp_packet.headers.first.first.first[:oui].to_s(16)
=> "1c10" Goldilocks Introspection >> tcp_packet.inspect_style = :hex
=> :hex
>> tcp_packet
=> Eth|IP|TCP
00 1c 10 cc 57 8a 00 26 22 96 0f 07 08 00 45 00 ....W..&".....E.
00 14 e7 85 00 00 20 06 ff ff c0 a8 0b 46 00 00 ...... ......F..
00 00 f0 1a 00 00 c4 90 a3 ff 00 00 00 00 50 00 ..............P.
40 00 4b 5f 00 00 @.K_.. >> tcp_packet.inspect_style = :dissect
=> :dissect
>> tcp_packet
=> --EthHeader-------------------------------------------
eth_dst 00:1c:10:cc:57:8a PacketFu::EthMac
eth_src 00:26:22:96:0f:07 PacketFu::EthMac
eth_proto 0x0800 StructFu::Int16
--IPHeader--------------------------------------------
ip_v 4 Fixnum
ip_hl 5 Fixnum
ip_tos 0 StructFu::Int8
ip_len 20 StructFu::Int16
ip_id 0xe785 StructFu::Int16
ip_frag 0 StructFu::Int16
ip_ttl 32 StructFu::Int8
ip_proto 6 StructFu::Int8
ip_sum 0xffff StructFu::Int16
ip_src 192.168.11.70 PacketFu::Octets
ip_dst 0.0.0.0 PacketFu::Octets
--TCPHeader-------------------------------------------
tcp_src 61466 StructFu::Int16
tcp_dst 0 StructFu::Int16
tcp_seq 0xc490a3ff StructFu::Int32
tcp_ack 0x00000000 StructFu::Int32
tcp_hlen 5 PacketFu::TcpHlen
tcp_reserved 0 PacketFu::TcpReserved
tcp_ecn 0 PacketFu::TcpEcn
tcp_flags ...... PacketFu::TcpFlags
tcp_win 16384 StructFu::Int16
tcp_sum 0x4b5f StructFu::Int16
tcp_urg 0 StructFu::Int16
tcp_opts PacketFu::TcpOptions >> (PacketFu.methods - Object.methods).sort
=> [:add_packet_class, :at_least?, :binarize_version, :classes, :force_binary, :inspect_style, :inspect_style=, :newer_than?, :older_than?, :packet_classes, :packet_prefixes, :pcaprub_loaded?, :pcaprub_platform_require, :remove_packet_class, :require_protos, :version] "Hey, I need a new packet."

"Set the IP source address to 1.2.3.4."

"Set the dest address to 10.20.30.40"

"Set the TCP source port to 1025"

"Set the TCP dest port to 80"

"Recalculate the packet's checksum." Do not want Fun fact: actually pasting all this text into Prezi will crash Flash. Pass by Reference >> packet = PcapFile.read_packets("test/sample.pcap")[7]
>> packet.proto
=> ["Eth", "IP", "TCP"]
>> h_objs = packet.headers.map {|x| x.object_id}
=> [17557540, 17556784, 17554908]
=> packet.instance_variable_get("@ip_header")
>> ( returns an IPHeader Struct object )
>> packet.instance_variable_get("@ip_header").object_id
=> 17556784
>> h_objs.include? _
=> true
>> packet.instance_variable_get("@ip_header").body.class
=> PacketFu::TCPHeader
>> packet.instance_variable_get("@ip_header").body.object_id
=> 17554908
>> h_objs.include? _
=> true
>> packet.instance_variable_get("@eth_header").body.equal? packet.headers[1]
=> true Assignment might be tricky >> new_packet = packet
>> new_packet.ip_saddr = "1.2.3.4"
=> "1.2.3.4"
>> packet.ip_saddr
=> "1.2.3.4"
>> new_packet = packet.dup
>> new_packet.ip_saddr = "10.20.30.40"
=> "10.20.30.40"
>> packet.ip_saddr
=> "10.20.30.40"
>> new_packet = packet.clone
>> new_packet.ip_saddr = "2.4.6.8"
=> "2.4.6.8"
>> packet.ip_saddr
=> "10.20.30.40" Instantiation idioms # Post instantiation
tcp1 = TCPPacket.new
tcp1.eth_saddr = "00:11:22:33:44:55"
tcp1.eth_daddr = "de:ad:be:ef:ca:fe" Rule of Thumb:

If you're templating packets to throw on the wire, use shallow copies (dup). If you're going to save and reuse them, use deep copies (clone). # Passing in pre-configured headers:
ip_header = IPHeader.new(
:ip_src => "\x01\x02\x03\x04",
:ip_dst => "\x05\x06\x07\x08")
tcp5 = TCPPacket.new(:ip => ip_header) Capture.new My interface is 'eth0'
Start capturing packets.
For each packet,
parse it,
skip to the next one if it's from me,
otherwise get some data about it and
print the data to the screen. def sniff(iface)
iface ||= "eth0"
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[: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 >> Utils.ifconfig("vmnet8")
=> {:iface=>"vmnet8", :eth_saddr=>"00:50:56:c0:00:08", :eth_src=>"\x00PV\xC0\x00\b", :ip_saddr=>"192.168.145.1", :ip_src=>"\xC0\xA8\x91\x01", :ip4_obj=>#<IPAddr: IPv4:192.168.145.0/255.255.255.0>, :ip6_saddr=>"fe80::250:56ff:fec0:8/64", :ip6_obj=>#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:0000:0000:0000:0000>} PacketFu::Utils.ifconfig 145.58.33.95 -> 192.168.11.70 1514 TCP
212.233.158.76 -> 192.168.11.70 110 UDP
88.174.164.147 -> 192.168.11.70 110 UDP
145.58.33.95 -> 192.168.11.70 1514 TCP
145.58.33.95 -> 192.168.11.70 1514 TCP
145.58.33.95 -> 192.168.11.70 1514 TCP
145.58.33.95 -> 192.168.11.70 1514 TCP
8.8.8.8 -> 192.168.11.70 143 UDP
41.237.73.186 -> 192.168.11.70 60 TCP
145.58.33.95 -> 192.168.11.70 1514 TCP
145.58.33.95 -> 192.168.11.70 1514 TCP
8.8.8.8 -> 192.168.11.70 143 UDP
8.8.8.8 -> 192.168.11.70 128 UDP
8.8.8.8 -> 192.168.11.70 187 UDP
24.45.247.232 -> 192.168.11.70 70 TCP Development with RVM Gem installation $ gem install packetfu
$ gem install pcaprub $ gem install packetfu --pre More stable: More recent: (or just use --development) Build from source svn checkout http://packetfu.googlecode.com/svn/trunk/packetfu
git clone https://github.com/todb/packetfu.git $ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
$ rvm install 1.8.7
$ rvm use 1.8.7 --default
Using /home/todb/.rvm/gems/ruby-1.8.7-p334
$ rvm install 1.9.1-p378
$ rvm use 1.9.1-p378--default More information Channel #packetfu on Freenode IRC packetfu/examples (from source or your gemdir) E-mail me! Packet#to_w() >> p = IPPacket.new
>> p.ip_id = 0xbabe
>> p.ip_saddr = "10.20.30.40"
>> p.ip_daddr = "10.1.2.3"
>> p.payload = "Here's a packet. It's not much, but it's mine."
>> p.recalc
>> 3.times { p.to_w("eth0") }
=> 3 "sudo make me a packet"

"Set some fields."

"Recalculate the checksum."

"Put it on the wire three times." PacketFu
by
Example <todb@planb-security.net> # Based on the host configuration:
tcp2 = TCPPacket.new(:config => Utils.whoami?)
tcp3 = TCPPacket.new(:config => Utils.ifconfig)
tcp4 = TCPPacket.new(:config => {:ip_saddr => "1.2.3.4"}) # Manual # Borrowing another packet's headers:
tcp6 = TCPPacket.new(
:eth => tcp1.eth_header,
:ip => tcp5.ip_header.clone) #rvm on Freenode
See the full transcript