端口扫描代码_Tcp端口扫描源码

hacker|
278

如何用Scapy写一个端口扫描器

常见的端口扫描类型有:

1. TCP 连接扫描

2. TCP SYN 扫描(也称为半开放扫描或stealth扫描)

3. TCP 圣诞树(Xmas Tree)扫描

4. TCP FIN 扫描

5. TCP 空扫描(Null)

6. TCP ACK 扫描

7. TCP 窗口扫描

8. UDP 扫描

下面先讲解每种扫描的原理,随后提供具体实现代码。

TCP 连接扫描

客户端与服务器建立 TCP 连接要进行一次三次握手,如果进行了一次成功的三次握手,则说明端口开放。

客户端想要连接服务器80端口时,会先发送一个带有 SYN 标识和端口号的 TCP 数据包给服务器(本例中为80端口)。如果端口是开放的,则服务器会接受这个连接并返回一个带有 SYN 和 ACK 标识的数据包给客户端。随后客户端会返回带有 ACK 和 RST 标识的数据包,此时客户端与服务器建立了连接。如果完成一次三次握手,那么服务器上对应的端口肯定就是开放的。

当客户端发送一个带有 SYN 标识和端口号的 TCP 数据包给服务器后,如果服务器端返回一个带 RST 标识的数据包,则说明端口处于关闭状态。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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 SYN 扫描

这个技术同 TCP 连接扫描非常相似。同样是客户端向服务器发送一个带有 SYN 标识和端口号的数据包,如果目标端口开发,则会返回带有 SYN 和 ACK 标识的 TCP 数据包。但是,这时客户端不会返回 RST+ACK 而是返回一个只带有 RST 标识的数据包。这种技术主要用于躲避防火墙的检测。

如果目标端口处于关闭状态,那么同之前一样,服务器会返回一个 RST 数据包。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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"

TCP 圣诞树(Xmas Tree)扫描

在圣诞树扫描中,客户端会向服务器发送带有 PSH,FIN,URG 标识和端口号的数据包给服务器。如果目标端口是开放的,那么不会有任何来自服务器的回应。

如果服务器返回了一个带有 RST 标识的 TCP 数据包,那么说明端口处于关闭状态。

但如果服务器返回了一个 ICMP 数据包,其中包含 ICMP 目标不可达错误类型3以及 ICMP 状态码为1,2,3,9,10或13,则说明目标端口被过滤了无法确定是否处于开放状态。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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"

TCP FIN扫描

FIN 扫描会向服务器发送带有 FIN 标识和端口号的 TCP 数据包。如果没有服务器端回应则说明端口开放。

如果服务器返回一个 RST 数据包,则说明目标端口是关闭的。

如果服务器返回了一个 ICMP 数据包,其中包含 ICMP 目标不可达错误类型3以及 ICMP 代码为1,2,3,9,10或13,则说明目标端口被过滤了无法确定端口状态。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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"

TCP 空扫描(Null)

在空扫描中,客户端发出的 TCP 数据包仅仅只会包含端口号而不会有其他任何的标识信息。如果目标端口是开放的则不会回复任何信息。

如果服务器返回了一个 RST 数据包,则说明目标端口是关闭的。

如果返回 ICMP 错误类型3且代码为1,2,3,9,10或13的数据包,则说明端口被服务器过滤了。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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扫描

ACK 扫描不是用于发现端口开启或关闭状态的,而是用于发现服务器上是否存在有状态防火墙的。它的结果只能说明端口是否被过滤。再次强调,ACK 扫描不能发现端口是否处于开启或关闭状态。

客户端会发送一个带有 ACK 标识和端口号的数据包给服务器。如果服务器返回一个带有 RST 标识的 TCP 数据包,则说明端口没有被过滤,不存在状态防火墙。

如果目标服务器没有任何回应或者返回ICMP 错误类型3且代码为1,2,3,9,10或13的数据包,则说明端口被过滤且存在状态防火墙。

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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窗口扫描

