Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 带循环的反编译辅助_C_Assembly_X86_Decompiling - Fatal编程技术网

C 带循环的反编译辅助

C 带循环的反编译辅助,c,assembly,x86,decompiling,C,Assembly,X86,Decompiling,从2014年开始,我正在从一个旧的CTF中撤销一些x86,并试图理解下面的代码(它已被大幅缩短)。我相信它是通过字符串x执行某种while或for循环,其中x是字符串的长度 一些基本信息: 英特尔语法 给出了功能原型: int main(char*) 我的主要困惑在于.L3和.L2的末尾: 我相信.L3的结尾将寄存器算术存储在[ebp-12]中,然后增加[ebp-8]的值(我相信这是指向char*arg副本的指针) 我对它的松散转换(忽略了大部分.L3)在c中如下所示: int main

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

一些基本信息:

  • 英特尔语法
  • 给出了功能原型:
    • int main(char*)
我的主要困惑在于.L3和.L2的末尾:

我相信.L3的结尾将寄存器算术存储在[ebp-12]中,然后增加[ebp-8]的值(我相信这是指向char*arg副本的指针)

我对它的松散转换(忽略了大部分.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;
}

我相信这三行是去引用指针地址,零扩展位,然后符号扩展al字节。就“c”代码而言,我相信它只是用来索引数组中的每个特定字符,特别是用来使用其十进制值进行算术运算。

是的,它似乎在对字符串中的每个字符做“某些事情”。它可以计算一个散列码或CRC,或者无限多个可能的事物中的任何一个。如果不知道“讨厌的数学”是什么,就不可能说出来

更正确的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,这是函数返回的值


至少在我看来是这样的。但是,这个函数做什么呢。如果我的读数是正确的,那么函数实际上没有做任何有用的事情。除非“恼人的数学”包含对外部作用域中某些变量的引用。

也有一个StackExchange站点,用于此类内容,名为.post。不过有点希望这能得到更快的响应。在英特尔语法中,
movzx-eax,字节PTR[eax]
加载并零将
eax
指向的字节扩展到寄存器
eax
,替换指针的值。@iwillnotexistidoxist:是的,这是正确的。因此,如果在该指令之后,AL寄存器为0,则所有EAX都为0。如果al为0,则下一条指令
测试al,al
将设置Z标志。仅当未设置Z标志时才进行跳转。因此,当函数退出时,AL为0,因此EAX为0。@JimMischel在执行
movzx-EAX,BYTE PTR[EAX]
命令后,何时不设置Z标志?当它指向一个空字节时,它会将空字节与空字节进行比较,并使用下面的
test al,al
指令?@Kaiser17:你的问题是什么?我的观点是,正如我在上面解释的那样,函数总是返回0。如果您不同意,请解释返回值可以是什么。@Kaiser17 Jim是对的。是一种指令,当寄存器分别设置奇数位、符号位或未设置位时,该指令对两个寄存器进行and运算,并根据结果设置P、S和Z寄存器标志。当您将一个值与它自身合并时,它是不变的(
(x&x)=x
),因此
test
指令有效地单独检查
x
的奇偶校验、符号和零。只有当
al
包含NUL字节时,“Z”才会出现。
int main(char* arg)
{
    char* p = arg;
    int loc1 = 0;
    for (; *p != 0; p++)
    {
        loc1 = do_something_with(*p);
    }
    return 0;
}
movzx   eax, BYTE PTR [eax]         
test    al, al                      
jne     .L3