# Contemporaneous Open

This is a challenge where we need to manipulate TCP packets. When we connect
to the server, we need to provide an IP to ther server, then it  
can send the flag in a POST request form, it explicitly says that no SYN+ACK
packets will be received to the server, so the 3-way handshake will  
not be possible. But, is there another way to connect with the server using
TCP ? The answer is yes! and the hint is in the challenge's name.  
There is a alternative way to create a TCP connection called "TCP Simultaneous
Open" (explanation [here](https://diameter-
protocol.blogspot.com/2014/03/simultaneous-open-tcp-connections.html)) which
consists in the two devices will  
act as a server and client at the same time, and the connection is established
when both responds to a special SYN packet.

So, in this challenge we need to create that kind connection first in order
the server can be able to send us the flag.

I had in my pending projects, write a packet sniffer with Python, so I put my
hands on this. This can be simply done with the Scapy framework  
but, I prefer to do it using sockets, this way I can see and manipulate raw
data.  
![screenshot](https://github.com/stevenvegar/CTF-
Tools/blob/main/NahamCon22/ContemporaneousOpen/ContemporaneousOpen.png)

## [frame_sniffer.py](https://github.com/stevenvegar/CTF-
Tools/blob/main/NahamCon22/ContemporaneousOpen/frame_sniffer.py)  
This script captures the ethernet frames, here we can grab the information
from OSI-layer 2, which means, we can clasify frames depending on  
their [EtherType](https://en.wikipedia.org/wiki/EtherType). In this case, we
will capture IPv4 only frames. The script grabs all the raw information and
declare them into variables, useful  
when we need to manipulate or get a specific packet field. This script
captures <ins>inbound and outbound frames</ins>, works in Linux only.  
```bash  
└──╼ $sudo python3 frame_sniffer.py  
SourceMAC:08:00:27:xx:xx:xx DestinationMAC:e4:8d:8c:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:23257 Offset:0x4000 TTL:64  
TotalLength:412 IPHeadLength:20 Checksum:0xcfdc TCPHeadLength:32
Checksum:0x1035  
SrcAddress:192.168.XX.XX SrcPort:36880 DstAddress:23.239.29.5 DstPort:80  
SeqNum:54073446 AckNum:2448585548 Flags:PSH+ACK WindowSize:501 Pointer:0  
Data: 360  
GET / HTTP/1.1  
Host: openspeedtest.com  
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0  
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
Accept-Encoding: gzip, deflate  
\-------------------------------------------------------------------------------------  
SourceMAC:e4:8d:8c:xx:xx:xx DestinationMAC:08:00:27:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:52906 Offset:0x4000 TTL:51  
TotalLength:52 IPHeadLength:20 Checksum:0x6a73 TCPHeadLength:32
Checksum:0x5d9c  
SrcAddress:23.239.29.5 SrcPort:80 DstAddress:192.168.XX.XX DstPort:36880  
SeqNum:2448585548 AckNum:54073806 Flags:ACK WindowSize:505 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------  
```

## [packet_sniffer.py](https://github.com/stevenvegar/CTF-
Tools/blob/main/NahamCon22/ContemporaneousOpen/packet_sniffer.py)  
This script is similar to the above, but this captures only TCP <ins>inbound
packets</ins> and doesn't shows link layer info.  
```bash  
└──╼ $sudo python3 packet_sniffer.py  
Version:4 Protocol:TCP(6) DSCP:0 ID:26910 Offset:0x4000 TTL:41  
TotalLength:52 IPHeadLength:20 Checksum:0x3ccf TCPHeadLength:32 Checksum:0xb1b  
SrcAddress:188.184.21.108 SrcPort:80 DstAddress:192.168.XX.XX DstPort:49200  
SeqNum:3925070653 AckNum:385774714 Flags:ACK WindowSize:235 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------  
Version:4 Protocol:TCP(6) DSCP:0 ID:26911 Offset:0x4000 TTL:41  
TotalLength:930 IPHeadLength:20 Checksum:0x3960 TCPHeadLength:32
Checksum:0x8f91  
SrcAddress:188.184.21.108 SrcPort:80 DstAddress:192.168.XX.XX DstPort:49200  
SeqNum:3925070653 AckNum:385774714 Flags:PSH+ACK WindowSize:235 Pointer:0  
Data: 878  
HTTP/1.1 200 OK  
Date: Fri, 06 May 2022 18:54:19 GMT  
Server: Apache  
Last-Modified: Wed, 05 Feb 2014 16:00:31 GMT  
Content-Length: 646  
Content-Type: text/html

<html><head></head><body><header>  
```

