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 CHANGED
@@ -1,3 +1,4 @@
1
1
  lib/packetfu.rb
2
2
  lib/packetfu/
3
3
  README
4
+ LICENSE
@@ -20,6 +20,7 @@ end
20
20
  def count_packet_types(file)
21
21
  stats = {}
22
22
  count = 0
23
+ elapsed = 0
23
24
  start_time = Time.now
24
25
  PacketFu::PcapFile.read_packets(file) do |pkt|
25
26
  kind = pkt.proto.last.to_sym
data/lib/packetfu.rb CHANGED
@@ -1,8 +1,6 @@
1
1
 
2
2
  # :title: PacketFu Documentation
3
- # :main: ../README
4
- # :include: ../README
5
- # :include: ../LICENSE
3
+ # :main: README
6
4
 
7
5
  cwd = File.expand_path(File.dirname(__FILE__))
8
6
 
@@ -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
- # Returns a hex-formatted representation of the packet.
297
+ # If @inspect_style is :default (or :ugly), the inspect output is the usual
298
+ # inspect.
297
299
  #
298
- # ==== Arguments
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
- # 0..9 : If a number is given only the layer in @header[arg] will be displayed. Note that this will include all @headers included in that header.
301
- # :layers : If :layers is specified, the dump will return an array of headers by layer level.
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
- # ==== Examples
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 = RUBY_VERSION[/^1\.8/] ? elem.to_sym : elem
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(min=nil,max=nil)
373
- table = self.dissection_table
374
- widest = (0..2).map {|i| table.map {|x| x.map {|y| y[i].size}}.flatten.sort.last}
375
- table_formatted = ""
376
- begin
377
- if min
378
- layer_min = min.to_i
379
- layer_max = max ? max.to_i : layer_min
380
- table_range = (layer_min..layer_max)
381
- else
382
- layer_min = min
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
- header_line_width = widest.inject {|sum,i| sum ? sum + i : i} + 2
388
- table.each_with_index do |proto_table,proto_idx|
389
- if layer_min
390
- next unless table_range.member? proto_idx
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
- table_formatted << "--#{proto_table.first}"
393
- table_formatted << "-" * (header_line_width - proto_table.first.size) << "\n"
394
- proto_table[1,proto_table.size].each do |elem,value,type|
395
- table_formatted << " %-#{widest[0]}s " % elem
396
- table_formatted << "%-#{widest[1]}s " % value.to_s
397
- table_formatted << type << "\n"
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
- table_formatted << ("-" * header_line_width)
401
- table_formatted
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
- self.proto.join("|") + "\n" + self.inspect_hex
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
- @inspect_style = :pretty
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
- if @inspect_style == :pretty
546
- eval("class Packet; def inspect; super; end; end")
547
- @inspect_style = :ugly
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
- eval("class Packet; def inspect; self.proto.join('|') + \"\n\" + self.inspect_hex; end; end")
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: 199653271
4
+ hash: -1329738657
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 4
9
+ - 5
10
10
  - pre
11
- version: 1.0.4.pre
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-05-22 00:00:00 -05:00
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: