这个异或有什么作用?

逆向工程 拆卸 x86 免疫调试器
2021-07-05 08:10:56

我试图准确了解以下循环中发生的情况。我已经评论了我认为正在发生的事情。除了在 ImmunityDebugger 中运行代码并观察行为之外,我通过谷歌搜索每个操作代码并试图理解它的含义,得出了这些结论。

我不确定这是否是最有效的研究方式。请让我知道是否有其他最佳实践来发现相对较少的代码选择的功能。

内存地址会发生什么00401053在这种情况下 XOR 会做什么?

0040104B  |. 31C9           XOR ECX,ECX
0040104D  |> 8A81 58214000  /MOV AL,BYTE PTR DS:[ECX+402158] ;Move first byte of [ECX+402158] into AL
00401053  |. 34 7D          |XOR AL,7D                       ;Not sure what this means
00401055  |. 3A81 40214000  |CMP AL,BYTE PTR DS:[ECX+402140] ;Compare AL with the first byte of [ECX+402140]
0040105B     75 1E          |JNZ SHORT i_am_hap.0040107B     ;Jump out of loop if not zero << What does that mean?
0040105D  |. 41             |INC ECX                         ;increment ECX value
0040105E  |. 83F9 18        |CMP ECX,18                      ;loop runs 18 times
00401061    ^7C EA          \JL SHORT i_am_hap.0040104D      ;If above CMP fails restart the loop
2个回答

环形

首先,当你说“循环运行18次”时,实际上是0x18次(六),所以16+8=24次。

异或

XOR operand1, operand2

只不过是一个逻辑异或 (11=> 0, 10=> 1, 01=> 1, 00=> 0)。

这将是 AL = AL XOR 01111101。

一个24 字节的字符串可能存储在 0x402158并与 0x7d 进行异或。我说 24 字节是因为这段代码循环了 24 次,ECX 每次递增,异或字节位于 ECX+0x402158。

这意味着从 0x402158 到 0x402158 + 0x18 (0x402158 -> 0x402170) 的每个字节都将与 0x7d 进行异或。

JNZ

关于你的下一个问题:

Jump out of loop if not zero << What does that mean?

JNZ 操作数遵循比较 (CMP)。在引擎盖下,CMP 只不过是一种减法。如果减法结果为零,则零标志 (ZF) 设置为 1。JNZ 操作数(若非零则跳转)仅在 ZF 设置为 0 时跳转。

结论

话虽如此,我相信你可以弄清楚这里发生了什么。有一个字符串在字符后与 0x7d 字符进行异或运算。每次对字符进行异或运算时,都会将其与位于 0x402140 处的另一个字符串进行比较。如果 XORed 字符与此字符串中的字符不同,则 JNZ 跳转。伪 C 代码如下所示:

感谢 Guntram Blohm 评论编辑代码

char chr;
int i;
char check[]="\x2a\x18\x11\x11\x5d\x19\x12\x13\x18\x5d\x30\x14\x0e\x09\x18\x0f\x5d\x3‌​5\x1c\x1e\x16\x13\x19\x12"
for (i=0; i<24; i++) {
    argv[1][i] ^= '\x7d';
    if (argv[1][i] != check[i]) {
        break;
    }
}

该代码段在功能上等同于这个 powershell 脚本

将粘贴复制到 file.ps1 并像这样运行它

powershell -f file.ps1 "<猜测的密码>"

$402140=$args[0].tochararray();
$402158=@(13,28,14,14,10,18,15,25,93,20,14,93,14,24,30,15,24,9,93,31,28,31,4)
$ecx=0;
do{$al=(($402158[$ecx]) -bxor 0x7d);
if($al-ne$402140[$ecx]) {"bad pass";Throw;}
$ecx++;
}while($ecx-lt$402158.length)

$p="";13,28,14,14,10,18,15,25,93,20,14,93,14,24,30,15,24,9,93,31,28,31, 4|% {$p+="{0}" -f [char]($_-bxor 0x7d)};$p