Scapy is a very easy to use tool and makes it really simple to create your own packets and understand what request packet is being sent and what response packet is being received.
TCP
connect scan
TCP
connect is a three-way handshake between the client and the server. If the
three-way handshake takes place, then communication has been established.
A
client trying to connect to a server on port 80 initializes the connection by sending
a TCP packet with the SYN flag set and the port to which it wants to connect
(in this case port 80). If the port is open on the server and is accepting
connections, it responds with a TCP packet with the SYN and ACK flags set. The
connection is established by the client sending an acknowledgement ACK and RST
flag in the final handshake. If this three-way handshake is completed, then the
port on the server is open.
The
client sends the first handshake using the SYN flag and port to connect to the
server in a TCP packet. If the server responds with a RST instead of a SYN-ACK,
then that particular port is closed on the server.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
tcp_connect_scan_resp
=
sr1(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=10)
if(str(type(tcp_connect_scan_resp))=="<type
'NoneType'>"):
print
"Closed"
elif(tcp_connect_scan_resp.haslayer(TCP)):
if(tcp_connect_scan_resp.getlayer(TCP).flags
== 0x12):
send_rst
=
sr(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="AR"),timeout=10)
print
"Open"
elif
(tcp_connect_scan_resp.getlayer(TCP).flags == 0x14):
print
"Closed"
TCP stealth
scan
This
technique is similar to the TCP connect scan. The client sends a TCP packet
with the SYN flag set and the port number to connect to. If the port is open,
the server responds with the SYN and ACK flags inside a TCP packet. But this
time the client sends a RST flag in a TCP packet and not RST+ACK, which was the
case in the TCP connect scan. This technique is used to avoid port scanning
detection by firewalls.
The
closed port check is same as that of TCP connect scan. The server responds with
an RST flag set inside a TCP packet to indicate that the port is closed on the
server
The
Code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
stealth_scan_resp
=
sr1(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=10)
if(str(type(stealth_scan_resp))=="<type
'NoneType'>"):
print
"Filtered"
elif(stealth_scan_resp.haslayer(TCP)):
if(stealth_scan_resp.getlayer(TCP).flags
== 0x12):
send_rst
=
sr(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="R"),timeout=10)
print
"Open"
elif
(stealth_scan_resp.getlayer(TCP).flags == 0x14):
print
"Closed"
elif(stealth_scan_resp.haslayer(ICMP)):
if(int(stealth_scan_resp.getlayer(ICMP).type)==3
and int(stealth_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
print
"Filtered"
XMAS
scan
In the
XMAS scan, a TCP packet with the PSH, FIN, and URG flags set, along with the
port to connect to, is sent to the server. If the port is open, then there will
be no response from the server.
If the
server responds with the RST flag set inside a TCP packet, the port is closed
on the server.
If the
server responds with the ICMP packet with an ICMP unreachable error type 3 and
ICMP code 1, 2, 3, 9, 10, or 13, then the port is filtered and it cannot be
inferred from the response whether the port is open or closed.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
xmas_scan_resp
= sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="FPU"),timeout=10)
if
(str(type(xmas_scan_resp))=="<type 'NoneType'>"):
print
"Open|Filtered"
elif(xmas_scan_resp.haslayer(TCP)):
if(xmas_scan_resp.getlayer(TCP).flags
== 0x14):
print
"Closed"
elif(xmas_scan_resp.haslayer(ICMP)):
if(int(xmas_scan_resp.getlayer(ICMP).type)==3
and int(xmas_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
print
"Filtered"
FIN
scan
The FIN
scan utilizes the FIN flag inside the TCP packet, along with the port number to
connect to on the server. If there is no response from the server, then the
port is open.
If the
server responds with an RST flag set in the TCP packet for the FIN scan request
packet, then the port is closed on the server.
An ICMP
packet with ICMP type 3 and code 1, 2, 3, 9, 10, or 13 in response to the FIN
scan packet from the client means that the port is filtered and the port state
cannot be found.
The
code:
#!
/usr/bin/python
import
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
fin_scan_resp
= sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="F"),timeout=10)
if
(str(type(fin_scan_resp))=="<type 'NoneType'>"):
print
"Open|Filtered"
elif(fin_scan_resp.haslayer(TCP)):
if(fin_scan_resp.getlayer(TCP).flags
== 0x14):
print
"Closed"
elif(fin_scan_resp.haslayer(ICMP)):
if(int(fin_scan_resp.getlayer(ICMP).type)==3
and int(fin_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
print
"Filtered"
NULL
scan
In a
NULL scan, no flag is set inside the TCP packet. The TCP packet is sent along
with the port number only to the server. If the server sends no response to the
NULL scan packet, then that particular port is open.
If the
server responds with the RST flag set in a TCP packet, then the port is closed
on the server.
An ICMP
error of type 3 and code 1, 2, 3, 9, 10, or 13 means the port is filtered on
the server.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
null_scan_resp
= sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags=""),timeout=10)
if
(str(type(null_scan_resp))=="<type 'NoneType'>"):
print
"Open|Filtered"
elif(null_scan_resp.haslayer(TCP)):
if(null_scan_resp.getlayer(TCP).flags
== 0x14):
print
"Closed"
elif(null_scan_resp.haslayer(ICMP)):
if(int(null_scan_resp.getlayer(ICMP).type)==3
and int(null_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
print
"Filtered"
TCP ACK
scan
The TCP
ACK scan is not used to find the open or closed state of a port; rather, it is
used to find if a stateful firewall is present on the server or not. It only
tells if the port is filtered or not. This scan type cannot find the
open/closed state of the port.
A TCP
packet with the ACK flag set and the port number to connect to is sent to the
server. If the server responds with the RSP flag set inside a TCP packet, then
the port is unfiltered and a stateful firewall is absent.
If the
server doesn’t respond to our TCK ACK scan packet or if it responds with a TCP
packet with ICMP type 3 or code 1, 2, 3, 9, 10, or 13 set, then the port is
filtered and a stateful firewall is present.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
ack_flag_scan_resp
= sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="A"),timeout=10)
if
(str(type(ack_flag_scan_resp))=="<type 'NoneType'>"):
print
"Stateful firewall presentn(Filtered)"
elif(ack_flag_scan_resp.haslayer(TCP)):
if(ack_flag_scan_resp.getlayer(TCP).flags
== 0x4):
print
"No firewalln(Unfiltered)"
elif(ack_flag_scan_resp.haslayer(ICMP)):
if(int(ack_flag_scan_resp.getlayer(ICMP).type)==3
and int(ack_flag_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
print
"Stateful firewall presentn(Filtered)"
TCP
window scan
A TCP
window scan uses the same technique as that of TCP ACK scan. It also sends a
TCP packet with the ACK flag set and the port number to connect to. But this
scan type can be used to find the state of the port on the server. In a TCP ACK
scan, an RST indicates an unfiltered state. But in a TCP windows scan, when an
RST is received from the server, it then checks the value of the windows size.
If the value of window size is positive, then the port is open on the server.
If the
windows size of the TCP packet with the RST flag set to zero, then the port is
closed on the server.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=80
window_scan_resp
= sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="A"),timeout=10)
if
(str(type(window_scan_resp))=="<type 'NoneType'>"):
print
"No response"
elif(window_scan_resp.haslayer(TCP)):
if(window_scan_resp.getlayer(TCP).window
== 0):
print
"Closed"
elif(window_scan_resp.getlayer(TCP).window
> 0):
print
"Open"
UDP
scan
TCP is
a connection-oriented protocol and UDP is a connection-less protocol.
A
connection-oriented protocol is a protocol in which a communication channel
should be available between the client and server and only then is a further
packet transfer made. If there is no communication channel between the client
and the server, then no further communication takes place.
A
Connection-less protocol is a protocol in which a packet transfer takes place
without checking if there is a communication channel available between the
client and the server. The data is just sent on to the destination, assuming
that the destination is available.
The
client sends a UDP packet with the port number to connect to. If the server
responds to the client with a UDP packet, then that particular port is open on
the server.
The
client sends a UDP packet and the port number it wants to connect to, but the
server responds with an ICMP port unreachable error type 3 and code 3, meaning
that the port is closed on the server.
If the
server responds to the client with an ICMP error type 3 and code 1, 2, 9, 10,
or 13, then that port on the server is filtered.
If the
server sends no response to the client’s UDP request packet for that port, it
can be concluded that the port on the server is either open or filtered. No
final state of the port can be decided.
The
code:
#!
/usr/bin/pythonimport
logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
fromscapy.all
import *
dst_ip
= "10.0.0.1"
src_port
= RandShort()
dst_port=53
dst_timeout=10
defudp_scan(dst_ip,dst_port,dst_timeout):
udp_scan_resp
= sr1(IP(dst=dst_ip)/UDP(dport=dst_port),timeout=dst_timeout)
if
(str(type(udp_scan_resp))=="<type 'NoneType'>"):
retrans
= []
for
count in range(0,3):
retrans.append(sr1(IP(dst=dst_ip)/UDP(dport=dst_port),timeout=dst_timeout))
for
item in retrans:
if
(str(type(item))!="<type 'NoneType'>"):
udp_scan(dst_ip,dst_port,dst_timeout)
return
"Open|Filtered"
elif
(udp_scan_resp.haslayer(UDP)):
return
"Open"
elif(udp_scan_resp.haslayer(ICMP)):
if(int(udp_scan_resp.getlayer(ICMP).type)==3
and int(udp_scan_resp.getlayer(ICMP).code)==3):
return
"Closed"
elif(int(udp_scan_resp.getlayer(ICMP).type)==3
and int(udp_scan_resp.getlayer(ICMP).code) in [1,2,9,10,13]):
return
"Filtered"
udp_scan(dst_ip,dst_port,dst_timeout)
Explanation
of some functions and variables used in the above codes:
|
Function/Variable |
Explanation |
|
RandShort() |
Generates
a random number |
|
type() |
Gets
the type of data in a particular variable; it is passed as an argument |
|
sport |
The
source port number |
|
dport |
The destination
port number |
|
timeout |
The
amount of time to wait for the response of a sent request packet |
|
haslayer() |
To
find a particular layer like TCP or UDP or ICMP is present of not inside a
packet |
|
getlayer() |
To
get the a particular value from a layer like TCP or UDP or ICMP present
inside a packet |
Scapy
is a very easy to use tool and makes it really simple to create your own
packets and understand what request packet is being sent and what response
packet is being received.
0 Comments
I'd love to hear your thoughts!