用循环反编译辅助

时间:2015-04-08 02:16:46

标签: c assembly x86 decompiling

我正在从2014年的旧CTF中撤销一些x86,并试图理解下面的代码(它已经大大缩短了)。我相信它正在执行某种while或for循环遍历字符串x次,其中x是字符串的长度。

一些基本信息:

  • 英特尔语法
  • 功能原型给出:
    • int main(char *);

我的主要困惑在于.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,特别是使用其十进制值进行算术。

1 个答案:

答案 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;包括对外部范围内的一些变量的引用。