所以我试图编写一个脚本,它将从套接字中获取数据,并将其转换为屏幕。粗略的开始代码:
我的代码似乎正确地从套接字读取二进制信息,但我无法解压缩它,因为我无法访问原始结构。
我使用不同的程序输出此流的输出(这是我写的很糟糕的原因)
当我打印出recv时,就像这样......
b'L\x00k\x07vQ\n\x01\xffh\x00\x04NGIN\x04MAIN6Product XX finished reprocessing cdc XXXXX at jesadr 0c\x00k\x07vQ\n\x01\xffF\x00\x06CSSPRD\x0cliab_checkerCCheckpointed to XXXXXXXXXXXXXXXX:XXXXXXX.XXX at jesadr 0 (serial 0)[\x00l\x07vQ\n\x00\xff\x01\x00\x05MLIFE\x06dayendBdayend 1 Copyright XXXX XXXXXXX XXXXXXX XXXXX XXX XXXXXX XXXXXXXX.
从这个看,并将它与其他程序的输出进行比较,我猜想它应该被分解为......
b'L\x00k\x07vQ\n\x01\xffh\x00\x04NGIN\x04MAIN6Product XX finished reprocessing cdc XXXXX at jesadr 0'
带有相应的信息
04-23
00:00:43
10
1
NGIN
MAIN
255
104
Product XX finished reprocessing cdc XXXXX at jesadr 0
现在,根据我的研究,看起来我需要使用“struct”并解压缩它,但是我不知道它的原始结构,我只知道它可以获得什么信息,并且是老实说,我有一段时间搞清楚这一点。
我已经使用python解释器试图解开该行的各个部分,但这是一种令人沮丧的练习。
如果有人能帮助我开始,我会非常感激。
由于
答案 0 :(得分:2)
好。我想我已经设法解码它,虽然我不确定中间的16位值。
这个Python 2.7代码......
from cStringIO import StringIO
import struct
import time
def decode(f):
def read_le16(f):
return struct.unpack('<h', f.read(2))[0]
def read_timestamp(f):
ts = struct.unpack('<l', f.read(4))[0]
return time.ctime(ts)
def read_byte(f):
return ord(f.read(1))
def read_pascal(f):
l = ord(f.read(1))
return f.read(l)
result = []
# Read total length
result.append('Total message length is %d bytes' % read_le16(f))
# Read timestamp
result.append(read_timestamp(f))
# Read 3 x byte
result.append(read_byte(f))
result.append(read_byte(f))
result.append(read_byte(f))
# Read 1 x LE16
result.append(read_le16(f))
# Read 3 x pascal string
result.append(read_pascal(f))
result.append(read_pascal(f))
result.append(read_pascal(f))
return result
s = 'L\x00k\x07vQ\n\x01\xffh\x00\x04NGIN\x04MAIN6Product XX finished reprocessing cdc XXXXX at jesadr 0c\x00k\x07vQ\n\x01\xffF\x00\x06CSSPRD\x0cliab_checkerCCheckpointed to XXXXXXXXXXXXXXXX:XXXXXXX.XXX at jesadr 0 (serial 0)[\x00l\x07vQ\n\x00\xff\x01\x00\x05MLIFE\x06dayendBdayend 1 Copyright XXXX XXXXXXX XXXXXXX XXXXX XXX XXXXXX XXXXXXXX.'
f = StringIO(s)
print decode(f)
print decode(f)
print decode(f)
... ...产量
['Total message length is 76 bytes', 'Tue Apr 23 05:00:43 2013', 10, 1, 255, 104, 'NGIN', 'MAIN', 'Product XX finished reprocessing cdc XXXXX at jesadr 0']
['Total message length is 99 bytes', 'Tue Apr 23 05:00:43 2013', 10, 1, 255, 70, 'CSSPRD', 'liab_checker', 'Checkpointed to XXXXXXXXXXXXXXXX:XXXXXXX.XXX at jesadr 0 (serial 0)']
['Total message length is 91 bytes', 'Tue Apr 23 05:00:44 2013', 10, 0, 255, 1, 'MLIFE', 'dayend', 'dayend 1 Copyright XXXX XXXXXXX XXXXXXX XXXXX XXX XXXXXX XXXXXXXX.']
时间戳超出了5个小时,所以我认为这是时区的事情。
答案 1 :(得分:0)
我会说你使用struct是正确的,但结构很糟糕的是,你总是必须知道原始结构。
也许阅读tcp规范和isos会对所有人有所帮助,虽然现在仍然很难搞清楚:/
答案 2 :(得分:0)
如果不知道二进制流的结构,虽然有足够的时间对其进行逆向工程,但很难解析,你可能会接近或幸运。
虽然如果客户端程序使用了pickle协议,那么你很幸运。
答案 3 :(得分:0)
到目前为止,我只是反向设计的代码,而不是二进制流,所以我远远不是你挑战的专家。但是,我想分享一下我将如何解决你的问题的想法。也许有人在那里发现有用(也许我自己在某个时间)。
TL; DR相关教育视频:Harald Welte at 27C3
获取有关该程序的更多信息(编程语言,已知的序列化器/序列化格式,已知的怪癖等),域,该领域的任何规范,......
收集流中足够长的部分,或者,如果您知道消息的外观(任何消息开头/消息结束标记),请收集一组适当的消息。还要收集参考程序的相应输出。
尝试识别可在线路协议和相应输出中轻松发现的字符串和数字。记下哪些部分不太清楚。
通过查找有线协议消息的重复和差异来扩展您的知识。尝试将这些“有趣的点”与记录输出中的重复和差异相匹配。
根据您所知道的内容创建有关电汇格式的假设。特别要考虑步骤#1中可能对您有所帮助的信息。另外,考虑一下时间戳,序列号,校验和,消息头,元数据等内容。
在代码中实现您的假设。根据您记录的数据集运行它,以测试它是否按预期工作。然后,反对一堆(可能更长)的新鲜样本 - 即使你以前没有见过 - 来支持你的假设。如果出现故障,请返回步骤#5。
根据需要循环执行上述步骤,直到您可以提取所需的所有信息,甚至可以提取更多信息。
我认为,为了确保您对线路协议的理解是正确的,我们需要进行密集测试。这包括A)单元测试,以确保您在测试新假设时不会破坏脆弱代码中的内容,并且B)在验证步骤中提到,将新样本抛给代码并检查您的期望是否仍然有效。 / p>
但即便如此,您可能也错了。即使经过全面测试,这也不是保证您的假设是正确的。总是准备以新的方式思考,因为事实证明,看起来如此清晰的事实上是完全不同的。
如果有必要,请大胆了解电线格式中可能隐藏的内容或事物的排列和/或相关方式。
在我的这个可能无用的文字之后,让我完成一个关于逆向工程现实世界RFID支付系统的视频:Harald Welte at 27C3。