Python-Scapy

Scapy在大一的时候就学习了,但是当时做的笔记比较简陋,当时是写在本子上的,如果本子丢了还真就忘了…..
自从用了onenote,可以把学过的所有的相关知识都放到一个标签页面,很好很强大,所以重新学习一遍,一方面是整理笔记,二来也是加深印象同时也分享下所学的知识

贴一张自己的Onenote

学习的是乾颐堂秦柯老师讲的scapy
http://edu.51cto.com/course/7506.html

Scapy基础知识

乾颐堂上课用的是Python3.4(Fedora) + secureCRT+ WinSCP
上课环境拓扑

具体安装过程请看课程或百度。

包内的基础知识

当你铸造包的时候,scapy有一个默认值,不可能每个值都让你填
a = Ether()/IP()/TCP()
a.show()
看一下构造以太网/IP/TCP三种包的默认头部是什么

里边有相当一部分的默认值,这里用一个ARP包的请求包和响应包来学习里边字段的意思,在学习之前,我们先来看一下关于Scapy的发包方式

关于scapy的发包

带p的是二层包(要手写以太网头部),没有p的是三层包(二层的自动帮我处理)
sr() #发一个,可以收到很多
sr1() #发一个,只要一个响应
srp() #二层包,要手写以太网头部
send() #只管发,不关心返回的东西(可以涉及到flood相关的知识)
sendp() #二层包。

经典的ARP抓包

这是ARP数据帧的结构

我们来通过构造ARP包手动操作一个ARP请求

构造包

arp = srp(Ether(src=’00:0c:29:3d:5e:ec’,dst=’FF:FF:FF:FF:FF:FF’)/ARP(op=1,hwsrc=’00:0c:29:3d:5e:ec’,hwdst=’00:00:00:00:00:00’,psrc=’192.168.19.130’,pdst=’192.168.19.1’))

关于srp的意思在上边写了,Ether的src代表本地MAC(这使我虚拟机一块虚拟网卡的MAC),dst为全F,代表广播。
ARP中的op代表操作位,1是请求,2是响应,hwsrc代表本地硬件地址(MAC地址),hwdst全0(我们这要问192.168.19.1它的MAC是多少,填全0),psrc代表逻辑本地地址(IP地址),pdst代表你要询问的目的地址。

我们看到我们收到了一个响应,在这里我们需要学习如何去分析包。

分析包


在图中我们看到收到了一个other的回应,因为ARP不是TCP也不是UDP更不是ICMP,返回的结果是一个元组

我们需要看的是有结果的而不是未响应的,所以是arp[0]

我们想看到里边的内容,把包产生为清单,arp[0].res
这里需要好好注意一下,我们看到返回的是一个列表,而列表里边只有一个元组(当我们收到多少个包,这个列表就会出现多少个元组),这个元组里边分别是请求包和响应包。

因为请求包是我们自己构造的,所以我们查看第一个元组的第二部分 arp[0].res[0][1]

里边东西太多,我们看起来不舒服,想让这个包产生为字典,通过arp[0].res[0][1].fields
因为这个包是由192.168.19.1向我们发送过来的,所以源MAC地址是它的MAC地址,而目标MAC是我们自己的

其实在这里还是需要注意一点,我们show一下

发现有3个头部,我们刚才使用arp[0].res[0][1].fields默认读取的是以太网头部,你如果想要看ARP的或者是负载的可以用arp[0].res[0][1][x].fields 0是以太网,1是ARP,2是负载

这样我们就可以打印源IP地址所对应的MAC地址
源IP地址 + result_raw[0].res[0][1][0].fields[‘psrc’]
源MAC地址 + result_raw[0].res[0][1][0].fields[‘hwsrc’]

知识补充

这里还需要补充一点知识,就是关于ARP数据包

Ether中
协议类型:0x0806(正常是0x0800,代表IPv4)
ARP中
Hardware:1 硬件地址为1代表以太网
Hardware Addr Length:6 以太网地址长度是6个字节
Protocol Addr Length:4 IP地址长度是4个字节
接下来就是源硬件地址IP地址,目的硬件地址IP地址

这里边还有一个额外的数据,MTU不能超过1500否则要分片,最小MTU是46,ARP头部是28,所以要加18补够最小MTU才会发包。

MTU:最大传输单元,指一种通信协议的某一层上面所能通过的最大数据报大小(字节为单元)。
MTU越大,一个协议数据单元的承载的有效数据就越长,通信效率也就越高,传送给相同用户数据需要的数据包个数也就越少,
MTU越大,通信效率越高产生的传输延迟也就越大。

产生一个PING包

这个其实应该放在ARP之前,也是比较经典的一个例子

ping = sr1(IP(dst=’目标IP’,ttl=1,id=168)/ICMP(id=188,seq=1)/b’Welcome to china!’)
ping.show()

自己去看看返回了哪些东西

Scapy其他知识

课程上到这也就差不多了,接下来的就是写脚本来练手了

ARP探测脚本

脚本见下Github

脚本一

用os和re模块来查询本地IP和MAC,然后用sys接收参数(其实用optparse也可以,是不是大材小用-.-),然后查询指定IP的MAC

脚本二

直接用ARP探测局域网内存活的IP,然后返回其MAC

脚本三

ARP毒化,中间人攻击,让指定的两个IP的MAC互换,欺骗路由器.

脚本四

Scapy监控异常ARP事件(ARP攻击),首先先了解网络里边IP和MAC对应关系,如果监控中出现IP和MAC不匹配或者一个IP对应多个MAC,就发出警告。
这里需要调用sniff来抓取ARP包,然后用一个函数来过滤。

Scapy SYN端口扫描

raw = sr(IP(dst=’192.168.19.1’)/TCP(dport=(1,5555),flags=”S”),verbose=False)

这里的dport支持元组,(开始端口,结束端口),我们可以利用这个来扫描目标开放的端口,效率更高,只是探测力度不够。flags是S也就是SYN,也就是成功发出去的请求包。

看到只有一个TCP响应。


我们看到目标向我们发过来的包里边,1539端口,发送的flags位是SA,也就是SYN+ACK,说明这个端口是开的,而本地这个端口也确实是打开的。

直接把老师的结果拿过来看看

脚本见Github.

Scapy实现防火墙开放端口扫描

防火墙身后有台服务器,所以防火墙必须为服务器开启端口号,探测防火墙到底为其内部的机器开放了哪些端口号

环境自己没有搭,其实要搭也可以,用PT拉进来ASA、路由器、PC,设好ACL,然后本地脚本来探测一下也是可以的。
脚本见gayhub。

拓扑见文章开头的拓扑。

第一步还是清除报错,引入scapy。

然后为scapy添加一条路由来让包从scapy到达防火墙后边的inside,这个路由只是单独为scapy添加的,linux是不看这个路由表。

这个包必须得有ttl,你得确认这个包到防火墙的瞬间TTL为0,然后inside向我们的scapy返回包,经过防火墙时防火墙检查是否开启了这个端口号,如果开启,那么给你返回一个ICMP的TTL超时,通过这样来确定防火墙对内部主机开放了哪些端口。

inter,间隔。每隔1秒发一个包,对于防火墙你不能太快。
timeout,超时,5秒要是还没有包就超时。如果没有超时scapy会等很久,你发过去的包的有些东西如果防火墙没有它可能不会给你响应。
verbose=False,不出现回显,就是发了多少个包收到了多少个等等。
ICMP TYPE CODE对应表中11,就是表示TTL为0.
其余见脚本。

Github

https://github.com/Yokeen/Scapy

若有差错,还望多多指正。