TCP 窗口扫描的流程同 ACK 扫描类似,同样是客户端向服务器发送一个带有 ACK 标识和端口号的 TCP 数据包,但是这种扫描能够用于发现目标服务器端口的状态。在 ACK 扫描中返回 RST 表明没有被过滤,但在窗口扫描中,当收到返回的 RST 数据包后,它会检查窗口大小的值。如果窗口大小的值是个非零值,则说明目标端口是开放的。

如果返回的 RST 数据包中的窗口大小为0,则说明目标端口是关闭的。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.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扫描

TCP 是面向连接的协议,而UDP则是无连接的协议。

面向连接的协议会先在客户端和服务器之间建立通信信道,然后才会开始传输数据。如果客户端和服务器之间没有建立通信信道,则不会有任何产生任何通信数据。

无连接的协议则不会事先建立客户端和服务器之间的通信信道,只要客户端到服务器存在可用信道,就会假设目标是可达的然后向对方发送数据。

客户端会向服务器发送一个带有端口号的 UDP 数据包。如果服务器回复了 UDP 数据包,则目标端口是开放的。

如果服务器返回了一个 ICMP 目标不可达的错误和代码3,则意味着目标端口处于关闭状态。

如果服务器返回一个 ICMP 错误类型3且代码为1,2,3,9,10或13的数据包,则说明目标端口被服务器过滤了。

但如果服务器没有任何相应客户端的 UDP 请求,则可以断定目标端口可能是开放或被过滤的,无法判断端口的最终状态。

代码:

#! /usr/bin/python

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *

dst_ip = "10.0.0.1"

src_port = RandShort()

dst_port=53

dst_timeout=10

def udp_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"

print udp_scan(dst_ip,dst_port,dst_timeout)

下面解释下上述代码中的一些函数和变量:

RandShort():产生随机数

type():获取数据类型

sport:源端口号

dport:目标端口号

timeout:等待相应的时间

haslayer():查找指定层:TCP或UDP或ICMP

getlayer():获取指定层:TCP或UDP或ICMP

以上扫描的概念可以被用于“多端口扫描”,源码可以参考这里:

Scapy 是一个非常好用的工具,使用它可以非常简单的构建自己的数据包,还可以很轻易的处理数据包的发送和相应。

(译者注:上述所有代码均在Kali 2.0下测试通过,建议读者在Linux环境下测试代码,如想在Windows上测试,请参见 Scapy官方文档 配置好scapy环境)

在网上摘抄了一个python编写的TCP端口扫描程序,求解释。

你那个写死的ip是本机ip吗

相当于判断当前脚本是否是被直接执行还是被当作模块调用(同一个文件可以有多种作用,如果直接执行可能输出测试日志,但作为模块一般不输出,所以要判断)

渗透测试之端口扫描

端口扫描:端口对应 *** 服务及应用端程序

服务端程序的漏洞通过端口攻入

发现开放的端口

更具体的攻击面

UDP端口扫描:

如果收到ICMP端口不可达,表示端口关闭

如果没有收到回包,则证明端口是开放的

和三层扫描IP刚好相反

Scapy端口开发扫描

命令:sr1(IP(dst="192.168.45.129")/UDP(dport=53),timeout=1,verbose=1)

nmap -sU 192.168.45.129

TCP扫描:基于连接的协议

三次握手:基于正常的三次握手发现目标是否在线

隐蔽扫描:发送不完整的数据包,不建立完整的连接,如ACK包,SYN包,不会在应用层访问,

僵尸扫描:不和目标系统产生交互,极为隐蔽

全连接扫描:建立完整的三次握手

所有的TCP扫描方式都是基于三次握手的变化来判断目标系统端口状态

隐蔽扫描:发送SYN数据包,如果收到对方发来的ACK数据包,证明其在线,不与其建立完整的三次握手连接,在应用层日志内不记录扫描行为,十分隐蔽, *** 层审计会被发现迹象

