欢迎关注个人公众号:运维开发故事
SYN/ACK或RST响应表示机器已启动并正在运行。
>>> ans,unans=sr(IP(dst="60.205.177.0/28")/TCP(dport=80,flags="S"))
Begin emission:
Finished sending 16 packets.
.*********..................................................................................^C
Received 92 packets, got 9 answers, remaining 7 packets
>>> ans.summary(lambda s:s[1].sprintf("%IP.src% is alive"))
60.205.177.1 is alive
60.205.177.2 is alive
60.205.177.4 is alive
60.205.177.6 is alive
60.205.177.7 is alive
60.205.177.8 is alive
60.205.177.11 is alive
60.205.177.12 is alive
60.205.177.14 is alive
SYN-ping和ACK-ping看起来可能是多余的,但是大多数无状态防火墙不会过滤未经请求的ACK数据包,所以最好同时使用这两种ping技术。
>>> ans, unans = sr(IP(dst=‘60.205.177.90-105‘)/TCP(dport=80, flags=‘A‘))
Begin emission:
Finished sending 16 packets.
.*.******....................................................................................................................................................................^C
Received 173 packets, got 7 answers, remaining 9 packets
>>> ans.summary(lambda s:s[1].sprintf("{IP: %IP.src% is alive}"))
60.205.177.91 is alive
60.205.177.94 is alive
60.205.177.95 is alive
60.205.177.97 is alive
60.205.177.100 is alive
60.205.177.101 is alive
60.205.177.102 is alive
ICMP端口不可达表示机器是启动的。
>>> ans, unans = sr(IP(dst=‘60.205.177.100-254‘)/UDP(dport=90),timeout=0.1)
Begin emission:
Finished sending 155 packets.
..******..*****...
Received 18 packets, got 11 answers, remaining 144 packets
>>> ans.summary(lambda s:s[1].sprintf("%IP.src% is unreachable"))
60.205.177.106 is unreachable
60.205.177.108 is unreachable
60.205.177.107 is unreachable
60.205.177.111 is unreachable
60.205.177.125 is unreachable
60.205.177.172 is unreachable
60.205.177.191 is unreachable
60.205.177.203 is unreachable
60.205.177.224 is unreachable
60.205.177.242 is unreachable
60.205.177.244 is unreachable
- 由于在 IPv6 中没有 ARP协议,所以在 IPv6 上层定义了 NDP 协议实现 ARP 的地址解析,冲突地址检测等功能以及IPV6 的邻居发现功能。
>>> ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="172.17.51.0/24"),timeout=2)
Begin emission:
Finished sending 256 packets.
*******************************************************************************.***********************************************************************************...........................
Received 190 packets, got 162 answers, remaining 94 packets
>>> ans.summary(lambda r: r[0].sprintf("%Ether.src% %ARP.pdst%") )
00:16:3e:0c:d1:ad 172.17.51.0
00:16:3e:0c:d1:ad 172.17.51.1
00:16:3e:0c:d1:ad 172.17.51.2
00:16:3e:0c:d1:ad 172.17.51.3
00:16:3e:0c:d1:ad 172.17.51.4
00:16:3e:0c:d1:ad 172.17.51.5
00:16:3e:0c:d1:ad 172.17.51.6
00:16:3e:0c:d1:ad 172.17.51.7
>>> ans,unans=sr(IP(dst="60.205.177.168-180")/ICMP())
>>> ans.summary(lambda s:s[0].sprintf("{IP: %IP.dst% is alive}"))
60.205.177.168 is alive
60.205.177.169 is alive
60.205.177.171 is alive
60.205.177.172 is alive
60.205.177.175 is alive
60.205.177.174 is alive
60.205.177.176 is alive
60.205.177.179 is alive
60.205.177.178 is alive
60.205.177.180 is alive
找了个网图( 侵删)
这里展示一下tcpdump抓到的握手包
192.168.2.1.35555 > 192.168.2.12.4444: Flags [S] seq=12345
192.168.2.12.4444 > 192.168.2.1.35555: Flags [S.], seq=9998 ack=12346
192.168.2.1.35555 > 192.168.2.12.4444: Flags [.] seq=12346 ack=9999
IP与端口号之间以‘.‘分隔,ACK用‘.‘表示,SYN用‘S‘表示,而[S.]则表示SYN+ACK
第1步-将客户端的SYN发送到侦听服务器
制作一个TCP标头,在其中生成TCP源端口,设置服务器侦听的目标端口,设置TCP的flag SYN,并生成客户端的seq。
ip=IP(src="192.168.2.53", dst="60.205.177.168")
syn_packet = TCP(sport=1500, dport=80, flags="S", seq=100)
第2步-监听服务器的响应(SYN-ACK)
获取服务器的TCP序列号,并将该值加1。
synack_packet = sr1(ip/syn_packet)
my_ack = synack_packet.seq+1
第3步从客户端发送对服务器响应的确认(ACK)
ack_packet = TCP(sport=1500, dport=80, flags="A", seq=101, ack=my_ack)
send(ip/ack_packet)
完整代码如下
#!/usr/bin/python
from scapy.all import *
# 构建payload
get=‘GET / HTTP/1.0\n\n‘
#设置目的地址和源地址
ip=IP(src="192.168.2.53",dst="60.205.177.168")
# 定义一个随机源端口
port=RandNum(1024,65535)
# 构建SYN的包
SYN=ip/TCP(sport=port, dport=80, flags="S", seq=42)
# 发送SYN并接收服务器响应(SYN,ACK)
SYNACK=sr1(SYN)
#构建确认包
ACK=ip/TCP(sport=SYNACK.dport,dport=80,flags="A",seq=SYNACK.ack,ack=SYNACK.seq+1)/get
#发送ack确认包
reply,error=sr(ACK)
# 打印响应结果
print(reply.show())
SYN扫描也称为半开放扫描。可以使用这种策略来确定通信端口的状态而无需建立完整的连接。客户端首先向被测主机发送一个syn数据包,如果端口开放,那么服务端会响应一个syn+ack的数据包,之后客户端会发送rst数据包进行重置。否则服务端会直接响应一个rst包,表示端口没有开放。如果我们发了大量的syn包而不去确认,服务端会继续发送syn+ack的包,会不断的消耗服务器的CPU和内存,这也就是我们常说的syn泛洪***了。
接下来我们使用scapy来模拟syn扫描
sr1
功能发送并响应数据包使用sprintf
方法在响应中打印字段。(“ SA”标志表示开放的端口,“ RA”标志表示关闭的端口)
>>> syn_packet = IP(dst=‘60.205.177.168‘)/TCP(dport=22,flags=‘S‘)
>>> rsp=sr1(syn_packet)
Begin emission:
Finished sending 1 packets.
..*
Received 3 packets, got 1 answers, remaining 0 packets
>>> rsp.sprintf("%IP.src% %TCP.sport% %TCP.flags%")
‘60.205.177.168 ssh SA‘
>>> ans,unans=sr(IP(dst="60.205.177.168")/TCP(dport=(20,22),flags="S"))
Begin emission:
Finished sending 3 packets.
..*..**
Received 7 packets, got 3 answers, remaining 0 packets
>>> ans.summary(lambda s:s[1].sprintf("%TCP.sport% %TCP.flags%" ))
ftp_data RA
ftp RA
ssh SA
make_table
接受三个值,行,列和表数据。(在下面的示例中,目标IP位于x轴上,目标端口位于y轴上,响应中的TCP标志是表格数据)60.205.177.169的20和22端口没有响应数据包,猜测中间可能有设备(防火墙)给拦下了。
>>> ans,unans = sr(IP(dst=["60.205.177.168-170"])/TCP(dport=[20,22,80],flags="S"))
Begin emission:
Finished sending 9 packets.
..*..**..*.................................................................................................................................................................................................................................................^C
Received 251 packets, got 4 answers, remaining 5 packets
>>> ans.make_table(lambda s: (s[0].dst, s[0].dport,s[1].sprintf("%TCP.flags%")))
60.205.177.168 60.205.177.169
20 RA -
22 SA -
80 SA SA
客户端会发送带有fin标志(关闭连接)的数据包到服务端,当服务端没有响应时,表示端口是开放状态,否则会收到rst的包。
>>> fin_packet = IP(dst=‘60.205.177.168‘)/TCP(dport=4444,flags=‘F‘)
>>> resp = sr1(fin_packet)
Begin emission:
Finished to send 1 packets.
^C
Received 0 packets, got 0 answers, remaining 1 packets
>>> fin_packet = IP(dst=‘60.205.177.168‘)/TCP(dport=4399,flags=‘F‘)
>>> resp = sr1(fin_packet)
>>> resp.sprintf(‘%TCP.flags%‘)
‘RA‘
null扫描会发送一个没有设置任何flag的TCP数据包,当收到rst的响应包则表示端口关闭,否则表示端口开放,如果收到类型为3且代码为1、2、3、9、10或13的ICMP错误表示该端口已被过滤,获取不到端口状态。
>>> null_scan_resp = sr1(IP(dst="60.205.177.168")/TCP(dport=4399,flags=""),timeout=1)
>>> null_scan_resp.sprintf(‘%TCP.flags%‘)
‘RA‘
XMAS扫描会发送带有URG,PUSH,FIN标志的TCP数据包,如果未接收到任何数据包,则认为该端口处于打开状态;如果接收到RST数据包,则将该端口视为已关闭。如果收到类型为3且代码为1、2、3、9、10或13的ICMP错误表示该端口已被过滤,获取不到端口状态。
>>> xmas_scan_resp=sr1(IP(dst="60.205.177.168")/TCP(dport=4399,flags=”FPU”),timeout=1)
Begin emission:
.Finished sending 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
>>> xmas_scan_resp.sprintf(‘%TCP.flags%‘)
‘RA‘
UDP扫描最常见于检测DNS,SNMP和DHCP服务。客户端会发送带有要连接的端口号的UDP数据包。如果服务器使用UDP数据包响应客户端,那么该端口在服务器上是开放的。如果返回ICMP端口不可达的类型为3和code为3错误数据包,表示该端口在服务器是关闭状态。
>>> udp_scan=sr1(IP(dst="60.205.177.168")/UDP(dport=53),timeout=1))
>>> ans,unans=sr(IP(dst="49.232.152.189",ttl=(1,10))/ICMP())
Begin emission:
Finished sending 10 packets.
*****.**........................................................................................................^C
Received 112 packets, got 7 answers, remaining 3 packets
>>> ans.summary(lambda s:s[1].sprintf("%IP.src%"))
10.36.76.142
10.54.138.21
10.36.76.13
45.112.216.134
103.216.40.18
9.102.250.221
10.102.251.214
>>> ans,unans=sr(IP(dst="baidu.com",ttl=(1,10))/TCP(dport=53,flags="S"))
Begin emission:
Finished sending 10 packets.
*********......................^C
Received 31 packets, got 9 answers, remaining 1 packets
>>> ans.summary(lambda s:s[1].sprintf("%IP.src% {ICMP:%ICMP.type%}"))
10.36.76.142 time-exceeded
10.36.76.13 time-exceeded
10.102.252.130 time-exceeded
117.49.35.150 time-exceeded
10.102.34.237 time-exceeded
111.13.123.150 time-exceeded
218.206.88.22 time-exceeded
39.156.67.73 time-exceeded
39.156.27.1 time-exceeded
Scapy包含一个内置的traceroute()函数可以实现与上面相同的功能
>>> traceroute("baidu.com")
Begin emission:
Finished sending 30 packets.
************************
Received 24 packets, got 24 answers, remaining 6 packets
220.181.38.148:tcp80
2 10.36.76.13 11
3 10.102.252.34 11
4 117.49.35.138 11
5 116.251.112.185 11
6 36.110.217.9 11
7 36.110.246.201 11
8 220.181.17.150 11
14 220.181.38.148 SA
15 220.181.38.148 SA
16 220.181.38.148 SA
17 220.181.38.148 SA
18 220.181.38.148 SA
19 220.181.38.148 SA
20 220.181.38.148 SA
21 220.181.38.148 SA
22 220.181.38.148 SA
23 220.181.38.148 SA
24 220.181.38.148 SA
25 220.181.38.148 SA
26 220.181.38.148 SA
27 220.181.38.148 SA
28 220.181.38.148 SA
29 220.181.38.148 SA
30 220.181.38.148 SA
(<Traceroute: TCP:17 UDP:0 ICMP:7 Other:0>,
<Unanswered: TCP:6 UDP:0 ICMP:0 Other:0>
我们可以通过在traceroute()函数的l4参数中指定完整的数据包来执行DNS跟踪路由
>>> ans,unans=traceroute("60.205.177.168",l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="thesprawl.org")))
Begin emission:
****Finished sending 30 packets.
.................
Received 21 packets, got 4 answers, remaining 26 packets
60.205.177.168:udp53
1 10.2.0.1 11
2 114.242.29.1 11
4 125.33.185.114 11
5 61.49.143.2 11
原文:https://blog.51cto.com/u_12970189/2817565