Class: PacketFu::UDPPacket

Inherits:
Packet
  • Object
show all
Defined in:
lib/packetfu/protos/udp.rb

Overview

UDPPacket is used to construct UDP Packets. They contain an EthHeader, an IPHeader, and a UDPHeader.

Example

udp_pkt = PacketFu::UDPPacket.new
udp_pkt.udp_src=rand(0xffff-1024) + 1024
udp_pkt.udp_dst=53

udp_pkt.ip_saddr="1.2.3.4"
udp_pkt.ip_daddr="10.20.30.40"

udp_pkt.recalc
udp_pkt.to_f('/tmp/udp.pcap')

Parameters

:eth
  A pre-generated EthHeader object.
:ip
  A pre-generated IPHeader object.
:flavor
  TODO: Sets the "flavor" of the UDP packet. UDP packets don't tend have a lot of
  flavor, but their underlying ip headers do.
:config
 A hash of return address details, often the output of Utils.whoami?

Instance Attribute Summary collapse

Attributes inherited from Packet

#flavor, #headers, #iface, #inspect_style

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Packet

#==, #clone, #dissect, #dissection_table, force_binary, #handle_is_identity, #hexify, inherited, #inspect, #inspect_hex, #kind_of?, layer, #layer, #layer_symbol, layer_symbol, #method_missing, #orig_kind_of?, parse, #payload, #payload=, #peek, #proto, #recalc, #respond_to?, #size, #to_f, #to_pcap, #to_s, #to_w, #write

Constructor Details

#initialize(args = {}) ⇒ UDPPacket

Returns a new instance of UDPPacket.



161
162
163
164
165
166
167
168
169
170
171
# File 'lib/packetfu/protos/udp.rb', line 161

def initialize(args={})
  @eth_header = EthHeader.new(args).read(args[:eth])
  @ip_header = IPHeader.new(args).read(args[:ip])
  @ip_header.ip_proto=0x11
  @udp_header = UDPHeader.new(args).read(args[:icmp])
  @ip_header.body = @udp_header
  @eth_header.body = @ip_header
  @headers = [@eth_header, @ip_header, @udp_header]
  super
  udp_calc_sum
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class PacketFu::Packet

Instance Attribute Details

#eth_headerObject

Returns the value of attribute eth_header.



135
136
137
# File 'lib/packetfu/protos/udp.rb', line 135

def eth_header
  @eth_header
end

#ip_headerObject

Returns the value of attribute ip_header.



135
136
137
# File 'lib/packetfu/protos/udp.rb', line 135

def ip_header
  @ip_header
end

#udp_headerObject

Returns the value of attribute udp_header.



135
136
137
# File 'lib/packetfu/protos/udp.rb', line 135

def udp_header
  @udp_header
end

Class Method Details

.can_parse?(str) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
140
141
142
143
# File 'lib/packetfu/protos/udp.rb', line 137

def self.can_parse?(str)
  return false unless str.size >= 28
  return false unless EthPacket.can_parse? str
  return false unless IPPacket.can_parse? str
  return false unless str[23,1] == "\x11"
  return true
end

Instance Method Details

#peek_formatObject

Peek provides summary data on packet contents.



225
226
227
228
229
230
231
232
233
234
# File 'lib/packetfu/protos/udp.rb', line 225

def peek_format
  peek_data = ["U  "]
  peek_data << "%-5d" % self.to_s.size
  peek_data << "%-21s" % "#{self.ip_saddr}:#{self.udp_sport}"
  peek_data << "->"
  peek_data << "%21s" % "#{self.ip_daddr}:#{self.udp_dport}"
  peek_data << "%23s" % "I:"
  peek_data << "%04x" % self.ip_id
  peek_data.join
end

#read(str = nil, args = {}) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/packetfu/protos/udp.rb', line 145

def read(str=nil, args={})
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
  @eth_header.read(str)
  @ip_header.read(str[14,str.size])
  @eth_header.body = @ip_header
  if args[:strip]
    udp_len = str[16,2].unpack("n")[0] - 20
    @udp_header.read(str[14+(@ip_header.ip_hlen),udp_len])
  else
    @udp_header.read(str[14+(@ip_header.ip_hlen),str.size])
  end
  @ip_header.body = @udp_header
  super(args)
  self
end

#udp_calc_sumObject

udp_calc_sum() computes the UDP checksum, and is called upon intialization. It usually should be called just prior to dropping packets to a file or on the wire.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/packetfu/protos/udp.rb', line 175

def udp_calc_sum
  # This is /not/ delegated down to @udp_header since we need info
  # from the IP header, too.
  checksum = (ip_src.to_i >> 16)
  checksum += (ip_src.to_i & 0xffff)
  checksum += (ip_dst.to_i >> 16)
  checksum += (ip_dst.to_i & 0xffff)
  checksum += 0x11
  checksum += udp_len.to_i
  checksum += udp_src.to_i
  checksum += udp_dst.to_i
  checksum += udp_len.to_i
  if udp_len.to_i >= 8
    # For IP trailers. This isn't very reliable. :/
    real_udp_payload = payload.to_s[0,(udp_len.to_i-8)] 
  else
    # I'm not going to mess with this right now.
    real_udp_payload = payload 
  end
  chk_payload = (real_udp_payload.size % 2 == 0 ? real_udp_payload : real_udp_payload + "\x00")
  chk_payload.unpack("n*").each {|x| checksum = checksum+x}
  checksum = checksum % 0xffff
  checksum = 0xffff - checksum
  checksum == 0 ? 0xffff : checksum
  @udp_header.udp_sum = checksum
end

#udp_recalc(args = :all) ⇒ Object

udp_recalc() recalculates various fields of the UDP packet. Valid arguments are:

:all
  Recomputes all calculated fields.
:udp_sum
  Recomputes the UDP checksum.
:udp_len
  Recomputes the UDP length.


210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/packetfu/protos/udp.rb', line 210

def udp_recalc(args=:all)
  case args
  when :udp_len
    @udp_header.udp_recalc
  when :udp_sum
    udp_calc_sum
  when :all
    @udp_header.udp_recalc
    udp_calc_sum
  else
    raise ArgumentError, "No such field `#{arg}'"
  end
end