Faking it! (UDP packets that is…)

3 May, 2007 – 9:51 am

An associate of mine recently wanted a load script that could simulate thousands of UDP packets carrying a custom payload coming from different IP addresses. They were implementing a customised RFID solution that needed to simulate load from a lot of sources (think active RFID tags).

There are many different ways you can accomplish this, solutions like LoadRunner will offer the ability to spoof source IP addresses, but in this case the client couldn’t afford hefty licensing fees. So getting back to basics, I launched the *flood* from a cygwin shell running ruby.

The code looked a little like this…


UDP Faker.rb

def ipchecksum(data)
    checksum = data.unpack("n*").inject(0) { |s, x| s + x }
    ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end
 
require 'socket'
 
class UDP_Faker
 
    @@id = 1234 - 1
 
    def initialize
        @s = Socket.new(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
        @s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, 1)
    end
 
    def send(src, sport, dst, dport, payload = '')
        dst_numeric = dst.split(/\./).map { |x| x.to_i }
        to = [ Socket::AF_INET,
            dport, dst_numeric, '' ].flatten.pack('snCCCCa8')
        packet = make_ip_header([
            [ '01000101', 'B8' ],                # version, hlen
            [ 0, 'C' ],                          # tos
            [ 28 + payload.size, 'n' ],          # total len
            [ @@id += 1, 'n' ],                  # id
            [ 0, 'n' ],                          # flags, offset
            [ 64, 'C' ],                         # ttl
            [ 17, 'C' ],                         # protocol
            [ 0, 'n' ],                          # checksum
            [ ip2long(src), 'N' ],               # source
            [ ip2long(dst), 'N' ],               # destination
        ])
        packet << make_udp_header([
            [ sport, 'n'],                        # source port
            [ dport, 'n' ],                       # destination port
            [ 8 + payload.size, 'n' ],            # len
            [ 0, 'n' ]                            # checksum (mandatory)
        ])
        packet << payload
        @s.send(packet, 0, to)
    end
 
    private
 
    def ip2long(ip)
        long = 0
        ip.split(/\./).reverse.each_with_index do |x, i|
            long += x.to_i << (i * 8  )
        end
        long
    end
 
    def ipchecksum(data)
        checksum = data.unpack("n*").inject(0) { |s, x| s + x }
        ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
    end
 
    def make_ip_header(parts)
        template = ''
        data = []
        parts.each do |part|
            data += part[0..-2]
            template << part[-1]
        end
        data_str = data.pack(template)
        checksum = ipchecksum(data_str)
        data[-3] = checksum
        data.pack(template)
    end
 
    def make_udp_header(parts)
        template = ''
        data = []
        parts.each do |part|
            data += part[0..-2]
            template << part[-1]
        end
        data.pack(template)
    end
 
end
 
testRun = UDP_Faker.new
loop do
  #             Source IP       Port  Destination IP   Port   Payload
  testRun.send('203.64.36.24', 2069, '124.191.161.6', 81,    'Blob: here comes the data ...')
end
# TODO: Loop through a range of source IP addy's.
# Return response from server. Use correctly formatted blob.

In a similar vein, but long since shutdown, the guys at Hackers Choice provided some excellent C code for flooding TCP connections, which I also found useful in this project in order to conduct some stress to break testing. Understandably, some people might misuse this script, but for internal uses, I found it extremely useful to flood the TCP/IP stack. You can dowload the code here: flood_connect.c

It’s usage is along the lines of this:

Options:
    -S           use SSL after TCP connect (not usuable with -u, sets port=443)
    -u           use UDP protocol (default: TCP) (not usable with -c)
    -p port      port to connect to (default: %d)
    -f forks     number of forks to additionally spawn (default: 0)
    -i file      data to send to the port (default: none)
    -n connects  maximum number of connects (default: unlimited)
    -N delay     delay between connects in ms (default: 0)
    -c           close after connect (and sending data, if used with -i)
                 use twice to shutdown SSL sessions hard (-S -c -c)
    -C delay     delay before closing the port (for use with -c) (default: 0)
    -d           dump data read from server
    -D delay     delay before trying to read+dump data from server (default: 0)
    -e           stop when no more connects possible (default: retry forever)
    -k           no keep-alive after finnishing with connects, terminate!
    -v           verbose mode
    TARGET       target to flood attack (ip or dns)

Share it: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Netscape
  • Reddit
  • Slashdot
  • Technorati
  • YahooMyWeb

Post a Comment

*
To prove that you're not a bot, enter this code
Anti-Spam Image