僵尸扫描:是一种极其隐蔽的扫描方式,实施条件苛刻,对于扫描发起方和被扫描方之间,必须是需要实现地址伪造,必须是僵尸机(指的是闲置系统,并且系统使用递增的IPID)早期的win xp,win 2000都是递增的IPID,如今的LINUX,WINDOWS都是随机产生的IPID

1,扫描者向僵尸机发送SYN+ACY,僵尸机判断未进行三次握手,所以返回RST包,在RST数据包内有一个IPID,值记为X,那么扫描者就会知道被扫描者的IPID

2,扫描者向目标服务器发送SYN数据包,并且伪装源地址为僵尸机,如果目标服务器端口开放,那么就会向僵尸机发送SYN+ACK数据包,那么僵尸机也会发送RST数据包,那么其IPID就是X+1(因为僵尸机足够空闲,这个就为其收到的第二个数据包)

3,扫描者再向僵尸机发送SYN+ACK,那么僵尸机再次发送RST数据包,IPID为X+2,如果扫描者收到僵尸机的IPID为X+2,那么就可以判断目标服务器端口开放

使用scapy发送数据包:首先开启三台虚拟机,

kali虚拟机:192.168.45.128

Linux虚拟机:192.168.45.129

windows虚拟机:192.168.45.132

发送SYN数据包:

通过抓包可以查看kali给linux发送syn数据包

linux虚拟机返回Kali虚拟机SYN+ACK数据包

kali系统并不知道使用者发送了SYN包,而其莫名其妙收到了SYN+ACK数据包,便会发RST包断开连接

也可以使用下列该命令查看收到的数据包的信息,收到对方相应的SYN+ACK数据包,scapy默认从本机的80端口往目标系统的20号端口发送,当然也可以修改

如果向目标系统发送一个 随机端口:

通过抓包的获得:1,kali向linux发送SYN数据包,目标端口23456,

2,Linux系统由自己的23456端口向kali系统的20号端口返回RST+ACK数据包,表示系统端口未开放会话结束

使用python脚本去进行scapy扫描

nmap做隐蔽端口扫描:

nmap -sS  192.168.45.129 -p 80,21,110,443 #扫描固定的端口

nmap -sS 192.168.45.129 -p 1-65535 --open  #扫描该IP地址下1-65535端口扫描,并只显示开放的端口

nmap -sS 192.168.45.129 -p --open  #参数--open表示只显示开放的端口

nmap -sS -iL iplist.txt -p 80

由抓包可知,nmap默认使用-sS扫描,发送SYN数据包,即nmap=nmap  -sS

hping3做隐蔽端口扫描:

hping3 192.168.45.129 --scan 80 -S  #参数--scan后面接单个端口或者多个端口.-S表示进行SYN扫描

hping3 192.168.45.129 --scan 80,21,25,443 -S

hping3 192.168.45.129 --scan 1-65535 -S

由抓包可得:

hping3 -c 100  -S  --spoof 192.168.45.200 -p ++1 192.168.45.129

参数-c表示发送数据包的数量

参数-S表示发送SYN数据包

--spoof:伪造源地址,后面接伪造的地址,

参数-p表示扫描的端口,++1表示每次端口号加1,那么就是发送SYN从端口1到端口100

最后面跟的是目标IP

通过抓包可以得知地址已伪造,但对于linux系统(192.168.45.129)来说,它收到了192.168.45.200的SYN数据包,那么就会给192.168.45.200回复SYN+ACK数据包,但该地址却是kali伪造的地址,那么要查看目标系统哪些端口开放,必须登陆地址为kali伪造的地址即(192.168.45.200)进行抓包

hping3和nmap扫描端口的区别:1,hping3结果清晰明了

  2,nmap首先对IP进行DNS反向解析,如果没成功,那么便会对其端口发送数据包,默认发送SYN数据包

hping3直接向目标系统的端口发送SYN数据包,并不进行DNS反向解析

全连接端口扫描:如果单独发送SYN数据包被被过滤,那么就使用全连接端口扫描,与目标建立三次握手连接,结果是最准确的,但容易被入侵检测系统发现

