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)
