-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcp_idle.py
155 lines (123 loc) · 4.39 KB
/
tcp_idle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
TCP Idle scan
nmap flags: -sI
This script is based on the following article:
https://nmap.org/book/idlescan.html
"""
import socket
import time
from impacket import ImpactPacket, ImpactDecoder
from impacket.ImpactPacket import TCP
src = '10.0.2.15' # Ubuntu 20.04.3 LTS
zombie = '10.0.2.6' # Windows XP SP3
target = '10.0.2.4' # Parrot 4.11 64-bit
sport = 12345 # Random source port
dport = 80 # Port that we want to probe
'''
Step 1: Send a SYN/ACK to get the initial IP ID of the Zombie
'''
print("* Starting Step 1 of the TCP Idle Scan")
# Construct the IP Packet for Zombie
ip = ImpactPacket.IP()
ip.set_ip_src(src)
ip.set_ip_dst(zombie)
# Construct the TCP Segment
tcp = ImpactPacket.TCP()
tcp.set_th_sport(sport) # Set the source port in TCP header
tcp.set_th_dport(dport) # Set the destination port in TCP header
tcp.auto_checksum = 1
# Set the SYN/ACK flag bit
tcp.set_SYN()
tcp.set_ACK()
# Put the TCP Segment into the IP Packet
ip.contains(tcp)
# Create a Raw socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, 6)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# Send the packet to Zombie
s.sendto(ip.get_packet(), (zombie, 0))
packet = s.recvfrom(4096)[0]
res_ip = ImpactDecoder.IPDecoder().decode(packet)
res_tcp: TCP = res_ip.child()
flag_bits = bin(res_tcp.get_th_flags())[2:].zfill(6)
initial_IP_ID = 0
# Flag format: URG-ACK-PSH-RST-SYN-FIN
# if RST is set
if flag_bits == '000100':
print("* As expected, Zombie sent an RST.")
else:
print("* Zombie didn't send an RST. That's unexpected. The response flags is %s and 000100 was expected instead" % flag_bits)
# Capture the initial IP ID of the Zombie
initial_IP_ID = res_ip.get_ip_id()
print('* Initial Zombie IP ID: %d' % initial_IP_ID)
#######################################################################
'''
Step 2: Forge a SYN packet that appears to be coming from Zombie to the Target
'''
print("* Starting Step 2 of the TCP Idle Scan")
# Construct the fake IP Packet for the Target
ip = ImpactPacket.IP()
ip.set_ip_src(zombie)
ip.set_ip_dst(target)
# Construct the TCP Segment
tcp = ImpactPacket.TCP()
tcp.set_th_sport(sport) # Set the source port in TCP header
tcp.set_th_dport(dport) # Set the destination port in TCP header
tcp.auto_checksum = 1
# Set the SYN flag bit
tcp.set_SYN()
# Put the TCP Segment into the IP Packet
ip.contains(tcp)
# Send the packet to Target
s.sendto(ip.get_packet(), (target, 0))
print("* Sleeping for 2 seconds to allow the Target send it's response to Zombie")
time.sleep(2)
#######################################################################
'''
Step 3: Probe the IP ID of the Zombie again
'''
print("* Starting Step 3 of the TCP Idle Scan")
# Construct the IP Packet for Zombie
ip = ImpactPacket.IP()
ip.set_ip_src(src)
ip.set_ip_dst(zombie)
# Construct the TCP Segment
tcp = ImpactPacket.TCP()
tcp.set_th_sport(sport) # Set the source port in TCP header
tcp.set_th_dport(dport) # Set the destination port in TCP header
tcp.auto_checksum = 1
# Set the SYN/ACK flag bit
tcp.set_SYN()
tcp.set_ACK()
# Put the TCP Segment into the IP Packet
ip.contains(tcp)
# Send the packet to Zombie
s.sendto(ip.get_packet(), (zombie, 0))
packet = s.recvfrom(4096)[0]
res_ip = ImpactDecoder.IPDecoder().decode(packet)
res_tcp: TCP = res_ip.child()
flag_bits = bin(res_tcp.get_th_flags())[2:].zfill(6)
if flag_bits == '000100':
print("* As expected, Zombie sent an RST.")
else:
print("* Zombie didn't send an RST. The response flags is "+flag_bits)
updated_IP_ID = res_ip.get_ip_id()
print('* Updated Zombie IP ID: %d' % updated_IP_ID)
# Get the IP ID difference
IP_ID_diff = updated_IP_ID - initial_IP_ID
if IP_ID_diff == 2:
print('!!! Port %d of the target is open' % dport)
elif IP_ID_diff == 1:
print('!!! Port %d of the target is closed' % dport)
else:
print('??? IP ID difference is unexpected (%d). The Zombie might be having some other network traffic going on' % IP_ID_diff)
print('* Try re-running this script again.')
'''
In the real world, searching for a Zombie machine is a herculean task in my opinion.
The machine should have a global IP ID and should increase by 1 for every packet
and should have little to no network activity on it.
We can use the following nmap command to find the IP ID Sequence Generation on a machine:
sudo nmap -O -v <ip>
just use -v when doing OS detection and if we get 'IP ID Sequence Generation' as 'Incremental', then that is
the suitable Zombie for us.
'''