1. 介绍
scapy是一个可用于网络嗅探的非常强大的第三方库。在网络嗅探方面前面的博文介绍过通过Raw Socket进行网络嗅探,但是Raw Socket比较底层,使用起来可能不太容易而且在不同的系统上也有一定的区别。
在网络流量嗅探方面,常用的一些第三方库:
- pylibpcap
- pycapy
- pypcap
- impacket
- scapy
接下来我详细介绍下scapy的使用,它在这些库中功能最强大使用也最灵活。具有以下几个特点:
- 交互模式,用作第三方库。
- 可以用来做packet嗅探和伪造packet。
- 已经在内部实现了大量的网络协议。(DNS,ARP,IP,TCP,UDP等等)
- 可以用它来编写非常灵活实用的工具。
更详细的信息可参考官方scapy使用说明书。
2. 使用scapy
2.1 scapy安装
既然是第三方库,系统上默认是没有安装的。在Ubuntu下,我们可以直接使用以下命令进行安装:
sudo apt-get install scapy
安装完成以后,只需要在终端下执行sudo scapy
就可以进入scapy的命令行模式。
2.2 scapy可用到的协议层次
- ls() 列出scapy中已实现的网络协议。还有很多下图中没有列举出来,可亲自试验一下便知。
- ls(IP) 列出IP协议头部字段格式。
- IP().show() 显示包的IP信息。
- lsc() 列出scapy中可以使用的命令或函数。
- conf scapy配置选项
2.3 scapy嗅探示例
在scapy命令模式下,异常输入以下代码进行试验。
1)、嗅探流量包。
>>>
>>> pkts = sniff(iface = "eth0",count = 3 )
>>>
>>> pkts
<Sniffed: TCP:3 UDP:0 ICMP:0 Other:0>
>>>
sniffer函数进行嗅探流量,iface表示使用的网卡接口,count是嗅探包的个数。结果显示嗅探到了3个TCP包。可以输入pkts[i]查看包的具体内容。
>>> pkts[0]
<Ether dst=40:6c:8f:2e:d5:c4 src=08:00:27:35:42:59 type=0x800 |<IP version=4L ihl=5L tos=0x0 len=100 id=49675 flags=DF frag=0L ttl=64 proto=tcp chksum=0xf4ca src=192.168.1.14 dst=192.168.1.95 options=[] |<TCP sport=ssh dport=61557 seq=3819086788L ack=2841623555L dataofs=8L reserved=0L flags=PA window=4706 chksum=0x8414 urgptr=0 options=[(‘NOP‘, None), (‘NOP‘, None), (‘Timestamp‘, (201493961, 1254273559))] |<Raw load=‘\xc7\xb9 \xa7.\xa4\xd1\xf7\x90\xe2\x04\x8c\xb5\xd4Y:\xc5\x0eD*+e]*\xb2\xf1O(\xc3\x93\xd2\x96\x14\xfb\n\x1cGD>\x96\x86>$\x00\xcc\x95\xff`‘ |>>>>
>>>
>>>
可以看到以太网帧头各个字段的具体值,还有后面跟的协议类型,这里是IPv4,还有IP个字段的值以及IP上层的TCP协议及其字段值。如果感觉还是不够清晰,可以使用pkts[i].show()
更加清楚明了的看到packet中各协议字段的具体值。
2)、将嗅探到的packet内容写到pcap文件中和读取pcap文件。
>>>
>>>
>>> wrpcap("demo.pcap",pkts)
>>>
>>>
>>> read_pkts = rdpcap("demo.pcap")
>>>
>>> read_pkts[0]
<Ether dst=40:6c:8f:2e:d5:c4 src=08:00:27:35:42:59 type=0x800 |<IP version=4L ihl=5L tos=0x0 len=100 id=49675 flags=DF frag=0L ttl=64 proto=tcp chksum=0xf4ca src=192.168.1.14 dst=192.168.1.95 options=[] |<TCP sport=ssh dport=61557 seq=3819086788L ack=2841623555L dataofs=8L reserved=0L flags=PA window=4706 chksum=0x8414 urgptr=0 options=[(‘NOP‘, None), (‘NOP‘, None), (‘Timestamp‘, (201493961, 1254273559))] |<Raw load=‘\xc7\xb9 \xa7.\xa4\xd1\xf7\x90\xe2\x04\x8c\xb5\xd4Y:\xc5\x0eD*+e]*\xb2\xf1O(\xc3\x93\xd2\x96\x14\xfb\n\x1cGD>\x96\x86>$\x00\xcc\x95\xff`‘ |>>>>
>>>
>>> read_pkts[1]
<Ether dst=08:00:27:35:42:59 src=40:6c:8f:2e:d5:c4 type=0x800 |<IP version=4L ihl=5L tos=0x10 len=52 id=51922 flags=DF frag=0L ttl=64 proto=tcp chksum=0xec23 src=192.168.1.95 dst=192.168.1.14 options=[] |<TCP sport=61557 dport=ssh seq=2841623555L ack=3819086836L dataofs=8L reserved=0L flags=A window=4094 chksum=0x6ed5 urgptr=0 options=[(‘NOP‘, None), (‘NOP‘, None), (‘Timestamp‘, (1254273559, 201493961))] |>>>
>>>
>>>
3)、为sniffer函数添加过滤条件。
用过wireshark或者tcpdump的coders都知道,网络中的流量是庞大而复杂的,有时候我们需要增加一些特定的条件将我们想要看到的数据筛选出来。比如filter= "udp"
。
>>>
>>> pkts = sniff(iface = "eth0",filter = "udp",count = 3 )
>>>
>>> pkts[1]
<Ether dst=01:00:5e:40:98:8f src=f0:4d:a2:ec:0e:ae type=0x800 |<IP version=4L ihl=5L tos=0x0 len=164 id=12947 flags= frag=0L ttl=1 proto=udp chksum=0x3ca4 src=192.168.1.26 dst=239.192.152.143 options=[] |<UDP sport=63896 dport=6771 len=144 chksum=0xd3c7 |<Raw load=‘BT-SEARCH * HTTP/1.1\r\nHost: 239.192.152.143:6771\r\nPort: 6881\r\nInfohash: 84d2ada63a5dababde669f25018befe1e5c1a0d7\r\ncookie: 973480f9\r\n\r\n\r\n‘ |>>>>
>>> pkts[2]
<Ether dst=01:00:5e:40:98:8f src=f0:4d:a2:ec:0e:ae type=0x800 |<IP version=4L ihl=5L tos=0x0 len=164 id=12948 flags= frag=0L ttl=255 proto=udp chksum=0x3ea2 src=192.168.1.26 dst=239.192.152.143 options=[] |<UDP sport=6771 dport=6771 len=144 chksum=0xb2ed |<Raw load=‘BT-SEARCH * HTTP/1.1\r\nHost: 239.192.152.143:6771\r\nPort: 6881\r\nInfohash: 84d2ada63a5dababde669f25018befe1e5c1a0d7\r\ncookie: 973480f9\r\n\r\n\r\n‘ |>>>>
>>>
>>>
3)、动态打印出概要结果。
在scapy命令模式中输入命令pkts = sniff(iface = "eth0",filter = "icmp",count = 30, prn = lambda x: x.summary())
,这里我把嗅探包的数量提高到30,然后过滤ICMP协议类型的包。一边等待显示结果,可以另起一个终端,然后ping一个网址,观察嗅探现实的结果。
4)、帧与字符串的互相转换
>>>
>>>
>>> icmp_str = str(pkts[0])
>>>
>>> icmp_str
"@l\x8f.\xd5\xc4\x08\x00‘5BY\x08\x00E\x00\x00d\xc3\xdd@\x[email protected]\x06\xf2\xf8\xc0\xa8\x01\x0e\xc0\xa8\x01_\x00\x16\xf0u\xe3\xa3;\x04\xa9`\nS\x80\x18\x13\xcc\x84\x14\x00\x00\x01\x01\x08\n\x0c\x0b+\xa9J\xe5\x14\xccz\x19\x82\xbd\\$\xc7Y\x1c\x1c\xf0\xb5a\x9e\xa3\x0b7\x0c\xf0\xcb\xa[email protected]\x86,\xd8\xc5yJ_Q\xaaQ\xf5\x98\xd5<_q\x15B\xab\xceE\xa8&\x9d\x0b\x95"
>>>
>>> recombine = Ether(icmp_str)
>>>
>>> recombine
<Ether dst=40:6c:8f:2e:d5:c4 src=08:00:27:35:42:59 type=0x800 |<IP version=4L ihl=5L tos=0x0 len=100 id=50141 flags=DF frag=0L ttl=64 proto=tcp chksum=0xf2f8 src=192.168.1.14 dst=192.168.1.95 options=[] |<TCP sport=ssh dport=61557 seq=3819125508L ack=2841643603L dataofs=8L reserved=0L flags=PA window=5068 chksum=0x8414 urgptr=0 options=[(‘NOP‘, None), (‘NOP‘, None), (‘Timestamp‘, (202058665, 1256527052))] |<Raw load=‘z\x19\x82\xbd\\$\xc7Y\x1c\x1c\xf0\xb5a\x9e\xa3\x0b7\x0c\xf0\xcb\xa[email protected]\x86,\xd8\xc5yJ_Q\xaaQ\xf5\x98\xd5<_q\x15B\xab\xceE\xa8&\x9d\x0b\x95‘ |>>>>
>>>
5)、导入导出base64编码格式的数据
>>>
>>>
>>> export_object(str(pkts[0]))
eNoBeQCG/4ACVXJAbI8u1cQIACc1QlkIAEUAAGTD3UAAQAby+MCoAQ7AqAFfABbwdeOjOwSpYApT
gBgTzIQUAAABAQgKDAsrqUrlFMx6GYK9XCTHWRwc8LVhnqMLNwzwy6FAhizYxXlKX1GqUfWY1Txf
cRVCq85FqCadC5VxAS4+6i3U
>>>
>>> newPkt = import_object() #将上一步导出的字符串填入,回车,"ctrl_+d"结束。
eNoBeQCG/4ACVXJAbI8u1cQIACc1QlkIAEUAAGTD3UAAQAby+MCoAQ7AqAFfABbwdeOjOwSpYApT
gBgTzIQUAAABAQgKDAsrqUrlFMx6GYK9XCTHWRwc8LVhnqMLNwzwy6FAhizYxXlKX1GqUfWY1Txf
cRVCq85FqCadC5VxAS4+6i3U
>>> newPkt
"@l\x8f.\xd5\xc4\x08\x00‘5BY\x08\x00E\x00\x00d\xc3\xdd@\x[email protected]\x06\xf2\xf8\xc0\xa8\x01\x0e\xc0\xa8\x01_\x00\x16\xf0u\xe3\xa3;\x04\xa9`\nS\x80\x18\x13\xcc\x84\x14\x00\x00\x01\x01\x08\n\x0c\x0b+\xa9J\xe5\x14\xccz\x19\x82\xbd\\$\xc7Y\x1c\x1c\xf0\xb5a\x9e\xa3\x0b7\x0c\xf0\xcb\xa[email protected]\x86,\xd8\xc5yJ_Q\xaaQ\xf5\x98\xd5<_q\x15B\xab\xceE\xa8&\x9d\x0b\x95"
>>> Ether(newPkt)
<Ether dst=40:6c:8f:2e:d5:c4 src=08:00:27:35:42:59 type=0x800 |<IP version=4L ihl=5L tos=0x0 len=100 id=50141 flags=DF frag=0L ttl=64 proto=tcp chksum=0xf2f8 src=192.168.1.14 dst=192.168.1.95 options=[] |<TCP sport=ssh dport=61557 seq=3819125508L ack=2841643603L dataofs=8L reserved=0L flags=PA window=5068 chksum=0x8414 urgptr=0 options=[(‘NOP‘, None), (‘NOP‘, None), (‘Timestamp‘, (202058665, 1256527052))] |<Raw load=‘z\x19\x82\xbd\\$\xc7Y\x1c\x1c\xf0\xb5a\x9e\xa3\x0b7\x0c\xf0\xcb\xa[email protected]\x86,\xd8\xc5yJ_Q\xaaQ\xf5\x98\xd5<_q\x15B\xab\xceE\xa8&\x9d\x0b\x95‘ |>>>>
>>>