端口扫描工具

端口扫描工具
Johnny端口扫描工具
使用ICMP协议探测主机是否开启
代码
1 | def ping(host): |
Ping请求数据包。它使用了Scapy库来构建网络数据包。
IP(dst=host)
: 这部分代码创建了一个IP数据包,其中dst
参数设置为传递给函数的主机地址。这是Ping请求的目标主机地址ICMP()
: 这部分代码创建了一个ICMP包,用于发送Ping请求b'I\'m a ping packet '
: payload包含文本消息的字节序列
结果
对于开启的主机来说当接收到ICMP之后会进行响应,但是对于关闭的主机则没有响应
半连接扫描
代码
1 | def scan_S(ip, port): |
p = IP(dst=ip) / TCP(dport=int(port), flags="S")
: 这一行代码创建了一个TCP SYN请求数据包。IP(dst=ip)
: 这部分代码创建了一个IP数据包,其中dst
参数设置为传递给函数的目标主机的IP地址。TCP(dport=int(port), flags="S")
: 这部分代码创建了一个TCP数据包,其中dport
参数设置为传递给函数的端口号,flags
参数设置为 “S”,表示发送一个TCP SYN请求。link = sr1(p, timeout=1, verbose=1)
: 这一行代码使用Scapy库发送TCP SYN请求数据包到目标主机的指定端口,并等待回复。具体解释如下:
verbose=1
: 这个参数设置为1,表示显示详细的Scapy输出信息,以便查看扫描进度。
if link.haslayer(TCP):
: 这是一个条件语句,用于检查接收到的数据包是否包含TCP层。if link.getlayer(TCP).flags == 'SA':
: 如果数据包包含TCP层,这一行代码用于检查TCP层中的标志是否为 ‘SA’,表示TCP连接建立成功,端口是开放的。print("[SYN]The PORT is open.")
: 如果端口是开放的,代码将打印出 “[SYN]The PORT is open.” 消息。else:
: 如果数据包不包含TCP层或标志不是 ‘SA’,则表示端口不是开放的。print("[SYN]The PORT is closed.")
: 在这种情况下,代码将打印出 “[SYN]The PORT is closed.” 消息。
结果
对于未开放的端口发送SYN时,包直接被丢弃
对于开放的端口,服务器将回复SYN ACK
FIN
代码
1 | def scan_F(ip, port): |
p = IP(dst=ip) / TCP(dport=int(port), flags="F")
: 这一行代码创建了一个TCP FIN请求数据包。具体解释如下:IP(dst=ip)
: 这部分代码创建了一个IP数据包,其中dst
参数设置为传递给函数的目标主机的IP地址。TCP(dport=int(port), flags="F")
: 这部分代码创建了一个TCP数据包,其中dport
参数设置为传递给函数的端口号,flags
参数设置为 “F”,表示发送一个TCP FIN请求。
link = sr1(p, timeout=1, verbose=1)
: 这一行代码使用Scapy库发送TCP FIN请求数据包到目标主机的指定端口,并等待回复。if link == None:
: 这是一个条件语句,用于检查是否接收到了回复数据包。print("[FIN]The PORT is open.")
: 如果没有接收到回复数据包,说明端口是开放的,因为没有收到TCP FIN-ACK响应。elif link != None and link.getlayer(TCP).flags == 'RA':
: 如果接收到了回复数据包,并且该数据包的TCP标志为 ‘RA’(RST-ACK),则表示端口是关闭的。link.display()
: 这一行代码用于显示接收到的回复数据包的详细信息,包括IP和TCP头部的信息。print("[FIN]The PORT is closed.")
: 最后,代码打印出 “[FIN]The PORT is closed.” 消息,表示端口是关闭的。
结果
NULL
代码
1 | p = IP(dst=ip) / TCP(dport=int(port), flags="") |
检测指定主机的指定端口是否处于开放状态。与之前的FIN扫描和SYN扫描不同,NULL扫描发送一个没有标志位(flags)的TCP数据包,因此不应该触发目标主机的任何特定响应。
p = IP(dst=ip) / TCP(dport=int(port), flags="")
: 这一行代码创建了一个TCP NULL请求数据包。IP(dst=ip)
: 这部分代码创建了一个IP数据包,其中dst
参数设置为传递给函数的目标主机的IP地址。TCP(dport=int(port), flags="")
: 这部分代码创建了一个TCP数据包,其中dport
参数设置为传递给函数的端口号,但flags
参数设置为空字符串,表示发送一个TCP NULL请求,即没有设置任何标志位。
link = sr1(p, timeout=1, verbose=1)
: 这一行代码使用Scapy库发送TCP NULL请求数据包到目标主机的指定端口,并等待回复。print("[NULL]The PORT is open.")
: 如果没有接收到回复数据包,说明端口是开放的,因为没有收到TCP响应(因为发送的是一个空的TCP数据包)。elif link != None and link.getlayer(TCP).flags == 'RA':
: 如果接收到了回复数据包,并且该数据包的TCP标志为 ‘RA’(RST-ACK),则表示端口是关闭的。link.display()
: 这一行代码用于显示接收到的回复数据包的详细信息,包括IP和TCP头部的信息。print("[NULL]The PORT is closed.")
: 最后,代码打印出 “[NULL]The PORT is closed.” 消息,表示端口是关闭的。
结果
Xmas
代码
1 | p = IP(dst=ip) / TCP(dport=int(port), flags="FPU") |
p = IP(dst=ip) / TCP(dport=int(port), flags="FPU")
: 这一行代码创建了一个TCP Xmas请求数据包。TCP(dport=int(port), flags="FPU")
: 这部分代码创建了一个TCP数据包,其中dport
参数设置为传递给函数的端口号,而flags
参数设置为 “FPU”,表示发送一个TCP Xmas请求,即将FIN、PSH和URG标志位都设置为1。
link = sr1(p, timeout=1, verbose=1)
: 这一行代码使用Scapy库发送TCP Xmas请求数据包到目标主机的指定端口,并等待回复。if link == None:
: 这是一个条件语句,用于检查是否接收到了回复数据包。print("[Xmas]The PORT is open.")
: 如果没有接收到回复数据包,说明端口是开放的,因为没有收到TCP响应(因为发送的是一个Xmas请求,不符合正常的TCP握手)。elif link != None and link.getlayer(TCP).flags == 'RA':
: 如果接收到了回复数据包,并且该数据包的TCP标志为 ‘RA’(RST-ACK),则表示端口是关闭的。print("[Xmas]The PORT is closed.")
: 最后,代码打印出 “[Xmas]The PORT is closed.” 消息,表示端口是关闭的。
结果
FIN NULL Xmas存在的问题
首先我使用wireshark对虚拟机的端口进行抓包,以FIN为例,使用nmap进行FIN扫描,命令为:
1 | nmap 192.168.xx.xx -p xx -sF |
分别对开放端口22 和关闭的端口8888进行扫描,发现nmap确实发了一个只有FIN置位的TCP包,但是服务器都没有响应
之后我查看了LINUX的源码(内核版本5.4.0)
在进行实验的过程中,使用Scapy直接对服务器进行连接,初始状态为TCP_LISTEN, 同时进行三个判断,分别为ack rst syn(再进行fin),其他情况全部丢弃。 所以我认为是linux系统自动把非法的包给丢弃了。