下面的代码行位于j
循环中,其中ansString
递增,000\Qg$M!*P000\gQYA+ h000\M|$skd 000\Qo}plsd000\
是一串ASCII字符,例如ansString[j] = ((char)(paramString[j] >> j % 8 ^ paramString[j]));
。
paramString
我在弄清楚如何进行XOR时遇到了麻烦,而其他所有运算符都被颠倒了以找到docker pull avnerner/fontello_server
docker run -it -p 3000:3000 -d avnerner/fontello_server
。感谢任何帮助。
答案 0 :(得分:6)
右移(>>)和模(%)是不可逆的操作:
在正确的移位的情况下,下溢位会丢失,因此反转a >> b
会给您带来2 ^ b个不同的可能结果。
对于模运算符,在x % 8 = y
中,如果x的最大长度为8位,则有32种可能的值。 (那就是每个x * 8 + y
都适合8位)
异或运算是唯一的可逆运算。如果有
a ^ b = c
然后
c ^ b = a
因此,对于多个输入,您将具有相同的输出。例如,让我们假设j = 0
j % 8 = 0 % 8 = 0
paramString[j] >> (j % 8) = paramString[0] >> 0 = paramString[0]
paramString[0] ^ paramString[j] = paramString[0] ^ paramString[0] = 0
这意味着对于您的第一个字符和随后的第8个字符(这是其索引j为8的倍数的每个字符,因此j % 8 = 0
)的结果将为0,无论原始字符是(如您可以在示例输出字符串中看到)。
这就是为什么即使对所有可能的输入都进行暴力破解(总共256 * n个可能的输入字符串,即n个字符串长度),您也无法确定原始输入是什么,因为许多输入都会产生相同的输出。
答案 1 :(得分:1)
如果j
是运行索引,您将知道每次迭代中的偏移量。这样,您就可以找到前缀并解密该字符串。
例如对于j = 2
(0..7是位位置,两位数字是XORed位,x为0):
Original: 0 1 2 3 4 5 6 7
Shifted: x x 0 1 2 3 4 5
Encrypted: 0 1 02 13 24 35 46 57
如您所见,前两位数字保持不变。然后用这两位数字来加密接下来的两位,依此类推。
因此,要用j = 2进行解密,您会发现一个未加密的2位数字前缀。可用于解密接下来的2位(02和13):
Encrypted: 0 1 02 13 24 35 46 57
Shift-Mask: x x 0 1 x x x x
Temp1: 0 1 2 3 24 35 46 57
现在我们知道前4位数字,还有接下来2位的解密位:
Temp1: 0 1 2 3 24 35 46 57
Shift-Mask: x x x x 2 3 x x
Temp2: 0 1 2 3 4 5 46 57
再次:
Temp2: 0 1 2 3 4 5 46 57
Shift-Mask3: x x x x x x 4 5
Decrypted3: 0 1 2 3 4 5 6 7 <- Original string
基于此思想,您可以构建解密算法