问题

for ( i = 1; i <= 21; ++i )
{
*(&t01 + i) += (dword_424080[i % 6] >> 6) ^ (16 * dword_424080[(i - 1) % 6]);
(&t01 + i) = ((int)(unsigned __int8)(&t01 + i) >> 3) | (32 * *(&t01 + i));
}
以上是伪代码,我复现的有什么问题吗
for x in range(1,22):
for y in range(0,256):
t=y
t += ((key[x % 6] >> 6) ^ (16 * key[(x - 1) % 6]&0xFF))&0xFF
t = ((t >> 3) | (32 * t &0xFF))&0xFF
if t ==enc[x]:
print(chr(y))
break

思考

我先按 C/IDA 伪代码的类型提升和运算符优先级来对照你的 Python。这里最容易出错的是“什么时候截断到 8 位”,以及 & 0xFF 放的位置。

Thought for 28s

回答

主要问题在这一句:你加完之后没有先截断到 8 位

C 伪代码第二行里有:

c
((int)(unsigned __int8)*(&t01 + i) >> 3)

也就是说右移前取的是 unsigned __int8,所以 Python 里应该先:

python
t = (t + add) & 0xff

然后再做:

python
t = ((t >> 3) | (t << 5)) & 0xff

你现在写的是:

python
t += ... t = ((t >> 3) | (32 * t &0xFF))&0xFF

如果 t += ... 后超过 0xfft >> 3 用的是未截断的值,会错。

可以改成这样:

python
for x in range(1, 22): add = ((key[x % 6] >> 6) ^ (16 * key[(x - 1) % 6])) & 0xff for y in range(256): t = y t = (t + add) & 0xff t = ((t >> 3) | (t << 5)) & 0xff # ror8(t, 3) if t == enc[x]: print(chr(y), end="") break

另外还有两个点要确认:

  1. 你的 enc[x] 是否对齐。
    C 里 i = 1 时访问的是 *(&t01 + 1),也就是 t02。如果你的 enc[0]t01,那 enc[x] 没问题;如果 enc 只存了 21 个待比较字节,那应该用:

    python
    if t == enc[x - 1]:
  2. add 的截断位置。
    如果 *(&t01 + i)char / uint8_t,那么 += 后会存回 8 位,写成上面这样没问题。更贴近 C 的写法是:

    python
    add = (key[x % 6] >> 6) ^ (16 * key[(x - 1) % 6]) t = (y + add) & 0xff t = ((t >> 3) | (t << 5)) & 0xff

核心修正就是:& 0xff,再右移。

分享这个问答