我正在从2014年的旧CTF中撤销一些x86,并试图理解下面的代码(它已经大大缩短了)。我相信它正在执行某种while或for循环遍历字符串x次,其中x是字符串的长度。
一些基本信息:
我的主要困惑在于.L3和.L2:
的结尾我相信.L3的结尾是在[ebp-12]中存储寄存器算法,然后增加[ebp-8]的值(我相信这是指向char * arg副本的指针)
.L1
push ebp
mov ebp, esp
push ebx
sub esp, 20
mov DWORD PTR [ebp-12], 0
mov eax, DWORD PTR [ebp+8]
mov DWORD PTR [ebp-8], eax
jmp .L2
.L3
// Bunch of annoying arithmetic w/ registers
mov DWORD PTR [ebp-12], eax
add DWORD PTR [ebp-8], 1
.L2:
mov eax, DWORD PTR [ebp-8]
movzx eax, BYTE PTR [eax]
test al, al
jne .L3
add esp, 20
pop ebx
pop ebp
ret
我对此的松散转换(忽略.L3的大部分内容)如下c:
int main(char* arg)
{
int loc1 = 0;
char* str = arg;
for(i = 0; str[i] != '\0'; i++) { // <=== Pretty Sure
// .L3 Stuff w/ Assignment to loc1 // This is incorrect
}
return loc1;
}
有人愿意解释[ebp-8]的增量,前两行.L2,并确认/否认在返回期间我调用的eax或loc1的值将基于结束返回of .L2?
代码中唯一有趣的部分与这三行重复出现在.L3中反复出现:
mov eax, DWORD PTR [ebp-8]
movzx eax, BYTE PTR [eax]
movsx eax, al
我相信这三行是取消引用指针地址,零扩展位然后签署扩展al字节。就“c”代码而言,我认为它只是用于索引数组中的每个特定char,特别是使用其十进制值进行算术。
答案 0 :(得分:1)
是的,似乎正在做什么&#34;&#34;每个字符都在一个字符串中。它可以是计算哈希码或CRC,或者是无数个可能的东西中的任何一个。不知道&#34;烦人的数学&#34;是的,这是不可能的。
更正确的C版本代码是:
int main(char* arg)
{
char* p = arg;
int loc1 = 0;
for (; *p != 0; p++)
{
loc1 = do_something_with(*p);
}
return 0;
}
正如您所述,它不会返回loc1
。终止条件如下:
movzx eax, BYTE PTR [eax]
test al, al
jne .L3
第一条指令零扩展EAX。因此,如果AL寄存器为零,那么EAX也是如此。如果没有进行跳转,那么EAX为0,这是该函数返回的值。
至少,这就是它对我的看法。但是,这个功能做了什么。如果我的阅读是正确的,那么该功能实际上并没有做任何有用的事情。除非那个烦恼的数学&#34;包括对外部范围内的一些变量的引用。