response=sr1(IP(dst="192.168.45.129")/TCP(dport=80,flags="S"))

reply=sr1(IP(dst="192.168.45.129")/TCP(dport=80,flags="A",ack=(response[TCP].seq+1)))

抓包情况:首先kali向Linux发送SYN,Linux回复SYN+ACK给kali,但kali的系统内核不清楚kali曾给linux发送给SYN数据包,那么kali内核莫名其妙收到SYN+ACK包,那么便会返回RST请求断开数据包给Linux,三次握手中断,如今kali再给Linux发ACK确认数据包,Linux莫名其妙收到了ACK数据包,当然也会返回RST请求断开数据包,具体抓包如下:

那么只要kali内核在收到SYN+ACK数据包之后,不发RST数据包,那么就可以建立完整的TCP三次握手,判断目标主机端口是否开放

因为iptables存在于Linux内核中,通过iptables禁用内核发送RST数据包,那么就可以实现

使用nmap进行全连接端口扫描:(如果不指定端口,那么nmap默认会扫描1000个常用的端口,并不是1-1000号端口)

使用dmitry进行全连接端口扫描:

dmitry:功能简单,但功能简便

默认扫描150个最常用的端口

dmitry -p 192.168.45.129  #参数-p表示执行TCP端口扫描

dmitry -p 192.168.45.129 -o output  #参数-o表示把结果保存到一个文本文档中去

使用nc进行全连接端口扫描:

nc -nv -w 1 -z 192.168.45.129 1-100:      1-100表示扫描1-100号端口

参数-n表示不对Ip地址进行域名解析,只把其当IP来处理

参数-v表示显示详细信息

参数-w表示超时时间

-z表示打开用于扫描的模式

如何用java实现tcp connect,tcp syn端口扫描

connect比较简单,就是用Socket+多线程,每个端口创建一次连接,没连上是不会往下执行的,会抛出异常,网上有源码,都是这个 *** 。

syn和FIN还不知道咋实现,可以考虑用本地 *** 。

端口扫描原理及工具 - 安全工具篇

"端口"是英文port的意译,可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算机内部端口,不可见。例如计算机中的80端口、21端口、23端口等。

一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、 *** TP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的 *** 服务呢?显然不能只靠IP地址,因为IP 地址与 *** 服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。

因此,一个开放的端口代表一个提供的服务,不同的服务具有不同的端口号, 因此要对服务进行测试,首先要确定是否开放对应端口号 。

TCP端口和UDP端口。由于TCP和UDP 两个协议是独立的,因此各自的端口号也相互独立,比如TCP有235端口,UDP也 可以有235端口,两者并不冲突。

1、周知端口

周知端口是众所周知的端口号,范围从0到1023,其中80端口分配给WWW服务,21端口分配给FTP服务等。我们在IE的地址栏里输入一个网址的时候是不必指定端口号的,因为在默认情况下WWW服务的端口是“80”。

2、动态端口

动态端口的范围是从49152到65535。之所以称为动态端口,是因为它 一般不固定分配某种服务,而是动态分配。

3、注册端口

端口1024到49151,分配给用户进程或应用程序。这些进程主要是用户安装的程序。

1、使用Nmap工具查找ip的tcp端口

-O :获取操作系统版本信息

2、使用Nmap工具查找udp端口

-sU :表示udp scan , udp端口扫描

-Pn :不对目标进行ping探测(不判断主机是否在线)(直接扫描端口)

对于udp端口扫描比较慢,扫描完6万多个端口需要20分钟左右

3、使用Nmap工具获取端口Banner

只会返回有Banner信息的,没有则不会返回。

4、使用Nmap嗅探服务版本信息

如果没有返回banner信息的,也可以使用该 *** 尝试嗅探服务版本信息。

5、利用nmap对目标进行完整测试

在针对内容测试时,有授权的情况下,可以利用nmap对目标进行完整测试

0条大神的评论

发表评论