### TODO:  
\- Add support to capture other IP packet types (UDP, ICMP, etc).  
\- Add filters specifing them with parameters.  
\- Save output to pcap file.

## Solving the challenge  
First, as the server is requesting our IP address, this should be a public IP
address and we need to receive it requests directly to our machine so,  
we need to do a NAT port forwarding on our ISP and home's router. All packets
with the destination port = 80 received at our IP public address should be  
redirected to out home's router and it should redirect it again to out machine
within the local network. This is a little networking basics.

chall-server -> our public address -> ISP router -> home's router -> out
attacking machine

Then, let's try to capture the packets sent by the challenge server using the
frame_sniffer.py script and analyze them. Also, let's put a filter in our
frame_sniffer.py to visualize only the packets with src_port or dst_port = 80.
Also, remember to rename this script to TCPSimultaneousOpen.py to avoid re-
write the original code.

```python  
#before the script prints the packet info, add an "if" condition  
....  
if source_port == 80 or dest_port == 80:  
#prints all the info  
print ('SourceMAC:' + eth_addr(raw_frame[6:12]) + ' DestinationMAC:' +
eth_addr(raw_frame[0:6]) + ' Protocol:' + str(eth_proto))  
print ('Version:' + str(IP_ver) + ' Protocol:' + str(proto) + ' DSCP:' +
str(tos) + ' ID:' + str(pid) + ' Offset:' + str(hex(offset)) + ' TTL:' +
str(ttl))  
....  
```

```bash  
└──╼ $sudo python3 TCPSimultaneousOpen.py  
SourceMAC:e4:8d:8c:xx:xx:xx DestinationMAC:08:00:27:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:43085 Offset:0x4000 TTL:56  
TotalLength:60 IPHeadLength:20 Checksum:0x4324 TCPHeadLength:40
Checksum:0xc263  
SrcAddress:34.121.91.31 SrcPort:50746 DstAddress:192.168.XX.XX DstPort:80  
SeqNum:513852226 AckNum:0 Flags:SYN WindowSize:42600 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------  
SourceMAC:08:00:27:xx:xx:xx DestinationMAC:e4:8d:8c:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:0 Offset:0x4000 TTL:64  
TotalLength:40 IPHeadLength:20 Checksum:0xe385 TCPHeadLength:20
Checksum:0xb017  
SrcAddress:192.168.XX.XX SrcPort:80 DstAddress:34.121.91.31 DstPort:50746  
SeqNum:0 AckNum:513852227 Flags:RST+ACK WindowSize:0 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------  
```

As we can see, the challenge server sends a SYN packet and our machine
responds to it with a RST+ACK packet because it doesn't expect to receive a
connection over HTTP. Following the "TCP Simultaneous Open" procedure, we need
to send to the server a SYN packet equal to the one received and another
packet with the ACK flag to acknowledge the first SYN sent by the server.
Remember that the server will not receive SYN+ACK packets, instead, we will
send a simple ACK packet to tell the server we are ready to connect.

In order to connect with the server we need to create the following packets:  
\- SYN packet:  
\- srce IP : our machine's IP  
\- dest IP : server's IP (taken from the server's SYN source IP)  
\- srce port : 80  
\- dest port : server's source port (taken from the server's SYN source port)  
\- seq num : 0  
\- TCP flags : SYN

