Art of Manually Crafting Packets (TCP/IP).
Tags: security, python, cybersecurity
Published: 2023-05-13 09:46:39

Dissecting the TCP/IP packet. What’s inside the packet, in detail.

GitHub: [Salah Ud Din — 4yub1k](https://github.com/4yub1k)

After reading tons of articles, blogs, and testing. I wrote this article complete to the point and easy to understand. I hope you’ll enjoy it.

**Make sure you read this introductory article before starting. [[READ](https://dev.to/4yub1k/what-is-tcpip-explained-in-detail-34d3)]**

To install Python: [[LINK](https://dev.to/4yub1k/easy-how-to-set-up-python-and-visual-studio-code-on-windows-10-5gon)]

This article and script is purely for educational purposes. Ignore mistakes.

#### IP:

![IP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tea0hjk3r4wehjtiot70.jpg)

**IMPORTANT:**
You must make a minimum 8 bit word, for any calculation (except Addition see checksum), if it is in hex or binary in order to avoid errors. And fill the zeros as shown in figure above.

**Examples:**

- Version + IHL & TOS ( Type Of Service) = 0x45 is 8 bit, and 0x00 is also 8 bit word (1 Byte) , In binary = 01000101 00000000 16 bits.
- Flags & Fragment Offset = (000 3 bit) & (000000000 13 bit), But for calculation make a 8 bit word or 1 byte, Binary = 00000000 0000000 = 00 00.
- You can’t write protocol only 0x6 as it will be considered as 4 bit, so it must be 0x06, Binary = 00000110 = 06 = 0x06. No room to drop any bit even if it is ‘0’ as Leading.
- As in figure above there are total 5 rows, each row is of 32 bits, divided in 16 bits of chunks except the address rows.

#### We need for IP:

- Version : 4 bit
- IHL : 4 bit
- Type Of Service : 8 bit
- Total Length : 16 bit
- Identification : 16 bit
- Flag : 3 bit
- Fragment Offset : 13 bit
- Time To live (TTL) : 8 bit
- Protocol : 8 bit
- Header Checksum : 16 bit
- Source Address : 32 bits
- Destination Address : 32 bits

#### IHL:
Number of 32 bit words in packet: Count the number of fields/rows in above figure = 5. So, IHL will be 5 = 0x5 (4 bit).

#### Total Length:
Combine length of 32 bit word in both (IP and TCP). In short number of rows of 32 bit words in packet.
*we will fill it after filling TCP header.

#### Identification:
Take any random value less then 0xFFFF (16 bit). It is only for packet identity.

#### Flags + Fragment:
In bits 000 + 0000000000, you can leave it as it is but if you want to use it then,

**Do not fragment packet :**
Flag bit = 010 + 00000 00000000 = 01000000 00000000 = 4 0, combine them as they are 16 bit word = 0x40

#### Time To Live ( TTL ):
Every time a router forwards the packet, it decrements the TTL field in the packet header, and if the value reaches zero, the packet is dropped.
Value Ranges from 0–225, 0x00–0xFF as it is 8 bit.
Example : 64 decimal = 0x40 Hex.

#### Protocol :

- TCP = 06
- ICMP = 01
To know more Internet Protocols : [GOTO](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)

#### Header Checksum :
For the calculations, all necessary values are used in 16 bit words and added together. In case the value isn’t 16 bit long, it will be prepended with zeros. 0x6 = 0x0006 (16 bit).

> “|” means concatenate the bits.

You can see we have divided the IP Address in 16 bit word instead of 32 bit.

`Checksum = (Version | IHL | Type of Service) + Total Length + Identification + (Flags | Fragment Offset) + (TTL | Protocol + Header Checksum (0x0000 in calculation) ) + Source Address (IP) + Destination Address (IP)`


*if value of Checksum is greater then 0xFFFF then there will be a carry, 0x12345 → 0x2345 + 0x0001 = 0x2346 , This is how we can compensate carryover.
Total Checksum will be subtract 0x2346 from 0xFFF.
Checksum = Checksum + carryover (if any)

Total Checksum = 0xFFFF — ( checksum ), Negation with (0xFFFF)

#### Source & Destination IP :
Convert IP address to Hex values.
192.168.242.133
192 = 0xc0.
168 = 0xa8.
242 = 0xf2.
133 = 0x85.

#### TCP:

![TCP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/57qqwr5lf117l394c36c.jpg)

#### We need for TCP:

- Source Port : 16 bit
- Destination Port : 16 bit
- Sequence Number : 32 bit
- Acknowledgement Number : 32 bit
- Data Offset : 4 bit
- Reserved : 3 bit
- Flags : 9 bit
- Checksum : 16 bit
- Urgent Pointer : 16 bit

#### Source & Destination Port :
Decimal port value to hex value,
12336 = 0x3030
80 = 0x50

#### Ack & Sequence Number:
They are set to 0x0000 & 0x0000 initially.

#### Data Offset :
Is the number of 32 bit word in TCP header, count the row = 5 in above figure, There are ‘5’ 32 bit words. 0x5 = Binary = 0101. (Data offset is 4 bit).

#### Flags:
As we want to send a SYN request, the SYN bit will be set to 1 as in shown above.
000000010 = 0x2

#### Window Size:
Used for flow control, 2 bytes long, we chose a random value not too much large.
Window size= bandwidth(Mbits connection) x delay(ms),
For detail : GOTO

#### TCP Checksum:
Checksum consists of values of the TCP Header itself and a Pseudo Header. For the calculations, all necessary values are used in 16 bit words and added together.
In case the value isn’t 16 bit long, it will be prepended with zeros.

#### Pseudo Header:
The TCP pseudo header is used to associate the TCP segment with the IP header. The TCP pseudo header is added to the beginning of the TCP segment only during the checksum calculation and is not sent as part of the TCP segment.

Why? The use of the TCP pseudo header assures the receiver that a routing or fragmentation process did not improperly modify key fields in the IP header.
In short it makes sure that TCP datagram (packet) has reached correct destination.

#### Calculation:
Pseudo = Protocol + Source Address (IP) + Destination Address (IP) + TCP length (including the data part) in byte (no actual header field, has to be counted)

**TCP Checksum:**
`TCP header = Source Port + Destination Port + Sequence Number + Acknowledgement Number + (Data Offset | Reserved | Flags ) + Window Size + Checksum (set to 0x0000 in calculation) + Urgent Pointer
`
*if value of TCP header is greater then 0xFFFF then there will be a carry, 0x12345 → 0x2345 +0x0001 = 0x2346 , This how to compensate carryover.
Total will be 0xFFF — 0x2346 =
TCP Header = TCP header + carryover(if any).

Total Checksum = 0xFFF — ( Pseudo + TCP header ) , Negation with (0xFFFF)

#### Urgent Pointers:
If the URG flag is set, the urgent pointer points to the sequence number of the byte following the urgent data,
As its name says Urgent it will point to urgent data/priority, Must be processed urgently.

#### Let’s see the final packet after filling the values:


![TCP/IP Packet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4mov59ngw4cncf888n90.jpg)

> After filling the values you have to update few values Total length and Protocol you want to use.

#### Some Updates in IP Header :
**Total Length: ( IP )**
Total number of bytes in 32 bit words in the packet. Here number of 32 bit word (rows), above = 10 rows, and each row is of 4 byte.
10 x 4 = 40 bytes = 0x0028. (Convert Decimal 40 to Hex)

**Protocol:**
Protocol = 06 for TCP

Now, start Wireshark, and filter for source ip -> ip.addr=<source_ip>.

#### Run the script:
Download the script [[GOTO](https://github.com/4yub1k/tcp_ip)]
`python3 tcp_ip.py -h`

TCP/IP Crafting : GitHub @4yub1k 
**arguments:**

-   -h, --help        show this help message and exit
-   -s , --srcip      Source Ip address.
-   -sp , --srcport   Source port.
-   -d , --dstip      Destination Ip address.
-   -dp , --dstport   Destination port.
-   -t , --timeout    Wait for response.(Default=5 secs)

Example:
`python3 tcp_ip.py -s=192.168.0.16 -sp=12333 -d=192.168.0.1 -dp=80 -t=2`

Change values and run the script.

#### Wireshark:


![Wireshark](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zo7k6ksoljis6anjkhvm.png)

#### Packet Sent:
**IP:**


![IP Bytes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w33p431m1tfzyt3xbf2y.png)

**TCP:**

![TCP Bytes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wcrsa3ama2271j40mqq8.png)

#### Packet Received:

![Packet Received](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cn63uddawn255fsfabir.png)

#### Output of Script:


![IP Checksum](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06tzaogk1z9oxagj4ze9.png)

![TCP Checksum](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rqznra050yjeq5y0rdg.png)


![Final Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5ap3w5h55049ho59zz4.png)

That’s it Use Wireshark and study the packet, with script.

Yes, you can spoof the mac address and IP. The response will be sent to the source MAC/IP used. For more try it out 😂😎.

To change MAC address just add them like this before packet. That’s it.

- Destination: 62:3a:35:6c:49:0a (62:3a:35:6c:49:0a)
- Source: VMware_f4:e7:ac (00:0c:29:f4:e7:ac)
- Type: IPv4 (0x0800)


![MAC/IP Spoof](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvhvd8el4l72gfcucuwz.png)

#### Notes (Quick Revision):
TCP Header is HEX string.
TCP Bytes is ByteArray of HEX string.

This is how we can send these bytes (16 bit of word).
(“ | ” ) is concatenation.

`Packet = (Version | IHL | Type Of Service) + Total Length + Identification + (Flags | Fragment Offset) + (Time To Live | Protocol) + Header Checksum(IP) + Source Address+ Destination Address + Source Port + Destination Port + Sequence Number + Acknowledgement Number + (Data Offset | Flags) + Window Size + Checksum(TCP) + Urgent Pointer.`

`Packet = 4500 + 0028 + abcd + 0000 + 4006 + d7ab + c0a8 + f285 + 8efa + b52e + 3030 + 0050 + 0000 + 0000 + 0000 + 0000 + 5002 + 7110 + 16fb + 0000`

#### Final Packet in Bytes:

`Packet = b'\x45\x00\x00\x28\xab\xcd\x00\x00\x40\x06\xd7\xab\xc0\xa8\xf2\x85\x8e\xfa\xb5\x2e\x30\x30\x00\x50\00\x00\x00\x00\x00\x00\x00\x00\x50\x02\x71\x10\x16\xfb\x00\x00'`

e-g They are \x(1 byte) \x(1 byte)……….. You have to send them exactly like this. \x45 = 1 Byte = 8 bits. (Here 4 = 4 bit, 5 = 4 bit). So, 45 = 4+4 = 8 bits.

I hope you understood everything. 😎👍