Class: PacketFu::TCPPacket
- Includes:
- EthHeaderMixin, IPHeaderMixin, TCPHeaderMixin
- Defined in:
- lib/packetfu/protos/tcp.rb
Overview
TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
Example
tcp_pkt = PacketFu::TCPPacket.new
tcp_pkt.tcp_flags.syn=1
tcp_pkt.tcp_dst=80
tcp_pkt.tcp_win=5840
tcp_pkt.="mss:1460,sack.ok,ts:#{rand(0xffffffff)};0,nop,ws:7"
tcp_pkt.ip_saddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
tcp_pkt.ip_daddr=[rand(0xff),rand(0xff),rand(0xff),rand(0xff)].join('.')
tcp_pkt.recalc
tcp_pkt.to_f('/tmp/tcp.pcap')
Parameters
:eth
A pre-generated EthHeader object.
:ip
A pre-generated IPHeader object.
:flavor
TODO: Sets the "flavor" of the TCP packet. This will include TCP options and the initial window
size, per stack. There is a lot of variety here, and it's one of the most useful methods to
remotely fingerprint devices. :flavor will span both ip and tcp for consistency.
:type
TODO: Set up particular types of packets (syn, psh_ack, rst, etc). This can change the initial flavor.
:config
A hash of return address details, often the output of Utils.whoami?
Instance Attribute Summary collapse
-
#eth_header ⇒ Object
Returns the value of attribute eth_header.
-
#ip_header ⇒ Object
Returns the value of attribute ip_header.
-
#tcp_header ⇒ Object
Returns the value of attribute tcp_header.
Attributes inherited from Packet
#flavor, #headers, #iface, #inspect_style
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(args = {}) ⇒ TCPPacket
constructor
A new instance of TCPPacket.
-
#peek_format ⇒ Object
TCP packets are denoted by a “T ”, followed by size, source and dest information, packet flags, sequence number, and IPID.
- #read(str = nil, args = {}) ⇒ Object
-
#tcp_calc_flavor(str) ⇒ Object
Sets the correct flavor for TCP Packets.
-
#tcp_calc_sum ⇒ Object
tcp_calc_sum() computes the TCP checksum, and is called upon intialization.
-
#tcp_recalc(arg = :all) ⇒ Object
Recalculates various fields of the TCP packet.
Methods included from TCPHeaderMixin
#tcp_ack, #tcp_ack=, #tcp_ack_readable, #tcp_calc_hlen, #tcp_calc_seq, #tcp_calc_src, #tcp_dport, #tcp_dport=, #tcp_dst, #tcp_dst=, #tcp_ecn, #tcp_ecn=, #tcp_flags, #tcp_flags=, #tcp_flags_dotmap, #tcp_flags_readable, #tcp_hlen, #tcp_hlen=, #tcp_options, #tcp_options=, #tcp_opts, #tcp_opts=, #tcp_opts_len, #tcp_opts_readable, #tcp_reserved, #tcp_reserved=, #tcp_seq, #tcp_seq=, #tcp_seq_readable, #tcp_sport, #tcp_sport=, #tcp_src, #tcp_src=, #tcp_sum, #tcp_sum=, #tcp_sum_readable, #tcp_urg, #tcp_urg=, #tcp_win, #tcp_win=
Methods included from IPHeaderMixin
#ip_calc_id, #ip_calc_len, #ip_calc_sum, #ip_daddr, #ip_daddr=, #ip_dst, #ip_dst=, #ip_dst_readable, #ip_frag, #ip_frag=, #ip_hl, #ip_hl=, #ip_hlen, #ip_id, #ip_id=, #ip_id_readable, #ip_len, #ip_len=, #ip_proto, #ip_proto=, #ip_recalc, #ip_saddr, #ip_saddr=, #ip_src, #ip_src=, #ip_src_readable, #ip_sum, #ip_sum=, #ip_sum_readable, #ip_tos, #ip_tos=, #ip_ttl, #ip_ttl=, #ip_v, #ip_v=
Methods included from EthHeaderMixin
#eth_daddr, #eth_daddr=, #eth_dst, #eth_dst=, #eth_dst_readable, #eth_proto, #eth_proto=, #eth_proto_readable, #eth_saddr, #eth_saddr=, #eth_src, #eth_src=, #eth_src_readable
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 = {}) ⇒ TCPPacket
Returns a new instance of TCPPacket.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/packetfu/protos/tcp.rb', line 69 def initialize(args={}) @eth_header = (args[:eth] || EthHeader.new) @ip_header = (args[:ip] || IPHeader.new) @tcp_header = (args[:tcp] || TCPHeader.new) @tcp_header.flavor = args[:flavor].to_s.downcase @ip_header.body = @tcp_header @eth_header.body = @ip_header @headers = [@eth_header, @ip_header, @tcp_header] @ip_header.ip_proto=0x06 super if args[:flavor] tcp_calc_flavor(@tcp_header.flavor) else tcp_calc_sum end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class PacketFu::Packet
Instance Attribute Details
#eth_header ⇒ Object
Returns the value of attribute eth_header.
46 47 48 |
# File 'lib/packetfu/protos/tcp.rb', line 46 def eth_header @eth_header end |
#ip_header ⇒ Object
Returns the value of attribute ip_header.
46 47 48 |
# File 'lib/packetfu/protos/tcp.rb', line 46 def ip_header @ip_header end |
#tcp_header ⇒ Object
Returns the value of attribute tcp_header.
46 47 48 |
# File 'lib/packetfu/protos/tcp.rb', line 46 def tcp_header @tcp_header end |
Class Method Details
.can_parse?(str) ⇒ Boolean
48 49 50 51 52 53 54 |
# File 'lib/packetfu/protos/tcp.rb', line 48 def self.can_parse?(str) return false unless str.size >= 54 return false unless EthPacket.can_parse? str return false unless IPPacket.can_parse? str return false unless str[23,1] == "\x06" return true end |
Instance Method Details
#peek_format ⇒ Object
TCP packets are denoted by a “T ”, followed by size, source and dest information, packet flags, sequence number, and IPID.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/packetfu/protos/tcp.rb', line 183 def peek_format peek_data = ["T "] peek_data << "%-5d" % self.to_s.size peek_data << "%-21s" % "#{self.ip_saddr}:#{self.tcp_src}" peek_data << "->" peek_data << "%21s" % "#{self.ip_daddr}:#{self.tcp_dst}" flags = ' [' flags << self.tcp_flags_dotmap flags << '] ' peek_data << flags peek_data << "S:" peek_data << "%08x" % self.tcp_seq peek_data << "|I:" peek_data << "%04x" % self.ip_id peek_data.join end |
#read(str = nil, args = {}) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/packetfu/protos/tcp.rb', line 56 def read(str=nil, args={}) raise "Cannot parse `#{str}'" unless self.class.can_parse?(str) @eth_header.read(str) # Strip off any extra data, if we are asked to do so. if args[:strip] tcp_body_len = self.ip_len - self.ip_hlen - (self.tcp_hlen * 4) @tcp_header.body.read(@tcp_header.body.to_s[0,tcp_body_len]) end super(args) self end |
#tcp_calc_flavor(str) ⇒ Object
Sets the correct flavor for TCP Packets. Recognized flavors are:
windows, linux, freebsd
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/packetfu/protos/tcp.rb', line 90 def tcp_calc_flavor(str) ts_val = Time.now.to_i + rand(0x4fffffff) ts_sec = rand(0xffffff) case @tcp_header.flavor = str.to_s.downcase when "windows" # WinXP's default syn @tcp_header.tcp_win = 0x4000 @tcp_header.="MSS:1460,NOP,NOP,SACKOK" @tcp_header.tcp_src = rand(5000 - 1026) + 1026 @ip_header.ip_ttl = 64 when "linux" # Ubuntu Linux 2.6.24-19-generic default syn @tcp_header.tcp_win = 5840 @tcp_header.="MSS:1460,SACKOK,TS:#{ts_val};0,NOP,WS:7" @tcp_header.tcp_src = rand(61_000 - 32_000) + 32_000 @ip_header.ip_ttl = 64 when "freebsd" # Freebsd @tcp_header.tcp_win = 0xffff @tcp_header.="MSS:1460,NOP,WS:3,NOP,NOP,TS:#{ts_val};#{ts_sec},SACKOK,EOL,EOL" @ip_header.ip_ttl = 64 else @tcp_header.="MSS:1460,NOP,NOP,SACKOK" end tcp_calc_sum end |
#tcp_calc_sum ⇒ Object
tcp_calc_sum() computes the TCP checksum, and is called upon intialization. It usually should be called just prior to dropping packets to a file or on the wire. – This is /not/ delegated down to @tcp_header since we need info from the IP header, too. ++
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/packetfu/protos/tcp.rb', line 120 def tcp_calc_sum 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 += 0x06 # TCP Protocol. checksum += (ip_len.to_i - ((ip_hl.to_i) * 4)) checksum += tcp_src checksum += tcp_dst checksum += (tcp_seq.to_i >> 16) checksum += (tcp_seq.to_i & 0xffff) checksum += (tcp_ack.to_i >> 16) checksum += (tcp_ack.to_i & 0xffff) checksum += ((tcp_hlen << 12) + (tcp_reserved << 9) + (tcp_ecn.to_i << 6) + tcp_flags.to_i ) checksum += tcp_win checksum += tcp_urg chk_tcp_opts = (tcp_opts.to_s.size % 2 == 0 ? tcp_opts.to_s : tcp_opts.to_s + "\x00") chk_tcp_opts.unpack("n*").each {|x| checksum = checksum + x } if (ip_len - ((ip_hl + tcp_hlen) * 4)) >= 0 real_tcp_payload = payload[0,( ip_len - ((ip_hl + tcp_hlen) * 4) )] # Can't forget those pesky FCSes! else real_tcp_payload = payload # Something's amiss here so don't bother figuring out where the real payload is. end chk_payload = (real_tcp_payload.size % 2 == 0 ? real_tcp_payload : real_tcp_payload + "\x00") # Null pad if it's odd. chk_payload.unpack("n*").each {|x| checksum = checksum+x } checksum = checksum % 0xffff checksum = 0xffff - checksum checksum == 0 ? 0xffff : checksum @tcp_header.tcp_sum = checksum end |
#tcp_recalc(arg = :all) ⇒ Object
Recalculates various fields of the TCP packet.
Parameters
:all
Recomputes all calculated fields.
:tcp_sum
Recomputes the TCP checksum.
:tcp_hlen
Recomputes the TCP header length. Useful after options are added.
166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/packetfu/protos/tcp.rb', line 166 def tcp_recalc(arg=:all) case arg when :tcp_sum tcp_calc_sum when :tcp_hlen @tcp_header.tcp_recalc :tcp_hlen when :all @tcp_header.tcp_recalc :all tcp_calc_sum else raise ArgumentError, "No such field `#{arg}'" end end |