\- ACK packet:  
\- pack id : server's SYN packet id + 1  
\- srce IP : our machine's IP  
\- dest IP : server's IP (taken from the server's SYN source IP)  
\- srce port : 80  
\- dest port : server's source port (taken from the server's SYN source port)  
\- seq num : server's SYN packet ack num + 1  
\- ack num : server's SYN packet seq num + 1  
\- TCP flags : ACK

I know, it's a little confusing, but it makes stronger our knowlegde in how
TCP works and our packet-level understanding. What we are about to do is
[this](http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm):

![screenshot](http://www.tcpipguide.com/free/diagrams/tcpopensimul.png)

Next step is to get rid of the RST+ACK packet sent by our machine. This can be
done with the help of iptables included in our machine or with a external
firewall in our local network. The easiest way is to set a new iptables rule
to stop (drop) RST packets get out from our machine, we can achieve it with
the following command:  
```bash  
sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST --sport 80 -j DROP  
```  
(thanks to [yetanotherf0rked](https://github.com/yetanotherf0rked) for this
command in his writeup)

Now, let's create the syntax for our packets and make a new filter to send
them only when it's the correct moment. To do this, we have to use Scapy
framework to craft our special packets so, we will modify the following lines
in the TCPSimultaneousOpen.py script:  
```python  
#after the info is printed out from the last modification, add another "if"
condition  
....  
print ("Data Hex: " + str(data_size) + "\n" + data.hex())

if dest_port == 80 and tcp_flags(flags) == "SYN":  
send_SYN_packet(s_addr,source_port)  
send_ACK_packet(s_addr,pid,ttl,source_port,seqnum,acknum)

print ("\n" + ("-" * 85) + "\n")  
....  
```  
```python  
#at the beginning of the script, import scapy framework and declare the
functions  
from scapy.all import *  
def send_SYN_packet(s_addr,source_port):  
print ("Sending SYN packet")  
craftsyn = IP(len=40, ttl=64, src="192.168.XX.XX", dst=s_addr)/TCP(sport=80,
dport=source_port, seq=0, flags="S")  
send(craftsyn)  
print ("Custom SYN sended!")

def send_ACK_packet(s_addr,pid,ttl,source_port,seqnum,acknum):  
print ("Sending ACK packet")  
craftack = IP(len=40, id=pid+1, ttl=ttl, src="192.168.XX.XX",
dst=s_addr)/TCP(sport=80, dport=source_port, seq=acknum+1, ack=seqnum+1,
flags="A")  
send(craftack)  
print ("Custom ACK sended!")  
```

Alright, we've got everything we need set up. Let's trigger the script and
request the flag!!!

```bash  
└──╼ $nc challenge.nahamcon.com 32062  
so glad you're here! i would love to give you the flag. just give me the IP
address that's running an HTTP server, and I'll shoot you the flag
immediately.  
oh one snag, we've got some firewall issues on our side, and some important
packets are getting dropped. shouldn't be a problem for you, though.  
>>> 201.202.XXX.XXX  
here it comes!  
hmm nope looks like you didn't get it...  
```  
```bash  
└──╼ $sudo python3 TCPSimultaneousOpen.py  
SourceMAC:e4:8d:8c:xx:xx:xx DestinationMAC:08:00:27:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:24428 Offset:0x4000 TTL:56  
TotalLength:60 IPHeadLength:20 Checksum:0x8c05 TCPHeadLength:40
Checksum:0x1afa  
SrcAddress:34.121.91.31 SrcPort:44916 DstAddress:192.168.XX.XX DstPort:80  
SeqNum:422867056 AckNum:0 Flags:SYN WindowSize:42600 Pointer:0  
Data: 0

Sending SYN packet  
.  
Sent 1 packets.  
Custom SYN sended!  
Sending ACK packet  
.  
Sent 1 packets.  
Custom ACK sended!  
\-------------------------------------------------------------------------------------
↑ the first SYN packet sent by the server, and our two crafted packets sent  
SourceMAC:08:00:27:xx:xx:xx DestinationMAC:e4:8d:8c:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:1 Offset:0x0 TTL:64  
TotalLength:40 IPHeadLength:20 Checksum:0x2385 TCPHeadLength:20
Checksum:0x88d3  
SrcAddress:192.168.XX.XX SrcPort:80 DstAddress:34.121.91.31 DstPort:44916  
SeqNum:0 AckNum:0 Flags:SYN WindowSize:8192 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------
↑ our SYN sent to the server with the dst port same as src port of first
packet  
SourceMAC:08:00:27:xx:xx:xx DestinationMAC:e4:8d:8c:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:24429 Offset:0x0 TTL:56  
TotalLength:40 IPHeadLength:20 Checksum:0xcc18 TCPHeadLength:20
Checksum:0xff1e  
SrcAddress:192.168.XX.XX SrcPort:80 DstAddress:34.121.91.31 DstPort:44916  
SeqNum:1 AckNum:422867057 Flags:ACK WindowSize:8192 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------
↑ our ACK sent to the server with all modification to respond to the first
packet  
SourceMAC:e4:8d:8c:xx:xx:xx DestinationMAC:08:00:27:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:24429 Offset:0x4000 TTL:56  
TotalLength:60 IPHeadLength:20 Checksum:0x8c04 TCPHeadLength:40
Checksum:0x1a30  
SrcAddress:34.121.91.31 SrcPort:44916 DstAddress:192.168.XX.XX DstPort:80  
SeqNum:422867056 AckNum:1 Flags:SYN+ACK WindowSize:42600 Pointer:0  
Data: 0  
\-------------------------------------------------------------------------------------
↑ a SYN+ACK from the server responding to our SYN, now, the server is
connected to our machine  
SourceMAC:e4:8d:8c:xx:xx:xx DestinationMAC:08:00:27:xx:xx:xx Protocol:8  
Version:4 Protocol:TCP(6) DSCP:0 ID:24430 Offset:0x4000 TTL:56  
TotalLength:256 IPHeadLength:20 Checksum:0x8b3f TCPHeadLength:20
Checksum:0xb681  
SrcAddress:34.121.91.31 SrcPort:44916 DstAddress:192.168.XX.XX DstPort:80  
SeqNum:422867057 AckNum:1 Flags:PSH+ACK WindowSize:333 Pointer:0  
Data: 216  
POST / HTTP/1.1  
Host: 201.202.XX.XX  
User-Agent: python-requests/2.27.1  
Accept-Encoding: gzip, deflate  
Accept: */*  
Connection: keep-alive  
Content-Length: 50  
Content-Type: application/x-www-form-urlencoded

flag=flag%7B6acfdfc9369eadfdb9439b0ac3969711%7D%0A

\-------------------------------------------------------------------------------------
↑ the POST request sent from the server with the flag !!! =D  
```

That was an exciting journey, I learned a lot of new things, improved my
Python scripting skills, I didn't know anything about "TCP Simultaneous Open"
and finally I have my own packet capture script that will help me in future
CTFs.

Thanks to the players who uploaded write-ups right after the CTF finished.
Check theirs too:  
\- [yetanotherf0rked - Spending spring days crafting packets at NahamCon 2022
(1 of 3)](https://github.com/yetanotherf0rked/ctf-
writeups/blob/main/NahamCon2022/Just%20crafting%20packets%20at%20Nahamcon2022%20(1%20of%203).md)  
\- [nneonneo -
server.py](https://gist.github.com/nneonneo/1b371ac9da8703eda9c3a9b26d61a483)

Original writeup (https://github.com/stevenvegar/CTF-Writeups-and-
Tools/tree/main/NahamCon22/ContemporaneousOpen).