Python:解析erf文件在linux下工作,但不能在windows下工作

时间:2016-01-05 10:40:11

标签: python-2.7 wireshark

我已经实现了一个脚本来解析ERF文件以从数据包中获取DNS记录。该脚本在Linux下运行,但不能在Windows下运行。

我试图简化它并从文件中只读取两个数据包,结果完全错误。

以下是前两个数据包的输出:

rlen 1232
wlen 1213
ts:  (5822080496043415499L,)
rec len:  1232
protocol:  6  rem  1180
tcp
src port:  59626
remaining length based on the erf header 1160 remaining length based in IP total length 1155
----------------------
rlen 44076
wlen 13638
ts:  (246640611164160L,)
rec len:  44076
protocol:  9  rem  44024
----------------------

对于第一个数据包,输出是正确的,但对于第二个数据包,一切都是错误的。我所做的是从ERF头读取记录长度以跟踪数据包边界。当我打印tcp的有效负载时,我发现下一个数据包的erf头是在tcp的有效负载中。当我在linux下运行代码时,这个问题并没有发生。

谁能告诉我我做错了什么?

这是我的代码:

if __name__ == '__main__':

    argv= sys.argv
    outputFile=''
    inputFile=''
    dnsPacketCounter=0
    ethH = {}
    ipHeader = {}
    ipH = {}
    totalPackets=0



    if len(argv) ==1:
        print 'erfParser.py -i <inputfile> -o <outputfile>'
        sys.exit(0)
    elif len(argv) == 2:
        if argv[1] == '-h':
            print 'erfParser.py -i <inputfile> -o <outputfile>'
        sys.exit(0)
    elif len(argv) == 5:
        if argv[1] == '-i':
            inputFile = argv[2].strip()
        elif argv[3] == '-i':
            inputFile = argv[4].strip()
        if argv[1] == '-o':
            outputFile = argv[2].strip()
        elif argv[3] == '-o':
            outputFile= argv[4].strip()
    else: 
        # Open the trace file
        print 'erfParser.py -i <inputfile> -o <outputfile>'
        sys.exit(0)
    try:
        packets = open(inputFile , 'r+')
    except IOError:
        print 'The file: ',inputFile,' not found.'
        sys.exit(0)
    try:
        outFile=open(outputFile+'.txt', 'w+')
    except IOError:
        print 'The file: ',outputFile,' can not be opened.'
        sys.exit(0)

    ts=packets.read(8)
    i=0
    while ts:
        erf={}
        hdr = packets.read(8)
        #print ts.encode('hex')
        totalPackets=totalPackets+1
        erf= getERFHeader(ts,hdr)
        print 'rlen',erf['rlen']
        print 'wlen',erf['wlen']
        print 'ts: ',erf['ts']
        remainingLength=erf['rlen']- 16
        print 'rec len: ',erf['rlen']
        if erf['type'] == 0x07:
            ext=packets.read(8)
            remainingLength=remainingLength- 8
        pad=packets.read(2) # pad
        remainingLength=remainingLength- 2
        ethH= packets.read(14) # ethernet header `16 bytes
        remainingLength=remainingLength- 14    
        ipHeader= packets.read(20) #ip header length is 20 bytes
        remainingLength=remainingLength- 20
        ipH= getIPHeader(ipHeader)

        print 'protocol: ',ipH['protocol'],' rem ',remainingLength
        if ipH['protocol'] ==TCP:
            print 'tcp'
            hdr = packets.read(20)
            remainingLength=remainingLength- 20
            tcpHeader=getTCPHeader(hdr)
            tcpPayload= packets.read(remainingLength)
            print 'src port: ',tcpHeader['srcPort']
           # print 'tcp payload in hex: ',tcpPayload.encode('hex')
            print 'remaining length based on the erf header',remainingLength,'remaining length based in IP total length' ,ipH['totalL']-40
        print '----------------------'
        ts=packets.read(8)

        i=i+1
        if i==2:
            break;

    pass

1 个答案:

答案 0 :(得分:1)

  

谁能告诉我我做错了什么?

是的,我可以告诉你,你是以文本模式而不是二进制模式打开文件:

packets = open(inputFile , 'r+')

引用the Python documentation for open()

  

模式'r+''w+''a+'打开文件进行更新(读写);请注意'w+'截断文件。将'b'附加到模式以在二进制模式下打开文件,在区分二进制文件和文本文件的系统上;在没有这种区别的系统上,添加'b'无效。

UN * Xes,例如Linux是&#34;系统没有这种区别&#34;,因为Python open()是以&#34;的UN * X版本为模型的。标准I / O库&#34;,其中行以\n结尾。在Windows上,行以\r\n结尾,并在&#34;标准I / O库中打开&#34;可以:

  • 以文字模式打开,其中行末尾的\r\n在读取时会以\n\n的形式显示给程序line,写成\r\n,因此为UN * X编写的程序可以在Windows上运行,而不必担心行尾序列;
  • 以二进制模式打开,在这种情况下,read会准确显示文件中的字节数,而write会将给定的字节放入文件中;

因此,它是一个“区分”二进制文件和文本文件的系统,至少在某些I / O库中是这样。 (在I / O的最低级别,即CreateFile()ReadFile()WriteFile()调用,Windows没有这样的区别 - 它将文件视为原始字节序列,没有& #34;以文本&#34;选项打开,正如UN * X系统对open()read()write()所做的那样 - 但是在I / O的所有级别上都是有意的UN * X兼容,它们提供文本与二进制选项。)

ERF文件是二进制文件,因此您需要使用'rb+''r+b'而不是'r+'打开。这对UN * Xes(如Linux)没有任何影响,但会在Windows上为您提供原始二进制数据。

(实际上,只需'rb'即可 - 如果您不打算写信给您正在阅读的文件,则+不是必需的,并创建意外覆盖文件的风险。)