无法在 Python 中重现有效的 C 按位编码函数
Can't reproduce working C bitwise encoding function in Python
我正在对一种专有网络协议进行逆向工程,该协议会在启动时生成一个(静态)一次性密码本,然后将其用于 encode/decode 每个数据包 sends/receives。它在一系列复杂的 XOR、移位和乘法中使用一次一密。
我用 IDA 遍历了程序中的解码函数后生成了以下 C 代码。这个功能encodes/decodes 数据完美:
void encodeData(char *buf)
{
int i;
size_t bufLen = *(unsigned short *)buf;
unsigned long entropy = *((unsigned long *)buf + 2);
int xorKey = 9 * (entropy ^ ((entropy ^ 0x3D0000) >> 16));
unsigned short baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
//Skip first 24 bytes, as that is the header
for (i = 24; i <= (signed int)bufLen; i++)
buf[i] ^= byteTable[((unsigned short)i + baseByteTableIndex) & 2047];
}
现在我想尝试为这个协议制作一个 Peach 模糊器。由于在进行模糊测试之前,我需要自定义 Python 修复来执行 encoding/decoding,因此我需要将此 C 代码移植到 Python.
我已经实现了以下 Python 函数,但在解码接收到的数据包时没有任何运气。
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[2:6])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
return str(newBuf)
我尝试过使用和不使用 array()
或 pack()
/unpack()
各种变量来强制它们成为按位运算的正确大小,但我必须遗漏了一些东西,因为我无法让 Python 代码像 C 代码那样工作。有谁知道我错过了什么?
如果它能帮助你在本地尝试这个,这里是一次性一密生成函数:
def buildXorPad():
global xorPad
xorKey = array('H', [0xACE1])
for i in range(0, 2048):
xorKey[0] = -(xorKey[0] & 1) & 0xB400 ^ (xorKey[0] >> 1)
xorPad = xorPad + pack('B',xorKey[0] & 0xFF)
这是十六进制编码的原始(编码)和解码数据包。
原文:20000108fcf3d71d98590000010000000000000000000000a992e0ee2525a5e5
解码:20000108fcf3d71d98590000010000000000000000000000ae91e1ee25252525
解决方案
原来我的问题与C和Python类型的区别没有太大关系,而是一些简单的编程错误。
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[8:12])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
padIndex = (i + baseByteTableIndex) & 2047
newBuf[i] ^= unpack('B',xorPad[padIndex])[0]
return str(newBuf)
感谢大家的帮助!
这一行C:
unsigned long entropy = *((unsigned long *)buf + 2);
应该翻译成
entropy = unpack('I', buf[8:12])
因为 buf
在将 2 添加到地址之前先转换为无符号长整型,这会向其添加 2 个无符号长整型的大小,而不是 2 个字节(假设无符号长整型的大小为 4 个字节) .
还有:
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
应该是
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
匹配C,否则输出实际上不是基于缓冲区的内容。
Python 整数不会溢出 - 当它们超过 sys.maxint
(或 -sys.maxint-1
)时,它们会自动提升到任意精度。
>>> sys.maxint
9223372036854775807
>>> sys.maxint + 1
9223372036854775808L
使用 array
and/or unpack
似乎没有什么不同(如您所见)
>>> array('H', [1])[0] + sys.maxint
9223372036854775808L
>>> unpack('H', '\x01\x00')[0] + sys.maxint
9223372036854775808L
要截断您的数字,您必须在每次增加变量大小时通过手动与适当的位掩码进行 ANDing 来模拟溢出。
我正在对一种专有网络协议进行逆向工程,该协议会在启动时生成一个(静态)一次性密码本,然后将其用于 encode/decode 每个数据包 sends/receives。它在一系列复杂的 XOR、移位和乘法中使用一次一密。
我用 IDA 遍历了程序中的解码函数后生成了以下 C 代码。这个功能encodes/decodes 数据完美:
void encodeData(char *buf)
{
int i;
size_t bufLen = *(unsigned short *)buf;
unsigned long entropy = *((unsigned long *)buf + 2);
int xorKey = 9 * (entropy ^ ((entropy ^ 0x3D0000) >> 16));
unsigned short baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
//Skip first 24 bytes, as that is the header
for (i = 24; i <= (signed int)bufLen; i++)
buf[i] ^= byteTable[((unsigned short)i + baseByteTableIndex) & 2047];
}
现在我想尝试为这个协议制作一个 Peach 模糊器。由于在进行模糊测试之前,我需要自定义 Python 修复来执行 encoding/decoding,因此我需要将此 C 代码移植到 Python.
我已经实现了以下 Python 函数,但在解码接收到的数据包时没有任何运气。
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[2:6])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
return str(newBuf)
我尝试过使用和不使用 array()
或 pack()
/unpack()
各种变量来强制它们成为按位运算的正确大小,但我必须遗漏了一些东西,因为我无法让 Python 代码像 C 代码那样工作。有谁知道我错过了什么?
如果它能帮助你在本地尝试这个,这里是一次性一密生成函数:
def buildXorPad():
global xorPad
xorKey = array('H', [0xACE1])
for i in range(0, 2048):
xorKey[0] = -(xorKey[0] & 1) & 0xB400 ^ (xorKey[0] >> 1)
xorPad = xorPad + pack('B',xorKey[0] & 0xFF)
这是十六进制编码的原始(编码)和解码数据包。
原文:20000108fcf3d71d98590000010000000000000000000000a992e0ee2525a5e5
解码:20000108fcf3d71d98590000010000000000000000000000ae91e1ee25252525
解决方案
原来我的问题与C和Python类型的区别没有太大关系,而是一些简单的编程错误。
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[8:12])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
padIndex = (i + baseByteTableIndex) & 2047
newBuf[i] ^= unpack('B',xorPad[padIndex])[0]
return str(newBuf)
感谢大家的帮助!
这一行C:
unsigned long entropy = *((unsigned long *)buf + 2);
应该翻译成
entropy = unpack('I', buf[8:12])
因为 buf
在将 2 添加到地址之前先转换为无符号长整型,这会向其添加 2 个无符号长整型的大小,而不是 2 个字节(假设无符号长整型的大小为 4 个字节) .
还有:
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
应该是
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
匹配C,否则输出实际上不是基于缓冲区的内容。
Python 整数不会溢出 - 当它们超过 sys.maxint
(或 -sys.maxint-1
)时,它们会自动提升到任意精度。
>>> sys.maxint
9223372036854775807
>>> sys.maxint + 1
9223372036854775808L
使用 array
and/or unpack
似乎没有什么不同(如您所见)
>>> array('H', [1])[0] + sys.maxint
9223372036854775808L
>>> unpack('H', '\x01\x00')[0] + sys.maxint
9223372036854775808L
要截断您的数字,您必须在每次增加变量大小时通过手动与适当的位掩码进行 ANDing 来模拟溢出。