packetfu 1.0.4.pre → 1.0.5.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/examples/new-simple-stats.rb +1 -0
- data/lib/packetfu.rb +1 -3
- data/lib/packetfu/packet.rb +79 -90
- data/lib/packetfu/pcap.rb +87 -88
- data/test/icmp_test.pcap +0 -0
- data/test/ip_test.pcap +0 -0
- data/test/tcp_test.pcap +0 -0
- data/test/udp_test.pcap +0 -0
- metadata +10 -22
data/.document
CHANGED
data/lib/packetfu.rb
CHANGED
data/lib/packetfu/packet.rb
CHANGED
@@ -9,6 +9,7 @@ module PacketFu
|
|
9
9
|
attr_reader :flavor # Packet Headers are responsible for their own specific flavor methods.
|
10
10
|
attr_accessor :headers # All packets have a header collection, useful for determining protocol trees.
|
11
11
|
attr_accessor :iface # Default inferface to send packets to
|
12
|
+
attr_accessor :inspect_style # Default is :dissect, can also be :hex or :default
|
12
13
|
|
13
14
|
# Register subclasses in PacketFu.packet_class to do all kinds of neat things
|
14
15
|
# that obviates those long if/else trees for parsing. It's pretty sweet.
|
@@ -293,34 +294,17 @@ module PacketFu
|
|
293
294
|
ret.join("\n")
|
294
295
|
end
|
295
296
|
|
296
|
-
#
|
297
|
+
# If @inspect_style is :default (or :ugly), the inspect output is the usual
|
298
|
+
# inspect.
|
297
299
|
#
|
298
|
-
#
|
300
|
+
# If @inspect_style is :hex (or :pretty), the inspect output is
|
301
|
+
# a much more compact hexdump-style, with a shortened set of packet header
|
302
|
+
# names at the top.
|
299
303
|
#
|
300
|
-
#
|
301
|
-
#
|
302
|
-
# :all : An alias for arg=0.
|
304
|
+
# If @inspect_style is :dissect (or :verbose), the inspect output is the
|
305
|
+
# longer, but more readable, dissection of the packet. This is the default.
|
303
306
|
#
|
304
|
-
#
|
305
|
-
#
|
306
|
-
# irb(main):003:0> pkt = TCPPacket.new
|
307
|
-
# irb(main):003:0> puts pkt.inspect_hex(:layers)
|
308
|
-
# 00 1a c5 00 00 00 00 1a c5 00 00 00 08 00 45 00 ..............E.
|
309
|
-
# 00 28 83 ce 00 00 ff 06 38 02 00 00 00 00 00 00 .(......8.......
|
310
|
-
# 00 00 a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00 ........{&....P.
|
311
|
-
# 40 00 a2 25 00 00 @..%..
|
312
|
-
# 45 00 00 28 83 ce 00 00 ff 06 38 02 00 00 00 00 E..(......8.....
|
313
|
-
# 00 00 00 00 a6 0f 00 00 ac 89 7b 26 00 00 00 00 ..........{&....
|
314
|
-
# 50 00 40 00 a2 25 00 00 P.@..%..
|
315
|
-
# a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00 40 00 ......{&....P.@.
|
316
|
-
# a2 25 00 00 .%..
|
317
|
-
# => nil
|
318
|
-
# irb(main):004:0> puts pkt.inspect_hex(:layers)[2]
|
319
|
-
# a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00 40 00 ......{&....P.@.
|
320
|
-
# a2 25 00 00 .%..
|
321
|
-
# => nil
|
322
|
-
#
|
323
|
-
# TODO: Colorize this! Everyone loves colorized irb output.
|
307
|
+
# TODO: Have an option for colors. Everyone loves colorized irb output.
|
324
308
|
def inspect_hex(arg=0)
|
325
309
|
case arg
|
326
310
|
when :layers
|
@@ -344,9 +328,9 @@ module PacketFu
|
|
344
328
|
table = []
|
345
329
|
@headers.each_with_index do |header,table_idx|
|
346
330
|
proto = header.class.name.sub(/^.*::/,"")
|
347
|
-
table << [proto]
|
331
|
+
table << [proto,[]]
|
348
332
|
header.class.members.each do |elem|
|
349
|
-
elem_sym =
|
333
|
+
elem_sym = elem.to_sym # to_sym needed for 1.8
|
350
334
|
next if elem_sym == :body
|
351
335
|
elem_type_value = []
|
352
336
|
elem_type_value[0] = elem
|
@@ -357,11 +341,14 @@ module PacketFu
|
|
357
341
|
elem_type_value[1] = header.send(elem)
|
358
342
|
end
|
359
343
|
elem_type_value[2] = header[elem.to_sym].class.name
|
360
|
-
table[table_idx]
|
361
|
-
table[table_idx] << elem_type_value
|
344
|
+
table[table_idx][1] << elem_type_value
|
362
345
|
end
|
363
346
|
end
|
364
347
|
table
|
348
|
+
if @headers.last.members.include? :body
|
349
|
+
body_part = [:body, self.payload, @headers.last.body.class.name]
|
350
|
+
end
|
351
|
+
table << body_part
|
365
352
|
end
|
366
353
|
|
367
354
|
# Renders the dissection_table suitable for screen printing. Can take
|
@@ -369,36 +356,52 @@ module PacketFu
|
|
369
356
|
# take either a range or a number -- if a range, only protos within
|
370
357
|
# that range will be rendered. If an integer, only that proto
|
371
358
|
# will be rendered.
|
372
|
-
def dissect
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
359
|
+
def dissect
|
360
|
+
dtable = self.dissection_table
|
361
|
+
hex_body = nil
|
362
|
+
if dtable.last.kind_of?(Array) and dtable.last.first == :body
|
363
|
+
body = dtable.pop
|
364
|
+
hex_body = hexify(body[1])
|
365
|
+
end
|
366
|
+
elem_widths = [0,0,0]
|
367
|
+
dtable.each do |proto_table|
|
368
|
+
proto_table[1].each do |elems|
|
369
|
+
elems.each_with_index do |e,i|
|
370
|
+
width = e.size
|
371
|
+
elem_widths[i] = width if width > elem_widths[i]
|
372
|
+
end
|
383
373
|
end
|
384
|
-
rescue => e
|
385
|
-
raise ArgumentError, "Method `dissect' accepts one or two to_i-able arguments"
|
386
374
|
end
|
387
|
-
|
388
|
-
table
|
389
|
-
|
390
|
-
|
375
|
+
total_width = elem_widths.inject(0) {|sum,x| sum+x}
|
376
|
+
table = ""
|
377
|
+
dtable.each do |proto|
|
378
|
+
table << "--"
|
379
|
+
table << proto[0]
|
380
|
+
if total_width > proto[0].size
|
381
|
+
table << ("-" * (total_width - proto[0].size + 2))
|
382
|
+
else
|
383
|
+
table << ("-" * (total_width + 2))
|
391
384
|
end
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
385
|
+
table << "\n"
|
386
|
+
proto[1].each do |elems|
|
387
|
+
table << " "
|
388
|
+
elems_table = []
|
389
|
+
(0..2).each do |i|
|
390
|
+
elems_table << ("%-#{elem_widths[i]}s" % elems[i])
|
391
|
+
end
|
392
|
+
table << elems_table.join("\s")
|
393
|
+
table << "\n"
|
398
394
|
end
|
399
395
|
end
|
400
|
-
|
401
|
-
|
396
|
+
if hex_body && !hex_body.empty?
|
397
|
+
table << "-" * 66
|
398
|
+
table << "\n"
|
399
|
+
table << "00-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f---0123456789abcdef\n"
|
400
|
+
table << "-" * 66
|
401
|
+
table << "\n"
|
402
|
+
table << hex_body
|
403
|
+
end
|
404
|
+
table
|
402
405
|
end
|
403
406
|
|
404
407
|
alias :orig_kind_of? :kind_of?
|
@@ -423,7 +426,14 @@ module PacketFu
|
|
423
426
|
# If you hate this, you can run PacketFu.toggle_inspect to return
|
424
427
|
# to the typical (and often unreadable) Object#inspect format.
|
425
428
|
def inspect
|
426
|
-
|
429
|
+
case @inspect_style
|
430
|
+
when :dissect
|
431
|
+
self.dissect
|
432
|
+
when :hex
|
433
|
+
self.proto.join("|") + "\n" + self.inspect_hex
|
434
|
+
else
|
435
|
+
super
|
436
|
+
end
|
427
437
|
end
|
428
438
|
|
429
439
|
# Returns the size of the packet (as a binary string)
|
@@ -457,6 +467,11 @@ module PacketFu
|
|
457
467
|
if self.class.name =~ /(::|^)PacketFu::Packet$/
|
458
468
|
raise NoMethodError, "method `new' called for abstract class #{self.class.name}"
|
459
469
|
end
|
470
|
+
if args[:inspect_style]
|
471
|
+
@inspect_style = args[:inspect_style]
|
472
|
+
else
|
473
|
+
@inspect_style = :dissect
|
474
|
+
end
|
460
475
|
if args[:config]
|
461
476
|
args[:config].each_pair do |k,v|
|
462
477
|
case k
|
@@ -511,43 +526,17 @@ module PacketFu
|
|
511
526
|
|
512
527
|
end # class Packet
|
513
528
|
|
514
|
-
|
515
|
-
|
516
|
-
# If @inspect_style is :ugly, set the inspect method to the usual inspect.
|
517
|
-
# By default, @inspect_style is :pretty. This default may change if people
|
518
|
-
# hate it.
|
519
|
-
# Since PacketFu is designed with irb in mind, the normal inspect is way too
|
520
|
-
# verbose when new packets are created, and it ruins the aesthetics of the
|
521
|
-
# PacketFu console or quick hping-like exercises in irb.
|
522
|
-
#
|
523
|
-
# However, there are cases where knowing things like object id numbers, the complete
|
524
|
-
# @header array, etc. is useful (especially in debugging). So, toggle_inspect
|
525
|
-
# provides a means for a script to declar which style of inspect to use.
|
526
|
-
#
|
527
|
-
# This method may be an even worse idea than the original monkeypatch to Packet.inspect,
|
528
|
-
# since it would almost certainly be better to redefine inspect just in the PacketFu console.
|
529
|
-
# We'll see what happens.
|
530
|
-
#
|
531
|
-
# == Example
|
532
|
-
#
|
533
|
-
# irb(main):001:0> p = PacketFu::TCPPacket.new
|
534
|
-
# => Eth|IP|TCP
|
535
|
-
# 00 1a c5 00 00 00 00 1a c5 00 00 00 08 00 45 00 ..............E.
|
536
|
-
# 00 28 ea d7 00 00 ff 06 d0 f8 00 00 00 00 00 00 .(..............
|
537
|
-
# 00 00 a9 76 00 00 f9 28 7e 95 00 00 00 00 50 00 ...v...(~.....P.
|
538
|
-
# 40 00 4e b0 00 00 @.N...
|
539
|
-
# irb(main):002:0> PacketFu.toggle_inspect
|
540
|
-
# => :ugly
|
541
|
-
# irb(main):003:0> p = PacketFu::TCPPacket.new
|
542
|
-
# => #<PacketFu::TCPPacket:0xb7aaf96c @ip_header=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>, @tcp_header=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">, @eth_header=#<struct PacketFu::EthHeader eth_dst=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_src=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_proto=#<struct StructFu::Int16 value=2048, endian=:big, width=2, default=0>, body=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>>, @headers=[#<struct PacketFu::EthHeader eth_dst=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_src=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_proto=#<struct StructFu::Int16 value=2048, endian=:big, width=2, default=0>, body=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>>, #<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>, #<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">]>
|
543
|
-
# irb(main):004:0>
|
529
|
+
# Switches inspect styles between :dissect, :default, and :hex
|
544
530
|
def toggle_inspect
|
545
|
-
|
546
|
-
|
547
|
-
@inspect_style = :
|
531
|
+
case @inspect_style
|
532
|
+
when :hex, :pretty
|
533
|
+
@inspect_style = :dissect
|
534
|
+
when :dissect, :verbose
|
535
|
+
@inspect_style = :default
|
536
|
+
when :default, :ugly
|
537
|
+
@inspect_style = :hex
|
548
538
|
else
|
549
|
-
|
550
|
-
@inspect_style = :pretty
|
539
|
+
@inspect_style = :dissect
|
551
540
|
end
|
552
541
|
end
|
553
542
|
|
data/lib/packetfu/pcap.rb
CHANGED
@@ -228,9 +228,95 @@ module PacketFu
|
|
228
228
|
# PcapHeader and PcapPackets.
|
229
229
|
#
|
230
230
|
# See http://wiki.wireshark.org/Development/LibpcapFileFormat
|
231
|
+
#
|
232
|
+
# PcapFile also can behave as a singleton class, which is usually the better
|
233
|
+
# way to handle pcap files of really any size, since it doesn't require
|
234
|
+
# storing packets before handing them off to a given block. This is really
|
235
|
+
# the way to go.
|
231
236
|
class PcapFile < Struct.new(:endian, :head, :body)
|
232
237
|
include StructFu
|
233
238
|
|
239
|
+
class << self
|
240
|
+
|
241
|
+
# Takes a given file and returns an array of the packet bytes. Here
|
242
|
+
# for backwards compatibilty.
|
243
|
+
def file_to_array(fname)
|
244
|
+
PcapFile.new.file_to_array(:f => fname)
|
245
|
+
end
|
246
|
+
|
247
|
+
# Takes a given file name, and reads out the packets. If given a block,
|
248
|
+
# it will yield back a PcapPacket object per packet found.
|
249
|
+
def read(fname,&block)
|
250
|
+
begin
|
251
|
+
file_handle = File.open(fname, "rb")
|
252
|
+
pcap_packets = PcapPackets.new unless block
|
253
|
+
file_header = PcapHeader.new
|
254
|
+
file_header.read file_handle.read(24)
|
255
|
+
packet_count = 0
|
256
|
+
pcap_packet = PcapPacket.new(:endian => file_header.endian)
|
257
|
+
while pcap_packet.read file_handle.read(16) do
|
258
|
+
len = pcap_packet.incl_len
|
259
|
+
pcap_packet.data = StructFu::String.new.read(file_handle.read(len.to_i))
|
260
|
+
packet_count += 1
|
261
|
+
if pcap_packet.data.size < len.to_i
|
262
|
+
warn "Packet ##{packet_count} is corrupted: expected #{len.to_i}, got #{pcap_packet.data.size}. Exiting."
|
263
|
+
break
|
264
|
+
end
|
265
|
+
if block
|
266
|
+
yield pcap_packet
|
267
|
+
else
|
268
|
+
pcap_packets << pcap_packet
|
269
|
+
end
|
270
|
+
end
|
271
|
+
unless block
|
272
|
+
return pcap_packets
|
273
|
+
end
|
274
|
+
ensure
|
275
|
+
file_handle.close
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Takes a filename, and an optional block. If a block is given,
|
280
|
+
# yield back the raw packet data from the given file. Otherwise,
|
281
|
+
# return an array of parsed packets.
|
282
|
+
def read_packet_bytes(fname,&block)
|
283
|
+
count = 0
|
284
|
+
packets = [] unless block
|
285
|
+
read(fname) do |packet|
|
286
|
+
if block
|
287
|
+
count += 1
|
288
|
+
yield packet.data.to_s
|
289
|
+
else
|
290
|
+
packets << packet.data.to_s
|
291
|
+
end
|
292
|
+
end
|
293
|
+
block ? count : packets
|
294
|
+
end
|
295
|
+
|
296
|
+
alias :file_to_array :read_packet_bytes
|
297
|
+
|
298
|
+
# Takes a filename, and an optional block. If a block is given,
|
299
|
+
# yield back parsed packets from the given file. Otherwise, return
|
300
|
+
# an array of parsed packets.
|
301
|
+
#
|
302
|
+
# This is a brazillian times faster than the old methods of extracting
|
303
|
+
# packets from files.
|
304
|
+
def read_packets(fname,&block)
|
305
|
+
count = 0
|
306
|
+
packets = [] unless block
|
307
|
+
read_packet_bytes(fname) do |packet|
|
308
|
+
if block
|
309
|
+
count += 1
|
310
|
+
yield Packet.parse(packet)
|
311
|
+
else
|
312
|
+
packets << Packet.parse(packet)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
block ? count : packets
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
234
320
|
def initialize(args={})
|
235
321
|
init_fields(args)
|
236
322
|
super(args[:endian], args[:head], args[:body])
|
@@ -265,6 +351,7 @@ module PacketFu
|
|
265
351
|
# Clears the contents of the PcapFile prior to reading in a new string.
|
266
352
|
def read!(str)
|
267
353
|
clear
|
354
|
+
force_binary(str)
|
268
355
|
self.read str
|
269
356
|
end
|
270
357
|
|
@@ -399,94 +486,6 @@ module PacketFu
|
|
399
486
|
|
400
487
|
end
|
401
488
|
|
402
|
-
# PcapFile also can behave as a singleton class, which is usually the better
|
403
|
-
# way to handle pcap files of really any size, since it doesn't require
|
404
|
-
# storing packets before handing them off to a given block. This is really
|
405
|
-
# the way to go.
|
406
|
-
class PcapFile
|
407
|
-
class << self
|
408
|
-
|
409
|
-
# Takes a given file and returns an array of the packet bytes. Here
|
410
|
-
# for backwards compatibilty.
|
411
|
-
def file_to_array(fname)
|
412
|
-
PcapFile.new.file_to_array(:f => fname)
|
413
|
-
end
|
414
|
-
|
415
|
-
# Takes a given file name, and reads out the packets. If given a block,
|
416
|
-
# it will yield back a PcapPacket object per packet found.
|
417
|
-
def read(fname,&block)
|
418
|
-
begin
|
419
|
-
file_handle = File.open(fname, "rb")
|
420
|
-
pcap_packets = PcapPackets.new unless block
|
421
|
-
file_header = PcapHeader.new
|
422
|
-
file_header.read file_handle.read(24)
|
423
|
-
packet_count = 0
|
424
|
-
pcap_packet = PcapPacket.new(:endian => file_header.endian)
|
425
|
-
while pcap_packet.read file_handle.read(16) do
|
426
|
-
len = pcap_packet.incl_len
|
427
|
-
pcap_packet.data = StructFu::String.new.read(file_handle.read(len.to_i))
|
428
|
-
packet_count += 1
|
429
|
-
if pcap_packet.data.size < len.to_i
|
430
|
-
warn "Packet ##{packet_count} is corrupted: expected #{len.to_i}, got #{pcap_packet.data.size}. Exiting."
|
431
|
-
break
|
432
|
-
end
|
433
|
-
if block
|
434
|
-
yield pcap_packet
|
435
|
-
else
|
436
|
-
pcap_packets << pcap_packet
|
437
|
-
end
|
438
|
-
end
|
439
|
-
unless block
|
440
|
-
return pcap_packets
|
441
|
-
end
|
442
|
-
ensure
|
443
|
-
file_handle.close
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
# Takes a filename, and an optional block. If a block is given,
|
448
|
-
# yield back the raw packet data from the given file. Otherwise,
|
449
|
-
# return an array of parsed packets.
|
450
|
-
def read_packet_bytes(fname,&block)
|
451
|
-
count = 0
|
452
|
-
packets = [] unless block
|
453
|
-
read(fname) do |packet|
|
454
|
-
if block
|
455
|
-
count += 1
|
456
|
-
yield packet.data.to_s
|
457
|
-
else
|
458
|
-
packets << packet.data.to_s
|
459
|
-
end
|
460
|
-
end
|
461
|
-
block ? count : packets
|
462
|
-
end
|
463
|
-
|
464
|
-
alias :file_to_array :read_packet_bytes
|
465
|
-
|
466
|
-
# Takes a filename, and an optional block. If a block is given,
|
467
|
-
# yield back parsed packets from the given file. Otherwise, return
|
468
|
-
# an array of parsed packets.
|
469
|
-
#
|
470
|
-
# This is a brazillian times faster than the old methods of extracting
|
471
|
-
# packets from files.
|
472
|
-
def read_packets(fname,&block)
|
473
|
-
count = 0
|
474
|
-
packets = [] unless block
|
475
|
-
read_packet_bytes(fname) do |packet|
|
476
|
-
if block
|
477
|
-
count += 1
|
478
|
-
yield Packet.parse(packet)
|
479
|
-
else
|
480
|
-
packets << Packet.parse(packet)
|
481
|
-
end
|
482
|
-
end
|
483
|
-
block ? count : packets
|
484
|
-
end
|
485
|
-
|
486
|
-
end
|
487
|
-
|
488
|
-
end
|
489
|
-
|
490
489
|
end
|
491
490
|
|
492
491
|
module PacketFu
|
data/test/icmp_test.pcap
CHANGED
Binary file
|
data/test/ip_test.pcap
CHANGED
Binary file
|
data/test/tcp_test.pcap
CHANGED
Binary file
|
data/test/udp_test.pcap
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetfu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: -1329738657
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
9
|
+
- 5
|
10
10
|
- pre
|
11
|
-
version: 1.0.
|
11
|
+
version: 1.0.5.pre
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Tod Beardsley
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-06-06 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -35,20 +35,6 @@ dependencies:
|
|
35
35
|
version: 0.9.2
|
36
36
|
type: :development
|
37
37
|
version_requirements: *id001
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: rspec
|
40
|
-
prerelease: false
|
41
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
|
-
requirements:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
hash: 3
|
47
|
-
segments:
|
48
|
-
- 0
|
49
|
-
version: "0"
|
50
|
-
type: :development
|
51
|
-
version_requirements: *id002
|
52
38
|
description: PacketFu is a mid-level packet manipulation library for Ruby. With it, users can read, parse, and write network packets with the level of ease and fun they expect from Ruby. Note that this gem does not automatically require pcaprub, since users may install pcaprub through non-gem means.
|
53
39
|
email: todb@planb-security.net
|
54
40
|
executables: []
|
@@ -129,8 +115,8 @@ files:
|
|
129
115
|
- examples/new-simple-stats.rb
|
130
116
|
has_rdoc: true
|
131
117
|
homepage: http://code.google.com/p/packetfu/
|
132
|
-
licenses:
|
133
|
-
|
118
|
+
licenses:
|
119
|
+
- BSD
|
134
120
|
post_install_message:
|
135
121
|
rdoc_options: []
|
136
122
|
|
@@ -156,8 +142,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
142
|
- 3
|
157
143
|
- 1
|
158
144
|
version: 1.3.1
|
159
|
-
requirements:
|
160
|
-
|
145
|
+
requirements:
|
146
|
+
- sdoc, for generating local documentation
|
147
|
+
- rspec, v2.6.2 or later, for testing
|
148
|
+
- pcaprub v0.9.2 or later, for packet capture/inject
|
161
149
|
rubyforge_project: packetfu
|
162
150
|
rubygems_version: 1.4.2
|
163
151
|
signing_key:
|