Python:解析 erf 文件在 linux 下有效但在 windows 下无效

Python: Parsing erf file works under linux but doesn't work under windows

我已经实现了一个脚本来解析 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 header 读取记录长度以跟踪数据包边界。当我打印 tcp 的有效负载时,我发现下一个数据包的 erf header 在 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

Can anyone tell me what I'm doing wrong?

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

packets = open(inputFile , 'r+')

引用the Python documentation for open():

Modes 'r+', 'w+' and 'a+' open the file for updating (reading and writing); note that 'w+' truncates the file. Append 'b' to the mode to open the file in binary mode, on systems that differentiate between binary and text files; on systems that don’t have this distinction, adding the 'b' has no effect.

UN*X如Linux是"systems that don't have this distinction",因为Pythonopen()是仿照UN*X版本的"standard I/O library",其中行以 \n 结尾。在 Windows 上,行以 \r\n 结尾,在 "standard I/O library" 中打开可以:

  • 以文本模式打开,其中行尾的 \r\n 在读取时向程序显示为 \n,在写入时显示为 \n到一行,写成 \r\n,这样为 UN*X 编写的程序可以在 Windows 上运行,而不必担心 end-of-line 序列;
  • 以二进制模式打开,在这种情况下,读取会准确地为您提供文件中的字节,而写入会将给定的字节放入文件;

所以它是一个“[区分]二进制文件和文本文件”的系统,至少在某些 I/O 库中是这样。 (在 I/O 的最低级别,即 CreateFile()ReadFile()WriteFile() 调用,Windows 没有这样的区别——它将文件视为序列原始字节,没有 "open as text" 选项,就像 UN*X 系统对 open()read()write() 所做的一样 - 但在所有级别的 I/O 预期有点 UN*X-compatible,它们提供文本与二进制选项。)

ERF 文件是二进制文件,因此您需要使用 'rb+''r+b' 打开,而不是 'r+'。这对 Linux 等 UN*Xes 没有影响,但会在 Windows.

上为您提供原始二进制数据

(实际上,'rb' 就足够了 - 如果您不打算写入您正在阅读的文件,则 + 不是必需的,并且会产生意外的风险覆盖文件。)