Shebang and Python script
A shebang refers to
two letters #!
It is also called sha-bang, hashbang, pound-bang,
or hash-pling.
Consider the following simple python file hello.py:
# hello.py
print("hello")
print("world")
Let's make the file executable, and run it.
~$ chmod 755 hello.py
~$ ./hello.py
./hello.py: line 2: syntax error near unexpected token `"hello"'
./hello.py: line 2: `print("hello")'
We see an error because we didn't give a shebang line that specifies the
interpreter to be used for this script file hello.py. So, let's add
a shebang line. Obviously, the inpterpreter is python3 whose full
path name is /usr/bin/python3.
#!/usr/bin/python3
# hello.py
print("hello")
print("world")
Now, let's run the file again:
~$ ./hello.py
hello
world
UDP Socket Spoofing
In this lecture, we learn how to spoof UDP packets. We would like to write
udp_spoof.py that will send a spoofed UDP packet.
Our Goal
We would like to fake the source IP address in the UDP packet.
For example:
- The source IP address of the UDP packet could be 123.123.123.123.
- Then the packet receiver will wrongly think that 123.123.123.123 has sent the packet.
We will demonstrate our success by showing a UDP netcat chat. We will use
serv_udp.py and check the the IP/port to see if the spoofing
works.
Socket Creation
We first create a raw socket.
Recall that IP header contains the source IP address field. This implies
that we need to craft IP header and IP payload. Fortuntately, since we don't
fake the Ethernet frame part, we simply let the OS fill out that part honestly.
This means that the raw socket that we create can be on the IP level, not the
Ethernet level.
#!/usr/bin/python3
# udp_spoof.py
from socket import *
raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)
Crafting a Packet and struct.pack
Now, we have to create a bytes object for the faked UDP packet.
We will use struct.pack.
Here's our strategy.
- We first create a bytes object
udp_payload.
- We next construct a bytes object
udp_header. Note we have
ip_payload = udp_header + udp_payload
Note: bytes objects can be concatenated
using "+" operator. For example, b"hello" + b"world" will be evaluated to
b"helloworld".
- Next construct
ip_header
- Finally, we have
ip_pkt = ip_header + ip_payload.
UDP payload
In our context, udp_payload corresponds to any chat text. Let's say:
udp_payload = b"Hello World\n"
Crafting a UDP header
See the header format on the right.
- It's easy to fill the Source Port (random), Destination Port (9000).
- The Lengh field should consider both the header and the payload (i.e.,
8 + len(udp_payload)). Note that the UDP header is 8 bytes
long (2 lines).
- Filling out Checksum seems to be difficult. Fortunately, it's fine to set
0 for this field! Recall UDP doesn't provide error-correction, so this
Checksum field is optional, but not usually used.
|
UDP Header Format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
So, we can write the following code:
import struct
udp_header = struct.pack(">HHHH", 12345, 9000, 8 + len(udp_payload), 0)
ip_payload = udp_header + udp_payload
Crafting a IP header
One way that helps is:
- Capture a normal UDP packet using wireshark.
- Mimick everything except the IP address and port number.
You can see a packet capture on the right.
We will fill out the IP header according to the format shown on the right.
- The first line:
- Version: 4
- IHL: 5 (lines for IP header)
- Type of Service: 0 (No special service)
- Total length: header length (20 bytes) + payload length.
version = 4
ihl = 5
# version is 4 bits, IHL is 4 bits
# version_ihl is 8 bits (1 byte)
version_ihl = (version << 4) | ihl
type_of_service = 0
total_length = 20 + len(ip_payload)
ip_header = struct.pack(">BBH",
version_ihl, type_of_service, total_length)
- The second line:
- Identification: Any unique number would be fine. We will set 12345.
- Fragment Offset: If you just set 0, the OS will take care of the rest.
ip_header += struct.pack(">HH", 12345, 0)
- The third line:
- TTL: Let's just set 20.
- Protocol: For UDP, you need to set 17.
- Checksum: Just put 0, and then the OS will fill in a correct value.
ttl = 20
protocol = 17
checksum = 0
ip_header += struct.pack(">BBH", ttl, protocol, checksum)
- The fourth line: source address. We spoof it to "123.123.123.123".
ip_header += struct.pack(">BBBB", 123, 123, 123, 123)
- The fifth line: destnation address. Here, we set 192.168.172.5. Change the
address according to your need. It should be the IP address of the receiving
host.
ip_header += struct.pack(">BBBB", 192, 168, 172, 5)
ip_pkt = ip_header + ip_payload
|
Internet Datagram Header
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |R D M| Fragment Offset |
| |S F F| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
Sending a Packet
You can simply use sendto() function as usual.
addr = ("192.168.172.5", 9000)
raw_socket.sendto(ip_pkt, addr)
Acitivty
- Have a UDP netcat chat. Use nc for the listening party.
- Using the above code, send a spoof packet.
- Use wireshark to capture the udp packet. See how the actual packet
contents look like.
Applications of Packet Spoofing
- Denial of Service: An attacker usually floods packets with a fake source IP
address.
- ARP Spoofing: An attacker sends fake ARP messages onto a local area
network. Generally, the aim is to associate the attacker's MAC address with
the IP address of another host, such as the default gateway, causing any
traffic meant for that IP address to be sent to the attacker instead.
- DNS Spoofing: In this attack, the perpetrator sends counterfeit DNS
replies, e.g., leading the victim to mistakenly associate www.google.com with
a malicious IP address.