metasploit-framework/lib/packetfu/write.rb

111 lines
3.0 KiB
Ruby

module PacketFu
# The Write class facilitates writing to libpcap files, which is the native file format
# for packet capture utilities such as tcpdump, Wireshark, and PacketFu::PcapFile.
#
# == Example
#
# cap = PacketFu::Capture.new(:start => true)
# sleep 10
# cap.save
# pkt_array = cap.array
# PacketFu::Write.a2f(:file => 'pcaps/my_capture.pcap', :array => pkt_array)
#
# === array_to_file() Arguments
#
# :filename | :file | :out
# The file to write to. If it exists, it will be overwritten. By default, no file will be written.
#
# :array | arr
# The array to read packet data from. Note, these should be strings, and not packet objects!
#
# :ts | :timestamp
# The starting timestamp. By default, it is the result of Time.now.to_i
#
# :ts_inc | :timestamp_increment
# The timestamp increment, in seconds. (Sorry, no usecs yet)
#
# == See Also
#
# Read, Capture
class Write
# Writes an array of binary data to a libpcap file.
def self.array_to_file(args={})
filename = args[:filename] || args[:file] || args[:out] || :nowrite
arr = args[:arr] || args[:array] || []
ts = args[:ts] || args[:timestamp] || Time.now.to_i
ts_inc = args[:ts_inc] || args[:timestamp_increment] || 1
if arr.class != Array
raise ArgumentError, "This needs to be an array."
end
formatted_packets = []
arr.each do |pkt|
this_pkt = PcapPacket.new
this_pkt.data = pkt[0,0xffff]
this_pkt.orig_len = pkt.size # orig_len isn't calc'ed already.
this_pkt.ts_sec = ts += decimal_to_usecs(ts_inc)[0]
formatted_packets << this_pkt.to_s
end
filedata = PcapFile.new
filedata.read(PcapFile.new.to_s + formatted_packets.join) # Like a cat playing the bass.
if filename != :nowrite
out = File.new(filename.to_s, 'w')
out.print filedata
out.close
# Return [filename, file size, # of packets, initial timestamp, timestamp increment]
ret = [filename,filedata.to_s.size,arr.size,ts,ts_inc]
else
ret = [nil,filedata.to_s.size,arr.size,ts,ts_inc]
end
end
def self.append(args={})
file = args[:file] || args[:out] || :nowrite
pkt = args[:packet] || args[:pkt] || nil
ts = args[:ts] || args[:timestamp] || Time.now.to_i
if (file == :nowrite)
return false
end
if (!file.kind_of?(File))
file = File.new(file, "a")
end
pc_pkt = PcapPacket.new
pc_pkt.data = pkt.to_s[0,0xffff]
pc_pkt.orig_len = pkt.size
pc_pkt.ts_sec = decimal_to_usecs(ts)[0]
file.print(pc_pkt.to_s)
return pc_pkt.to_s.size
end
# A synonym for array_to_file()
def self.a2f(args={})
self.array_to_file(args)
end
# TODO: Wire this in later to enable incrementing by microseconds.
def self.decimal_to_usecs(decimal)
secs = decimal.to_i
usecs = decimal.to_f.to_s.split('.')[1]
[secs,usecs]
end
# IRB tab-completion hack.
def truth
"Stranger than fiction" ; true
end
#:stopdoc:
alias_method :array_to_file, :truth
alias_method :a2f, :truth
#:startdoc:
end
end