最新公告
  • 欢迎您光临悠哉网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 数据包处理利器—Scapy高级使用(一)

    主机探测

    TCP SYN Ping

    • 发送仅设置了SYN的空TCP数据包
    • SYN/ACK或RST响应表示机器已启动并正在运行。
    1. >>> ans,unans=sr(IP(dst="60.205.177.0/28")/TCP(dport=80,flags="S")) 
    2. Begin emission: 
    3. Finished sending 16 packets. 
    4. .*********..................................................................................^C 
    5. Received 92 packets, got 9 answers, remaining 7 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("%IP.src% is alive")) 
    7. 60.205.177.1 is alive 
    8. 60.205.177.2 is alive 
    9. 60.205.177.4 is alive 
    10. 60.205.177.6 is alive 
    11. 60.205.177.7 is alive 
    12. 60.205.177.8 is alive 
    13. 60.205.177.11 is alive 
    14. 60.205.177.12 is alive 
    15. 60.205.177.14 is alive 

    TCP ACK Ping

    • 发送仅设置了ACK位的空TCP数据包。
    • 未经请求的ACK数据包应通过RST进行响应,RST显示一台机器。
    • SYN-ping和ACK-ping看起来可能是多余的,但是大多数无状态防火墙不会过滤未经请求的ACK数据包,所以最好同时使用这两种ping技术。
    1. >>> ans, unans = sr(IP(dst=\'60.205.177.90-105\')/TCP(dport=80, flags=\'A\')) 
    2. Begin emission: 
    3. Finished sending 16 packets. 
    4. .*.******....................................................................................................................................................................^C 
    5. Received 173 packets, got 7 answers, remaining 9 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("{IP: %IP.src% is alive}")) 
    7.  60.205.177.91 is alive 
    8.  60.205.177.94 is alive 
    9.  60.205.177.95 is alive 
    10.  60.205.177.97 is alive 
    11.  60.205.177.100 is alive 
    12.  60.205.177.101 is alive 
    13.  60.205.177.102 is alive 

    UDP Ping

    • 将UDP数据包发送给给定的端口(无论是否带有有效载荷),协议特定的有效载荷会使扫描更加有效。
    • 选择最有可能关闭的端口(开放的UDP端口可能会收到空数据包,但会忽略它们)。
    • ICMP端口不可达表示机器是启动的。
    1. >>> ans, unans = sr(IP(dst=\'60.205.177.100-254\')/UDP(dport=90),timeout=0.1) 
    2. Begin emission: 
    3. Finished sending 155 packets. 
    4. ..******..*****... 
    5. Received 18 packets, got 11 answers, remaining 144 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("%IP.src% is unreachable")) 
    7. 60.205.177.106 is unreachable 
    8. 60.205.177.108 is unreachable 
    9. 60.205.177.107 is unreachable 
    10. 60.205.177.111 is unreachable 
    11. 60.205.177.125 is unreachable 
    12. 60.205.177.172 is unreachable 
    13. 60.205.177.191 is unreachable 
    14. 60.205.177.203 is unreachable 
    15. 60.205.177.224 is unreachable 
    16. 60.205.177.242 is unreachable 
    17. 60.205.177.244 is unreachable 

    ARP Ping

    • 在同一网络/ LAN上探测存活主机时,可以使用ARP Ping。
    • 更快,更可靠,因为它仅通过ARP在第2层上运行。
    • ARP是任何第2层通信的骨干协议

    由于在 IPv6 中没有 ARP协议,所以在 IPv6 上层定义了 NDP 协议实现 ARP 的地址解析,冲突地址检测等功能以及IPV6 的邻居发现功能。

    1. >>>  ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="172.17.51.0/24"),timeout=2) 
    2. Begin emission: 
    3. Finished sending 256 packets. 
    4. *******************************************************************************.***********************************************************************************........................... 
    5. Received 190 packets, got 162 answers, remaining 94 packets 
    6. >>> ans.summary(lambda r: r[0].sprintf("%Ether.src% %ARP.pdst%") ) 
    7. 00:16:3e:0c:d1:ad 172.17.51.0 
    8. 00:16:3e:0c:d1:ad 172.17.51.1 
    9. 00:16:3e:0c:d1:ad 172.17.51.2 
    10. 00:16:3e:0c:d1:ad 172.17.51.3 
    11. 00:16:3e:0c:d1:ad 172.17.51.4 
    12. 00:16:3e:0c:d1:ad 172.17.51.5 
    13. 00:16:3e:0c:d1:ad 172.17.51.6 
    14. 00:16:3e:0c:d1:ad 172.17.51.7 

    ICMP Ping

    • ICMP扫描涉及无处不在的_ping程序_发送的标准数据包。
    • 向目标IP发送一个ICMP类型8(回显请求)数据包,收到一个ICMP类型0(回显应答)的包表示机器存活。
    • 现在许多主机和防火墙阻止这些数据包,因此基本的ICMP扫描是不可靠的。
    • ICMP还支持时间戳请求和地址掩码请求,可以显示计算机的可用性。
    1. >>>  ans,unans=sr(IP(dst="60.205.177.168-180")/ICMP()) 
    2. >>> ans.summary(lambda s:s[0].sprintf("{IP: %IP.dst% is alive}")) 
    3.  60.205.177.168 is alive 
    4.  60.205.177.169 is alive 
    5.  60.205.177.171 is alive 
    6.  60.205.177.172 is alive 
    7.  60.205.177.175 is alive 
    8.  60.205.177.174 is alive 
    9.  60.205.177.176 is alive 
    10.  60.205.177.179 is alive 
    11.  60.205.177.178 is alive 
    12.  60.205.177.180 is alive 

    服务发现(端口扫描)

    TCP连接扫描

    找了个网图( 侵删)

    这里展示一下tcpdump抓到的握手包

    1. 192.168.2.1.35555 > 192.168.2.12.4444: Flags [S] seq=12345    
    2. 192.168.2.12.4444 > 192.168.2.1.35555: Flags [S.],  seq=9998 ack=12346 
    3. 192.168.2.1.35555 > 192.168.2.12.4444: Flags [.] seq=12346 ack=9999   

    IP与端口号之间以\'.\'分隔,ACK用\'.\'表示,SYN用\'S\'表示,而[S.]则表示SYN+ACK

    Scapy中制作三次握手包

    第1步-将客户端的SYN发送到侦听服务器

    • 使用源IP地址和目标IP地址制作一个IP头。
    • 制作一个TCP标头,在其中生成TCP源端口,设置服务器侦听的目标端口,设置TCP的flag SYN,并生成客户端的seq。
    1. ip=IP(src="192.168.2.53", dst="60.205.177.168"
    2. syn_packet = TCP(sport=1500, dport=80, flags="S", seq=100) 

    第2步-监听服务器的响应(SYN-ACK)

    • 保存服务器的响应。
    • 获取服务器的TCP序列号,并将该值加1。
    1. synack_packet = sr1(ip/syn_packet) 
    2. my_ack = synack_packet.seq+1 

    第3步从客户端发送对服务器响应的确认(ACK)

    • IP标头与初始SYN数据包具有相同的源和目标。
    • TCP报头具有与syn数据包相同的TCP源端口和目标端口,仅设置ACK位,由于SYN数据包消耗一个序列号,因此将客户端的ISN递增1,将确认值设置为递增的服务器的序列号值。
    1. ack_packet = TCP(sport=1500, dport=80, flags="A", seq=101, ack=my_ack) 
    2. send(ip/ack_packet) 

    完整代码如下

    1. #!/usr/bin/python 
    2.  
    3. from scapy.all import * 
    4. # 构建payload 
    5. get=\'GET / HTTP/1.0\\n\\n\' 
    6. #设置目的地址和源地址 
    7. ip=IP(src="192.168.2.53",dst="60.205.177.168"
    8. # 定义一个随机源端口 
    9. port=RandNum(1024,65535) 
    10. # 构建SYN的包 
    11. SYN=ip/TCP(sport=port, dport=80, flags="S", seq=42) 
    12. # 发送SYN并接收服务器响应(SYN,ACK) 
    13. SYNACK=sr1(SYN) 
    14. #构建确认包 
    15. ACK=ip/TCP(sport=SYNACK.dport,dport=80,flags="A",seq=SYNACK.ack,ack=SYNACK.seq+1)/get 
    16. #发送ack确认包 
    17. reply,error=sr(ACK) 
    18. # 打印响应结果 
    19. print(reply.show()) 

    SYN扫描

    SYN扫描也称为半开放扫描。可以使用这种策略来确定通信端口的状态而无需建立完整的连接。客户端首先向被测主机发送一个syn数据包,如果端口开放,那么服务端会响应一个syn+ack的数据包,之后客户端会发送rst数据包进行重置。否则服务端会直接响应一个rst包,表示端口没有开放。如果我们发了大量的syn包而不去确认,服务端会继续发送syn+ack的包,会不断的消耗服务器的CPU和内存,这也就是我们常说的syn泛洪攻击了。

    接下来我们使用scapy来模拟syn扫描

    在单个主机,单个端口上进行SYN扫描

    • 使用sr1功能发送并响应数据包
    • 使用sprintf方法在响应中打印字段。(“ SA”标志表示开放的端口,“ RA”标志表示关闭的端口)
    1. >>> syn_packet = IP(dst=\'60.205.177.168\')/TCP(dport=22,flags=\'S\'
    2. >>> rsp=sr1(syn_packet) 
    3. Begin emission: 
    4. Finished sending 1 packets. 
    5. ..* 
    6. Received 3 packets, got 1 answers, remaining 0 packets 
    7. >>> rsp.sprintf("%IP.src%  %TCP.sport%  %TCP.flags%"
    8. \'60.205.177.168  ssh  SA\' 

    在单个主机,多个端口上进行SYN扫描

    1. >>> ans,unans=sr(IP(dst="60.205.177.168")/TCP(dport=(20,22),flags="S")) 
    2. Begin emission: 
    3. Finished sending 3 packets. 
    4. ..*..** 
    5. Received 7 packets, got 3 answers, remaining 0 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("%TCP.sport%  %TCP.flags%" )) 
    7. ftp_data  RA 
    8. ftp  RA 
    9. ssh  SA 

    对多个主机,多个端口进行SYN扫描

    • make_table接受三个值,行,列和表数据。(在下面的示例中,目标IP位于x轴上,目标端口位于y轴上,响应中的TCP标志是表格数据)

    60.205.177.169的20和22端口没有响应数据包,猜测中间可能有设备(防火墙)给拦下了。

    1. >>> ans,unans = sr(IP(dst=["60.205.177.168-170"])/TCP(dport=[20,22,80],flags="S")) 
    2. Begin emission: 
    3. Finished sending 9 packets. 
    4. ..*..**..*.................................................................................................................................................................................................................................................^C 
    5. Received 251 packets, got 4 answers, remaining 5 packets 
    6. >>> ans.make_table(lambda s: (s[0].dst, s[0].dport,s[1].sprintf("%TCP.flags%"))) 
    7.    60.205.177.168 60.205.177.169  
    8. 20 RA             -               
    9. 22 SA             -               
    10. 80 SA             SA  

    Fin 扫描

    客户端会发送带有fin标志(关闭连接)的数据包到服务端,当服务端没有响应时,表示端口是开放状态,否则会收到rst的包。

    端口开放

    1. >>> fin_packet = IP(dst=\'60.205.177.168\')/TCP(dport=4444,flags=\'F\'
    2. >>> resp = sr1(fin_packet) 
    3. Begin emission: 
    4. Finished to send 1 packets. 
    5. ^C 
    6. Received 0 packets, got 0 answers, remaining 1 packets 

    端口关闭

    1. >>> fin_packet = IP(dst=\'60.205.177.168\')/TCP(dport=4399,flags=\'F\'
    2. >>> resp = sr1(fin_packet) 
    3. >>> resp.sprintf(\'%TCP.flags%\'
    4. \'RA\' 

    NULL 扫描

    null扫描会发送一个没有设置任何flag的TCP数据包,当收到rst的响应包则表示端口关闭,否则表示端口开放,如果收到类型为3且代码为1、2、3、9、10或13的ICMP错误表示该端口已被过滤,获取不到端口状态。

    端口关闭

    1. >>> null_scan_resp = sr1(IP(dst="60.205.177.168")/TCP(dport=4399,flags=""),timeout=1) 
    2. >>> null_scan_resp.sprintf(\'%TCP.flags%\'
    3. \'RA\' 

    Xmas 扫描

    XMAS扫描会发送带有URG,PUSH,FIN标志的TCP数据包,如果未接收到任何数据包,则认为该端口处于打开状态;如果接收到RST数据包,则将该端口视为已关闭。如果收到类型为3且代码为1、2、3、9、10或13的ICMP错误表示该端口已被过滤,获取不到端口状态。

    端口关闭

    1. >>> xmas_scan_resp=sr1(IP(dst="60.205.177.168")/TCP(dport=4399,flags=”FPU”),timeout=1) 
    2. Begin emission: 
    3. .Finished sending 1 packets. 
    4. Received 2 packets, got 1 answers, remaining 0 packets 
    5. >>> xmas_scan_resp.sprintf(\'%TCP.flags%\'
    6. \'RA\' 

    UDP扫描

    UDP扫描最常见于检测DNS,SNMP和DHCP服务。客户端会发送带有要连接的端口号的UDP数据包。如果服务器使用UDP数据包响应客户端,那么该端口在服务器上是开放的。如果返回ICMP端口不可达的类型为3和code为3错误数据包,表示该端口在服务器是关闭状态。

    1. >>> udp_scan=sr1(IP(dst="60.205.177.168")/UDP(dport=53),timeout=1)) 

    跟踪路由

    跟踪路由技术基于IP协议的设计方式。IP标头中的TTL值被视为跳数限制。每当路由器收到要转发的数据包时,它将TTL减1并转发数据包。当TTL达到0时,路由器将向源计算机发送答复,表示数据包已被丢弃。

    各种工具背后的技术是相同的,但是实现它们的方式略有不同。Unix系统使用UDP数据报文,而Windows tracert则发送ICMP请求,Linux的tcptraceroute使用TCP协议。

    使用ICMP进行路由跟踪

    1. >>> ans,unans=sr(IP(dst="49.232.152.189",ttl=(1,10))/ICMP()) 
    2. Begin emission: 
    3. Finished sending 10 packets. 
    4. *****.**........................................................................................................^C 
    5. Received 112 packets, got 7 answers, remaining 3 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("%IP.src%")) 
    7. 10.36.76.142 
    8. 10.54.138.21 
    9. 10.36.76.13 
    10. 45.112.216.134 
    11. 103.216.40.18 
    12. 9.102.250.221 
    13. 10.102.251.214 

    使用tcp进行路由跟踪

    1. >>> ans,unans=sr(IP(dst="baidu.com",ttl=(1,10))/TCP(dport=53,flags="S")) 
    2. Begin emission: 
    3. Finished sending 10 packets. 
    4. *********......................^C 
    5. Received 31 packets, got 9 answers, remaining 1 packets 
    6. >>> ans.summary(lambda s:s[1].sprintf("%IP.src% {ICMP:%ICMP.type%}")) 
    7. 10.36.76.142 time-exceeded 
    8. 10.36.76.13 time-exceeded 
    9. 10.102.252.130 time-exceeded 
    10. 117.49.35.150 time-exceeded 
    11. 10.102.34.237 time-exceeded 
    12. 111.13.123.150 time-exceeded 
    13. 218.206.88.22 time-exceeded 
    14. 39.156.67.73 time-exceeded 
    15. 39.156.27.1 time-exceeded 

    Scapy包含一个内置的traceroute()函数可以实现与上面相同的功能

    1. >>> traceroute("baidu.com"
    2. Begin emission: 
    3. Finished sending 30 packets. 
    4. ************************ 
    5. Received 24 packets, got 24 answers, remaining 6 packets 
    6.    220.181.38.148:tcp80  
    7. 2  10.36.76.13     11    
    8. 3  10.102.252.34   11    
    9. 4  117.49.35.138   11    
    10. 5  116.251.112.185 11    
    11. 6  36.110.217.9    11    
    12. 7  36.110.246.201  11    
    13. 8  220.181.17.150  11    
    14. 14 220.181.38.148  SA    
    15. 15 220.181.38.148  SA    
    16. 16 220.181.38.148  SA    
    17. 17 220.181.38.148  SA    
    18. 18 220.181.38.148  SA    
    19. 19 220.181.38.148  SA    
    20. 20 220.181.38.148  SA    
    21. 21 220.181.38.148  SA    
    22. 22 220.181.38.148  SA    
    23. 23 220.181.38.148  SA    
    24. 24 220.181.38.148  SA    
    25. 25 220.181.38.148  SA    
    26. 26 220.181.38.148  SA    
    27. 27 220.181.38.148  SA    
    28. 28 220.181.38.148  SA    
    29. 29 220.181.38.148  SA    
    30. 30 220.181.38.148  SA    
    31. (<Traceroute: TCP:17 UDP:0 ICMP:7 Other:0>, 
    32.  <Unanswered: TCP:6 UDP:0 ICMP:0 Other:0> 

    使用DNS跟踪路由

    我们可以通过在traceroute()函数的l4参数中指定完整的数据包来执行DNS跟踪路由

    1. >>> ans,unans=traceroute("60.205.177.168",l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="thesprawl.org"))) 
    2. Begin emission: 
    3. ****Finished sending 30 packets. 
    4. ................. 
    5. Received 21 packets, got 4 answers, remaining 26 packets 
    6.   60.205.177.168:udp53  
    7. 1 10.2.0.1        11    
    8. 2 114.242.29.1    11    
    9. 4 125.33.185.114  11    
    10. 5 61.49.143.2     11  

    本文转载自微信公众号「运维开发故事」,可以通过以下二维码关注。转载本文请联系运维开发故事公众号。

    【编辑推荐】

    1. 鸿蒙官方战略合作共建——HarmonyOS技术社区
    2. 全国程序员岗位5月平均工资,你过线了吗?
    3. Windows必备的5款软件!一旦试用欲罢不能,赶紧收藏
    4. 这几款良心软件,让你的 Windows 爽到爆
    5. 2021年,薪酬最高的5种编程语言
    6. 如何在Linux上安装密码管理器1Password?
    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
    3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
    7. 如遇到加密压缩包,默认解压密码为"www.yoozai.net",如遇到无法解压的请联系管理员!
    悠哉网 » 数据包处理利器—Scapy高级使用(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    悠哉网 WWW.YOOZAI.NET
    悠哉网,用户消费首选的网站,喜欢你就悠哉一下。

    发表评论

    • 1072会员总数(位)
    • 40643资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 487稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情