Can';t在Python中重现工作的C位编码函数
我正在反向工程一个专有的网络协议,它在发射时生成一个(静态)一次性pad,然后使用它对发送/接收的每个数据包进行编码/解码。它在一系列复杂的异或、移位和乘法中使用一次性pad 在使用IDA遍历程序中的解码函数后,我生成了以下C代码。此功能完美地编码/解码数据:Can';t在Python中重现工作的C位编码函数,python,security,python-2.7,encoding,reverse-engineering,Python,Security,Python 2.7,Encoding,Reverse Engineering,我正在反向工程一个专有的网络协议,它在发射时生成一个(静态)一次性pad,然后使用它对发送/接收的每个数据包进行编码/解码。它在一系列复杂的异或、移位和乘法中使用一次性pad 在使用IDA遍历程序中的解码函数后,我生成了以下C代码。此功能完美地编码/解码数据: void encodeData(char *buf) { int i; size_t bufLen = *(unsigned short *)buf; unsigned long entropy = *((unsi
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];
}
我尝试过在各种变量上使用和不使用array()
或pack()
/unpack()
来强制它们成为按位操作的正确大小,但我肯定遗漏了一些东西,因为我无法让Python代码像C代码那样工作。有人知道我错过了什么吗
如果您可以在本地尝试此操作,以下是一次性pad生成函数:
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)
这是十六进制编码的原始(编码)和解码数据包
原件:20000108FCF3D71D98590000000000000000000000A992E0EE2525A5E5
解码:20000108FCF3D71D9859000000000000000000000000000000AE91E1EE25252525
解决方案
事实证明,我的问题与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])
因为在向地址添加2之前,buf
首先被强制转换为无符号长,这会向地址添加2个无符号长的大小,而不是2个字节(假设无符号长的大小为4个字节)
此外:
应该是
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
要匹配C,否则输出实际上并不基于缓冲区的内容。Python整数不会溢出-当它们超过sys.maxint(或
-sys.maxint-1
)时,会自动提升到任意精度
使用array
和/或unpack
似乎没有什么区别(正如您所发现的)
要截断数字,您必须在增加变量大小时手动使用适当的位掩码进行ANDing,以模拟溢出。解码的数据几乎与原始数据相同-是吗?是的,我应该在代码中添加更多注释。前24个字节是未编码的标头。我特别选择了这个数据包,因为“有效负载”减去报头的长度只有8个字节,并且我知道最后4个字节在解码时应该是0x25252525。首先,我会将所有计算屏蔽到正确的位长度,并确定是否需要逻辑或算术移位,并将其显式化。XORing是指ANDing吗?我也尝试过使用位掩码进行ANDing,但我会再试一次,确保捕获所有需要屏蔽的案例。@k0ss,是的,很抱歉,我会修复postpvoted,因为虽然我已经尝试过,但对于需要人为限制变量大小的人来说,这是一个很好的建议。好的,您已经了解了一些内容。我真不敢相信我错过了,我抓错了信息包的熵值部分!我甚至有一个010编辑器模板显示了它的位置,但显然忽略了它。问题是它仍然不起作用。这可能是endian ness的问题,我会在早上尝试解决。谢谢,解决了!我想这只是一些简单的编程错误,而不是编码/类型问题。我需要更加小心!我把最终的编码函数发布在主帖子中。
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
>>> sys.maxint
9223372036854775807
>>> sys.maxint + 1
9223372036854775808L
>>> array('H', [1])[0] + sys.maxint
9223372036854775808L
>>> unpack('H', '\x01\x00')[0] + sys.maxint
9223372036854775808L