我反向设计一种专有网络协议,该协议在启动时生成(静态)一次性缓冲区,然后使用它来编码/解码它发送/接收的每个数据包。它在一系列复杂的XOR,移位和乘法中使用一次性焊盘。
在使用IDA遍历程序中的解码功能后,我生成了以下C代码。此功能可以完美地对数据进行编码/解码:
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修正来进行编码/解码,因此我需要将此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()
,以强制它们成为按位操作的正确大小,但我必须是遗漏了一些东西,因为我无法像C代码一样使用Python代码。有谁知道我错过了什么?
如果它可以帮助你在本地尝试这个,这里是一次性垫生成功能:
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)
感谢大家的帮助!
答案 0 :(得分:2)
这一行C:
unsigned long entropy = *((unsigned long *)buf + 2);
应转换为
entropy = unpack('I', buf[8:12])
因为buf
在向地址添加2之前首先强制转换为无符号长整数,这会向其添加2个无符号长整数,而不是2个字节(假设无符号长整数为4个字节)。 / p>
此外:
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
应该是
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
匹配C,否则输出实际上不是基于缓冲区的内容。
答案 1 :(得分:1)
Python整数不会溢出 - 当超过sys.maxint
(或-sys.maxint-1
)时,它们会自动提升为任意精度。
>>> sys.maxint
9223372036854775807
>>> sys.maxint + 1
9223372036854775808L
使用array
和/或unpack
似乎没有任何区别(正如您所发现的那样)
>>> array('H', [1])[0] + sys.maxint
9223372036854775808L
>>> unpack('H', '\x01\x00')[0] + sys.maxint
9223372036854775808L
要截断您的数字,只要您增加变量的大小,就必须使用适当的位掩码手动进行AND运算来模拟溢出。