Class: PacketFu::Capture

Inherits:
Object
  • Object
show all
Defined in:
lib/packetfu/capture.rb

Overview

The Capture class is used to construct PcapRub objects in order to collect packets from an interface.

This class requires PcapRub. In addition, you will need root (or root-like) privileges in order to capture from the interface.

Note, on some wireless cards, setting :promisc => true will disable capturing.

Example

# Typical use
cap = PacketFu::Capture.new(:iface => 'eth0', :promisc => true)
cap.start
sleep 10
cap.save
first_packet = cap.array[0]

# Tcpdump-like use
cap = PacketFu::Capture.new(:start => true)
cap.show_live(:save => true, :filter => 'tcp and not port 22')

See Also

Read, Write

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Capture

Returns a new instance of Capture.



32
33
34
35
36
37
38
39
40
41
# File 'lib/packetfu/capture.rb', line 32

def initialize(args={})
  @array = [] # Where the packet array goes.
  @stream = [] # Where the stream goes.
  @iface = (args[:iface] || ENV['IFACE'] || PacketFu::Utils.default_int || "lo").to_s
  @snaplen = args[:snaplen] || 0xffff
  @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
  @timeout = args[:timeout] || 1
  @filter  = args[:filter] || args[:bpf]
  setup_params(args)
end

Instance Attribute Details

#arrayObject

Leave these public and open.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def array
  @array
end

#ifaceObject (readonly)

Returns the value of attribute iface.



30
31
32
# File 'lib/packetfu/capture.rb', line 30

def iface
  @iface
end

#promiscObject (readonly)

Returns the value of attribute promisc.



30
31
32
# File 'lib/packetfu/capture.rb', line 30

def promisc
  @promisc
end

#snaplenObject (readonly)

Returns the value of attribute snaplen.



30
31
32
# File 'lib/packetfu/capture.rb', line 30

def snaplen
  @snaplen
end

#streamObject

Leave these public and open.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def stream
  @stream
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



30
31
32
# File 'lib/packetfu/capture.rb', line 30

def timeout
  @timeout
end

Instance Method Details

#bpf(args = {}) ⇒ Object Also known as: filter

bpf() sets a bpf filter on a capture session. Valid arugments are:

:filter
  Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'


101
102
103
104
105
106
# File 'lib/packetfu/capture.rb', line 101

def bpf(args={})
  filter = args[:filter] || args[:bpf] || @filter
  capture if @stream.class == Array
  @stream.setfilter(filter) if filter
  @filter = filter
end

#capture(args = {}) ⇒ Object

capture() initializes the @stream varaible. Valid arguments are:

:filter
  Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
:start
  When true, start capturing packets to the @stream variable. Defaults to true


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/packetfu/capture.rb', line 57

def capture(args={})
  if Process.euid.zero?
    filter = args[:filter] || args[:bpf] || @filter
    start = args[:start] || true
    if start
      begin
        @stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
      rescue RuntimeError
        $stderr.print "Are you sure you're root? Error: "
        raise
      end
      bpf(:filter=>filter) if filter
    else
      @stream = []
    end
    @stream
  else
    raise RuntimeError,"Not root, so can't capture packets. Error: "
  end
end

#clear(args = {}) ⇒ Object

clear() clears the @stream and @array variables, essentially starting the capture session over. Valid arguments are:

:array
  If true, the @array is cleared.
:stream
  If true, the @stream is cleared.


90
91
92
93
94
95
# File 'lib/packetfu/capture.rb', line 90

def clear(args={})
  array = args[:array] || true
  stream = args[:stream] || true
  @array = [] if array
  @stream = [] if stream
end

#nextObject

next() exposes the Stream object’s next method to the outside world.



128
129
130
# File 'lib/packetfu/capture.rb', line 128

def next
  return @stream.next
end

#save(args = {}) ⇒ Object

save() is a equivalent to wire_to_array()



138
139
140
# File 'lib/packetfu/capture.rb', line 138

def save(args={})
  wire_to_array(args)
end

#setup_params(args = {}) ⇒ Object

Used by new().



44
45
46
47
48
49
# File 'lib/packetfu/capture.rb', line 44

def setup_params(args={})
  filter = args[:filter] || args[:bpf] || @filter
  start = args[:start] || false
  capture if start
  bpf(:filter=>filter) if filter
end

#show_live(args = {}) ⇒ Object

show_live() is a method to capture packets and display peek() data to stdout. Valid arguments are:

:filter
  Provide a bpf filter to captured packets.
:save
  Save the capture in @array
:verbose
  TODO: Not implemented yet; do more than just peek() at the packets.
:quiet
  TODO: Not implemented yet; do less than peek() at the packets.


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/packetfu/capture.rb', line 152

def show_live(args={})
  filter = args[:filter] || args[:bpf] || @filter
  save = args[:save]
  verbose = args[:verbose] || args[:v] || false
  quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.

  # Ensure the capture's started.
  if @stream.class == Array
    capture
  end

  @stream.setfilter(filter) if filter
  while true
    @stream.each do |pkt|
      puts Packet.parse(pkt).peek
      @array << pkt if args[:save]
    end
  end
end

#start(args = {}) ⇒ Object

start() is equivalent to capture().



79
80
81
# File 'lib/packetfu/capture.rb', line 79

def start(args={})
  capture(args)
end

#w2a(args = {}) ⇒ Object

w2a() is a equivalent to wire_to_array()



133
134
135
# File 'lib/packetfu/capture.rb', line 133

def w2a(args={})
  wire_to_array(args)
end

#wire_to_array(args = {}) ⇒ Object

wire_to_array() saves a packet stream as an array of binary strings. From here, packets may accessed by other functions. Note that the wire_to_array empties the stream, so multiple calls will append new packets to @array. Valid arguments are:

:filter
  Provide a bpf filter to apply to packets moving from @stream to @array.


117
118
119
120
121
122
123
124
125
# File 'lib/packetfu/capture.rb', line 117

def wire_to_array(args={})
  filter = args[:filter] || args[:bpf] || @filter
  bpf(:filter=>filter) if filter

  while this_pkt = @stream.next
    @array << this_pkt
  end
  @array.size
end