### Home Classes Methods

### In Files

- lib/packetfu/protos/tcp.rb

### Parent

PacketFu::Packet

### Methods

- ::can_parse?
- ::new
- #peek_format
- #read
- #tcp_calc_flavor
- #tcp_calc_sum
- #tcp_recalc

### Included Modules

- PacketFu::EthHeaderMixin
- PacketFu::IPHeaderMixin
- PacketFu::TCPHeaderMixin

### Files

- .document
- README.rdoc

### Class/Module Index

Quicksearch

- PacketFu
- PacketFu::ARPHeader
- PacketFu::ARPHeaderMixin
- PacketFu::ARPPacket
- PacketFu::AddrIpv6
- PacketFu::Capture
- PacketFu::Config
- PacketFu::EthHeader
- PacketFu::EthHeaderMixin
- PacketFu::EthMac
- PacketFu::EthNic
- PacketFu::EthOui
- PacketFu::EthPacket
- PacketFu::HSRPHeader
- PacketFu::HSRPHeaderMixin
- PacketFu::HSRPPacket
- PacketFu::ICMPHeader
- PacketFu::ICMPHeaderMixin
- PacketFu::ICMPPacket
- PacketFu::IPHeader
- PacketFu::IPHeaderMixin
- PacketFu::IPPacket
- PacketFu::IPv6Header
- PacketFu::IPv6HeaderMixin
- PacketFu::IPv6Packet
- PacketFu::Inject
- PacketFu::InvalidHeader
- PacketFu::InvalidPacket
- PacketFu::LLDPHeader
- PacketFu::LLDPHeaderMixin
- PacketFu::LLDPPacket
- PacketFu::Octets
- PacketFu::Packet
- PacketFu::PcapFile
- PacketFu::PcapHeader
- PacketFu::PcapPacket
- PacketFu::PcapPackets
- PacketFu::Read
- PacketFu::TCPHeader
- PacketFu::TCPHeaderMixin
- PacketFu::TCPPacket
- PacketFu::TcpEcn
- PacketFu::TcpFlags
- PacketFu::TcpHlen
- PacketFu::TcpOption
- PacketFu::TcpOption::ECHO
- PacketFu::TcpOption::ECHOREPLY
- PacketFu::TcpOption::EOL
- PacketFu::TcpOption::MSS
- PacketFu::TcpOption::NOP
- PacketFu::TcpOption::SACK
- PacketFu::TcpOption::SACKOK
- PacketFu::TcpOption::TS
- PacketFu::TcpOption::WS
- PacketFu::TcpOptions
- PacketFu::TcpReserved
- PacketFu::Timestamp
- PacketFu::UDPHeader
- PacketFu::UDPHeaderMixin
- PacketFu::UDPPacket
- PacketFu::Utils
- PacketFu::Write
- StructFu
- StructFu::Int
- StructFu::Int16
- StructFu::Int16be
- StructFu::Int16le
- StructFu::Int32
- StructFu::Int32be
- StructFu::Int32le
- StructFu::Int8
- StructFu::IntString
- StructFu::String
- Struct

No matching classes.

# PacketFu::TCPPacket

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.tcp_options="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?

### Attributes

eth_header[RW]
ip_header[RW]
tcp_header[RW]

### Public Class Methods

can_parse?(str) click to toggle source

    # File lib/packetfu/protos/tcp.rb, line 47
    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

new(args={}) click to toggle source

    # File lib/packetfu/protos/tcp.rb, line 68
    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

### Public Instance Methods

peek_format() click to toggle source

TCP packets are denoted by a "T ", followed by size, source and dest information, packet flags, sequence number, and IPID.

    # File lib/packetfu/protos/tcp.rb, line 182
    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={}) click to toggle source

    # File lib/packetfu/protos/tcp.rb, line 55
    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) click to toggle source

Sets the correct flavor for TCP Packets. Recognized flavors are:

    windows, linux, freebsd

    # File lib/packetfu/protos/tcp.rb, line 89
    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.tcp_options="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.tcp_options="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.tcp_options="MSS:1460,NOP,WS:3,NOP,NOP,TS:#{ts_val};#{ts_sec},SACKOK,EOL,EOL"
                    @ip_header.ip_ttl = 64
            else
                    @tcp_header.tcp_options="MSS:1460,NOP,NOP,SACKOK"
            end
            tcp_calc_sum
    end

tcp_calc_sum() click to toggle source

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.

    # File lib/packetfu/protos/tcp.rb, line 119
    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) click to toggle source

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.

    # File lib/packetfu/protos/tcp.rb, line 165
    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

[Validate]

Generated with the Darkfish Rdoc Generator 2.