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'
就足够了 - 如果您不打算写入您正在阅读的文件,则 +
不是必需的,并且会产生意外的风险覆盖文件。)
我已经实现了一个脚本来解析 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'
就足够了 - 如果您不打算写入您正在阅读的文件,则 +
不是必需的,并且会产生意外的风险覆盖文件。)