我一直在努力理解来自IOLI crackme0x06挑战的一段非常奇怪的 x86 汇编代码。
语境
但首先,这里是上下文:我已经成功地应对了挑战,顺便说一下,它只需要:
一个连号
该数字在有符号整数的 32 位表示范围内,即介于(
INT32_MIN
) 和(INT32_MAX
) 之间(由于调用sscanf显然如果输入大于 则对输入执行整数饱和INT32_MAX
)一个环境变量——其名称应以“ LOL ”开头——在crackme进程环境中导出。
问题
现在,为了完整起见,我正试图掌握这个crackme的每一条指令的目的,但到目前为止,我正在努力理解函数中的以下代码(从##loop beginning
到##loop end
)sym.parell
实际上是如何有用的程序 :
0804851a <parell>:
804851a: push ebp
804851b: mov ebp,esp
804851d: sub esp,0x18
8048520: lea eax,[ebp-0x4]
8048523: mov DWORD PTR [esp+0x8],eax
8048527: mov DWORD PTR [esp+0x4],0x804873d
804852f: mov eax,DWORD PTR [ebp+0x8]
8048532: mov DWORD PTR [esp],eax
8048535: call 80483c8 <sscanf@plt>
804853a: mov eax,DWORD PTR [ebp+0xc]
804853d: mov DWORD PTR [esp+0x4],eax
8048541: mov eax,DWORD PTR [ebp-0x4]
8048544: mov DWORD PTR [esp],eax
8048547: call 80484b4 <dummy>
804854c: test eax,eax
804854e: je 8048586 <parell+0x6c>
8048550: mov DWORD PTR [ebp-0x8],0x0 # Initialization of i (see pseudo-code below)
8048557: cmp DWORD PTR [ebp-0x8],0x9 ## loop beginning
804855b: jg 8048586
804855d: mov eax,DWORD PTR [ebp-0x4] # Handling password's parity check
8048560: and eax,0x1
8048563: test eax,eax
8048565: jne 804857f <parell+0x65>
8048567: mov DWORD PTR [esp],0x8048740
804856e: call 80483b8 <printf@plt>
8048573: mov DWORD PTR [esp],0x0
804857a: call 80483e8 <exit@plt>
804857f: lea eax,[ebp-0x8]
8048582: inc DWORD PTR [eax]
8048584: jmp 8048557 <parell+0x3d> ## loop end
8048586: leave
8048587: ret
它似乎等效于以下伪代码:
for (int i = 0; i <= 9; ++i)
if LSB (password) is 0 // ie if password is an even number
printf("Password OK!\n");
exit(0);
但问题是,从 0 到 9 的循环不会对数字的奇偶校验做任何相关的事情......
而且就密码测试而言,sym.parell
函数中发生的计算永远不会受到这样的循环的影响!
几个小时以来,我一直在挠头,但我真的无法弄清楚它的确切用途。
尚未初学者这一挑战(由它的第一个办法动手实验中的RPISEC学术课程),我还以为这只是一些无聊的混淆/垃圾代码的意思来偏转攻击,注意技术,它显然不是这样。
这一系列的挑战只是为了帮助新手在该领域打下扎实的基础。
我错了吗 ?
那么,说真的,这个程序中上述代码的目的是什么?