python中对2进制文件的解析提供了一个struct的模块,利用这个模块可以实现python对pcap文件的解析
今天下午闲来无事,就顺手写了一下,写的很粗糙,很多细节没去考虑,找了最简单的icmp包试验了一下,暂时没发现问题。。。
这个是主要的代码,代码主要打印了ip头部的信息,不过没有考虑到ip扩展头的情况
- #!/usr/bin/env python
- # -*- coding = UTF-8 -*-
- import sys
- from struct import pack,unpack
- from ip import print16
- from ip import str_to_addr
- from ip import addr_to_strn
- from ip import addr_to_strh
- '''
- pcap file = pcap_file_header + pcap_header + skb +...
- pcap_file_header 24B, pcap_header 16B
- '''
- pcap_file_header = ['majic','version_major','version_minor','zone','max_len','time_stap','link_type']
- pcap_header = ['gmt_time','micro_time','pcap_len','len']
- ip_header = ['version,ihl','tos','tot_len','id','frag_off','ttl','protocol','check','saddr','daddr']
- def print_mac_head(skb):
- pass
- def print_ip_head(skb):
- head = unpack('!BBHHHBBHII',skb[0:20])
- #print "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x" %(head)
- skb_head = dict(zip(ip_header,head))
- for key in skb_head.keys():
- if(key == 'saddr' or key == 'daddr'):
- print key,addr_to_strh(skb_head[key])
- else:
- print key,skb_head[key]
- def main():
- if(len(sys.argv) != 2):
- print 'Usage: ./pcap.py file.pcap'
- else:
- fp = open(sys.argv[1],'rb')
- text = fp.read()
- index = 0
- #pcap file head
- head1 = unpack('IHHIIII',text[index:24 + index])
- index += 24
- file_head = dict(zip(pcap_file_header,head1))
- print file_head
- while(index < len(text)):
- head2 = unpack('IIII',text[index:16 + index])
- index += 16
- pcap_head1 = dict(zip(pcap_header,head2))
- #print pcap_head1
- pcap_len = pcap_head1['pcap_len']
- #print pcap_len
- skb = text[index : pcap_len + index]
- print_mac_head(skb[:14])
- print_ip_head(skb[14:])
- index += pcap_len
- if __name__ == '__main__':
- main()
其中的ip模块是自己写的,主要为了实现C语言中的inet_addr及反向转换的过程,socket模块中应该有类似的实现,不过那个模块还没玩过,暂时将就下。。
- #!/usr/src/env python
- # -*- coding = UTF-8 -*-
- import sys
- ip_mask=[0,8,16,24]
- ip_mask2 = [24,16,8,0]
- def print16(num):
- print '0x%x'%(num)
- #转换成网络字节序
- def str_to_addr(s):
- ip = ( int(i) for i in s.split('.'))
- return reduce(lambda x,y:x+y,map(lambda x:x[0] << x[1],zip(ip,ip_mask)))
- #网络字节序显示
- def addr_to_strn(s):
- return '.'.join([str((s & (0xff << x)) >> x) for x in ip_mask])
- #主机字节序显示
- def addr_to_strh(s):
- return '.'.join([str((s & (0xff << x)) >> x) for x in ip_mask2])
struct基本上能够完成对于二进制文件的格式解析,但是遇到的一个主要问题就是,它最低解析位是unsigned char类型,即一个字节,对于C语言中的位格式,比如ip头部中的 u8 ihl:4; u8 version:4 , 暂时没发现什么好的方法把它解析出来,这点是使用起来不太爽的地方。
当然也可能是自己还没发现正确的使用方法。。。
阅读(11441) | 评论(1) | 转发(0) |