3

好的,所以我认为熟悉 Python 是个好主意。(我有过Java、php、perl、VB等方面的经验,不是什么高手,而是中级知识)

所以我正在尝试编写一个脚本,该脚本将从套接字中获取数据,并将其转换为屏幕。要遵循的粗略开始代码:

我的代码似乎正确地从套接字读取二进制信息,但我无法解压缩它,因为我无权访问原始结构。

我有这个流的输出和不同的程序,(写得很糟糕,这就是我要解决这个问题的原因)

当我打印出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

现在,根据我的研究,看起来我需要使用“结构”并将其解压缩,但是我不知道它的原始结构,我只知道从中可以获得哪些信息,老实说,我搞清楚这件事真是费了好大劲。

我已经使用 python 解释器尝试解开该行的点点滴滴,但这是一个令人沮丧的练习。

如果有人至少可以帮助我入门,我将非常感激。

谢谢

4

4 回答 4

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 小时,所以我假设这是一个时区的事情。

于 2013-04-25T19:32:21.923 回答
0

在不知道二进制流的结构的情况下,虽然有足够的时间对其进行逆向工程,但很难解析,你可能会接近或幸运。

虽然如果客户端程序使用了 pickle 协议,那么你很幸运。

于 2013-04-25T18:55:30.340 回答
0

到目前为止,我只对代码进行了逆向工程,而不是二进制流,所以我远非你所面临挑战的专家。但是,我想就如何尝试解决您的问题分享我的想法。也许那里的某个人觉得这很有用(也许有时我自己一个人)。

TL;DR 相关教育视频:Harald Welte at 27C3

路线图

1. 背景

尽可能多地获取有关程序的信息(编程语言、已知的序列化程序/序列化格式、已知的怪癖等)、域、该领域的任何规范……

2. 收藏

收集流的足够长的部分,或者,如果您知道消息的外观(任何消息开始/消息结束标记),则收集适当的消息束。还要收集参考程序的相应输出。

3. 低垂的果实

尝试识别可以在有线协议和相应输出中轻松发现的字符串和数字。记下哪些部分不是很好理解。

4.睁大眼睛

通过查找有线协议消息中的重复和差异来扩展您的知识。尝试将那些“有趣的地方”与记录输出中的重复和差异相匹配。

5. 假设

根据你所知道的创建关于线路格式的假设。尤其要考虑第 1 步中的信息,这些信息可能会对您正在发生的事情有所帮助。另外,想想时间戳、序列号、校验和、消息头、元数据等等。

6. 验证

在代码中实现你的假设。针对您记录的数据集运行它以测试它是否按预期工作。然后,针对一组(可能更长的)新鲜样本——甚至你以前从未见过——来支持你的假设。如果出现问题,请返回步骤#5。

7.从头再来

根据需要循环执行上述步骤,直到您可以提取您需要的所有信息,甚至更多信息。

闭幕致辞

我认为进行密集测试是一个好主意,以便确信您对有线协议的理解是正确的。这包括 A) 单元测试,以确保您在测试新假设时不会破坏脆弱代码中的内容,以及 B) 如验证步骤中所述,将新样本扔到代码中并检查您的期望是否仍然有效。

但即便如此,你也可能错了。即使进行了彻底的测试,这也不能保证您的假设是正确的。随时准备以新的方式思考,因为看起来如此清晰的东西实际上可能完全不同。

如有必要,请疯狂了解有线格式中可能隐藏的其他内容或事物的排列和/或关联方式。

在我的这段可能无用的文本之后,让我以一段视频结束:Harald Welte 在 27C3关于对真实世界的 RFID 支付系统进行逆向工程。

于 2013-04-25T20:40:11.553 回答
0

我会说你使用 struct 是对的,但 struct 的糟糕之处在于你总是必须知道原始结构。

也许阅读 tcp 规范和 iso 会有所帮助,尽管弄清楚它仍然是一个地狱:/

于 2013-04-25T18:45:19.697 回答