共计 9741 个字符,预计需要花费 25 分钟才能阅读完成。
文章目录[隐藏]
windows 下 pcapy 包下载地址:https://breakingcode.wordpress.com/2012/07/16/quickpost-updated-impacketpcapy-installers-for-python-2-5-2-6-2-7/
转自:http://www.cnblogs.com/xuanhun/p/5625186.html
涉及到的几个 python 网络抓包和分析的模块,dpkt和 scapy 在kali linux 2.0 中默认已经被安装,如果你的系统中没有需要手动安装一下,下面是软件包安装的简单说明。
在 kali 下安装 pypcap 需要两步(如果在其他系统上可能还需要安装python-dev):
apt-get install libpcap-dev
pip install pypcap
使用 pip 安装scapy。
root@kali:/home/pycharm# pip install scapy
使用 pip 安装scapy-http。
root@kali:/home/pycharm# pip install scapy-http
基础环境准备好之后,我还要再唠叨一下你必须要掌握的基础。
1.1 技术没有黑白,网络编程的基础是协议
把编程挂上黑客的名义,多少有些标题党。代码怎么写,程序怎么用,完全是技术问题。不会因为叫网络编程就低人一等,叫黑客编程也不会变得神秘或者高大上,代码就在那里,不卑微也不高尚。所以学习编程,要有颗平常心。
很多听课的同学和我反应,网络编程格外的吃力,繁琐,要实现某种功能,如果 Google 不到类似的代码就无法下手。各种语言或者框架针对网络编程的实现基本都相同,因为我们接触到网络通信都基于统一的规范和标准,语言和框架只是在用自己的方式去描述这个规范而已。本质的问题来了,如果你连基本的网络通信的四层模型都不懂,对 TCP/IP 协议族毫无概念,那么我奉劝你先不要着急敲代码,找本书,打开 WireShark 这样的工具好好做做练习。
本次课程中的所有案例,其实都在遵循一个基本的思路(其他网络通信场景类似):
初始化以太网数据包对象 à 以太网数据包分离出 ip 数据包 àIP 数据包分离传输层数据包 à 传输层数据包分离应用层数据包。
只要我们具备基础的网络知识,结合程序中各个对象提供的字段就能得到我们想要的任何基础信息,在此基础上做些信息处理就能完成大部分网络监听和数据处理的任务。附上几幅图,如果这方面有欠缺的话,请立即去充电吧!
以太网帧格式
ip数据包格式
Tcp数据包格式
1.2 使用 PYPCAP 实时抓包
pypcap进行实时的数据包捕获,使用上很简单,我们先看一小段示例代码:
import pcap
pc=pcap.pcap('wlan0') #注,参数可为网卡名,如eth0
pc.setfilter('tcp port 80') #2.设置监听过滤器
for ptime,pdata in pc: #ptime为收到时间,pdata为收到数据
print ptime,pdata #...
在上面的代码中,我们通过 “import pcap” 首先引入 pypcap 包,然后 初始化一个 pcap 类实例,构造函数需要传入一个网卡用来监听,我们可以通过 ifconfig 获取当前机器上的网卡。
pcap类的 setfilter 方法用来设置监听过滤条件,这里我们设置过滤的数据包为 tcp 协议 80 端口的数据。之后程序就进入监听状态了。
接下来我们循环输出接收到的数据,ptime为时间,pdata的数据,默认数据打印为 ascii 字符,效果如下:
在抓到数据包之后,下一步就需要对数据进行解析,这里我们引入 dpkt 组件包。
1.3 使用 DPKT 解析数据包
dpkt,简单来说是一个数据包解析工具,可以解析离线 / 实时 pcap 数据包。
1.3.1 实时解析
我们以下面的代码为例,讲解基本应用。
import pcap
import dpkt
def captData():
pc=pcap.pcap('wlan0') #注,参数可为网卡名,如eth0
pc.setfilter('tcp port 80') #设置监听过滤器
for ptime,pdata in pc: #ptime为收到时间,pdata为收到数据
anlyCap(pdata);
def anlyCap(pdata):
p=dpkt.ethernet.Ethernet(pdata)
if p.data.__class__.__name__=='IP':
ip='%d.%d.%d.%d'%tuple(map(ord,list(p.data.dst)))
if p.data.data.__class__.__name__=='TCP':
if p.data.data.dport==80:
print p.data.data.data # http 请求的数据
captData();
在上面代码中,我们首先导入 dpkt 包。这段代码中新增了一个 anlyCap 方法,该方法接收由 pcap 捕获的 http 数据包,然后先取得 ip 数据报文,从 ip 报文中再提取 tcp 数据包,最后从 tcp 数据包中提取 http 请求的数据,将其打印出来。
对于数据包的分析,新手可能会感到迷茫,如何选择合适的协议和方法来分析呢?这个问题的答案不在代码,而在于网络通信协议本身的掌握和理解。
回到上面的代码,我们想要分析 http 请求的数据,http是应用层协议,通过 TCP 协议来传输数据,那么 TCP 数据又被封装在 IP 数据报文中。使用 dpkt 的第一步就是选择数据包类型,这里当然是要选择以太网数据包了。
按照网络协议,层层剥离,会解析到所有你想要的数据。
1.3.2 解析离线数据包
下面我们来看一个解析离线数据包的例子。
import dpkt
import socket
#----------------------------------------------------------------------
def printPcap(pcap):
""""""
for(ts,buf) in pcap:
try:
eth=dpkt.ethernet.Ethernet(buf);
ip=eth.data;
src=socket.inet_ntoa(ip.src);
dst=socket.inet_ntoa(ip.dst);
tcp=ip.data;#tcp.dport tcp.sport
print '[+]Src: '+src+ ' --->Dst: '+ dst
except:
pass;
#----------------------------------------------------------------------
def main():
""""""
f=open('/home/pcap/test.pcap');#1.open file
pcap=dpkt.pcap.Reader(f);# init pcap obj
printPcap(pcap);
if __name__ == '__main__':
main();
首先我准备了一个测试的抓包文件 —test.pcap,该文件是我使用wireshark 在windows上抓取的数据包,现在使用代码对齐进行基本的分析。在方法 printPcap 中,获取 ip 数据报的内容,然后获取它的源 ip 和目标 ip 数据,通过 socket.inet_ntoa 方法转换成 ip 字符串,最后打印出来。结果如下图所示:
1.4 使用 SCAPY 进行数据监听
Scapy的是一个强大的交互式数据包处理程序(使用 python 编写)。它能够伪造或者解码大量的网络协议数据包,能够发送、捕捉、匹配请求和回复包等等。它可以很容易地处理一些典型操作,比如端口扫描,tracerouting,探测,单元 测试,攻击或网络发现(可替代 hping,NMAP,arpspoof,ARP-SK,arping,tcpdump,tethereal,P0F 等)。 最重要的他还有很多更优秀的特性——发送无效数据帧、注入修改的 802.11 数据帧、在 WEP 上解码加密通道(VOIP)、ARP缓存攻击(VLAN) 等,这也是其他工具无法处理完成的。
Scapy可以单独使用,也可以在 python 中调用。
1.4.1 Scapy基本使用
了解 Scapy 的基本使用和支持的方法,首先我们从终端启动scapy,进入交互模式。
ls()显示 scapy 支持的所有协议。
ls()函数的参数还可以是上面支持的协议中的任意一个的类型属性,也可以是任何一个具体的数据包,如 ls(TCP),ls(newpacket) 等。
lsc()列出 scapy 支持的所有的命令。
本篇文章使用的只是 scapy 众多命令中的一个,sniff。
conf:显示所有的配置信息。conf变量保存了 scapy 的配置信息。
help()显示某一命令的使用帮助,如help(sniff)。
show()显示指定数据包的详细信息。例如,这里我们先创建一个 IP 数据包,然后调用 show 方法。
sprintf()输出某一层某个参数的取值,如果不存在就输出 ”??”,具体的format 格式是 :%[[fmt][r],][layer[:nb].]field%,详细的使用参考<Security Power Tools> 的146页。
%[[fmt][r],][layer[:nb].]field%
layer:协议层的名字,如 Ether、IP、Dot11、TCP 等。
filed:需要显示的参数。
nb:当有两个协议层有相同的参数名时,nb用于到达你想要的协议层。
r:是一个标志。当使用 r 标志时,意味着显示的是参数的原始值。例如,TCP标志中使用人类可阅读的字符串 ’SA’ 表示 SYN 和ACK标志,而其原始值是18.
1.4.2 sniff
Scapy的功能如此强大,足够写个系列了,本文只关注 sniff 这一个方法。
sniff方法是用来嗅探数据的,我们首先使用 help 查看一下此方法的使用说明:
sniff(count=0, store=1, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, *arg, **karg)
Sniff packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
count: number of packets to capture. 0 means infinity
store: wether to store sniffed packets or discard them
prn: function to apply to each packet. If something is returned,
it is displayed. Ex:
ex: prn = lambda x: x.summary()
lfilter: python function applied to each packet to determine
if further action may be done
ex: lfilter = lambda x: x.haslayer(Padding)
offline: pcap file to read packets from, instead of sniffing them
timeout: stop sniffing after a given time (default: None)
L2socket: use the provided L2socket
opened_socket: provide an object ready to use .recv() on
stop_filter: python function applied to each packet to determine
if we have to stop the capture after this packet
ex: stop_filter = lambda x: x.haslayer(TCP)
除了上面介绍的几个参数,sniff()函数还有一个重要的参数是 filter,用来表示想要捕获数据包类型的过滤器,如只捕获ICMP 数据包,则 filter=”ICMP”; 只捕获 80 端口的 TCP 数据包,则 filter=”TCP and (port 80)”。 其他几个重要的参数有:count表示需要不活的数据包的个数;prn表示每个数据包处理的函数,可以是 lambda 表达式,如 prn=lambda x:x.summary();timeout 表示数据包捕获的超时时间。
sniff(filter="icmp and host 66.35.250.151", count=2)
这段代码过滤 icmp 协议,host地址为 66.35.250.151,捕获数据包个数为2 个。
sniff(iface="wifi0", prn=lambda x: x.summary())
这段代码绑定网卡 wifi0,对捕获的数据包使用summary 进行数据汇总。
sniff(iface="eth1", prn=lambda x: x.show())
这段代码绑定网卡 eth1,对数据包调用show 方法,显示基本信息。
下面我们看具体的一段代码:
from scapy.all import *
ap_list = []
def PacketHandler(pkt) :
if pkt.haslayer(Dot11) :
if pkt.type == 0 and pkt.subtype == 8 :
if pkt.addr2 not in ap_list :
ap_list.append(pkt.addr2)
print "AP MAC: %s with SSID: %s " %(pkt.addr2, pkt.info)
sniff(iface="wlan0mon", prn = PacketHandler)
上面这段代码对绑定网卡 WLAN0mon,对每个数据包调用PacketHandler 方法进行解析。PacketHandler实际上是通过数据包过滤可访问的无线网络 的SSID。
1.4.3 Scapy-http
Scapy-http直接将 数据包格式化成 http 数据信息,免去自己构建 http 数据结构进行解析的麻烦。
import scapy_http.http as HTTP
from scapy.all import *
from scapy.error import Scapy_Exception
count=0
def pktTCP(pkt):
global count
count=count+1
print count
if HTTP.HTTPRequest or HTTP.HTTPResponse in pkt:
src=pkt[IP].src
srcport=pkt[IP].sport
dst=pkt[IP].dst
dstport=pkt[IP].dport
test=pkt[TCP].payload
if HTTP.HTTPRequest in pkt:
#print "HTTP Request:"
#print test
print "======================================================================"
if HTTP.HTTPResponse in pkt:
print "HTTP Response:"
try:
headers,body= str(test).split("\r\n\r\n", 1)
print headers
except Exception,e:
print e
print "======================================================================"
else:
#print pkt[IP].src,pkt[IP].sport,'->',pkt[TCP].flags
print 'other'
sniff(filter='tcp and port 80',prn=pktTCP,iface='wlan0')
上面的这段代码,我们引入 scapy_http.http,该组件包可以直接将Http 请求的 TCP 数据包格式化成 HTTPRequest 或者 HTTPResponse 对象,这大大方便了我们对 HTTP 数据的分析。
• scapy_http在 github 上的开源地址为:https://github.com/invernizzi/scapy-http。
1.4.4 综合实例--net-creds
net-creds是一个小的开源程序,由 python 编写,主要是从网络或者 pcap 中嗅探敏感数据。可以嗅探以下类型的数据:
· URLs visited
· POST loads sent
· HTTP form logins/passwords
· HTTP basic auth logins/passwords
· HTTP searches
· FTP logins/passwords
· IRC logins/passwords
· POP logins/passwords
· IMAP logins/passwords
· Telnet logins/passwords
· SMTP logins/passwords
· SNMP community string
· NTLMv1/v2 all supported protocols like HTTP, SMB, LDAP, etc
· Kerberos
基本用法如下:
自动选择网卡进行嗅探:
sudo python net-creds.py
指定嗅探的网卡:
sudo python net-creds.py -i eth0
忽略指定 IP 的数据包:
sudo python net-creds.py -f 192.168.0.2
从 pcap 文件中过滤信息:
python net-creds.py -p pcapfile
建议读者能够静下心来阅读该程序的源码,本身并不是很复杂,难度不高。下面摘几段代码。
ipr = Popen(['/sbin/ip', 'route'], stdout=PIPE, stderr=DN)
for line in ipr.communicate()[0].splitlines():
if 'default' in line:
l = line.split()
iface = l[4]
return iface
上面这一段代码是利用 Popen 组件和 PIPE 组件来自动查找网卡。
def telnet_logins(src_ip_port, dst_ip_port, load, ack, seq):
'''
Catch telnet logins and passwords
'''
global telnet_stream
msg = None
if src_ip_port in telnet_stream:
# Do a utf decode in case the client sends telnet options before their username
# No one would care to see that
try:
telnet_stream[src_ip_port] += load.decode('utf8')
except UnicodeDecodeError:
pass
# \r or \r\n or \n terminate commands in telnet if my pcaps are to be believed
if '\r' in telnet_stream[src_ip_port] or '\n' in telnet_stream[src_ip_port]:
telnet_split = telnet_stream[src_ip_port].split(' ', 1)
cred_type = telnet_split[0]
value = telnet_split[1].replace('\r\n', '').replace('\r', '').replace('\n', '')
# Create msg, the return variable
msg = 'Telnet %s: %s' % (cred_type, value)
printer(src_ip_port, dst_ip_port, msg)
del telnet_stream[src_ip_port]
# This part relies on the telnet packet ending in
# "login:", "password:", or "username:" and being <750 chars
# Haven't seen any false+ but this is pretty general
# might catch some eventually
# maybe use dissector.py telnet lib?
if len(telnet_stream) > 100:
telnet_stream.popitem(last=False)
mod_load = load.lower().strip()
if mod_load.endswith('username:') or mod_load.endswith('login:'):
telnet_stream[dst_ip_port] = 'username'
elif mod_load.endswith('password:'):
telnet_stream[dst_ip_port] = 'password'
上面的代码是过滤 telnet 用户名和密码。首先对数据流就行 utf-8 解码,然后按照 telnet 协议对字符串进行分割和搜索,从而获取登录信息。
