这个汇编 x86 代码的反编译 (C) 代码构造是什么?

bsd*_*anm 2 c x86 assembly decompiling reverse-engineering

此代码将字符串的每个字符(位于ebp+arg_0)与不同的常量(ASCII 字符)进行比较,例如“I”、“o”和“S”。我猜,基于其他代码部分,这段代码最初是用 C 编写的。

集会

这个比较代码部分看起来效率很低。我的问题是,你认为这段代码在 C 中看起来如何?最初使用什么代码结构?到目前为止我的想法

  • 这不是for 循环。因为我没有看到任何向上跳跃和停止条件。

  • 这不是一个 while/case/switch 代码构造

  • 我最好的猜测是,这是很多连续的 if/else 语句。你能帮我吗?

是的,这是挑战的一部分,我已经有了标志/解决方案,不用担心。只是想更好地理解代码。

tka*_*usl 5

这不是 for 循环。因为我没有看到任何向上跳跃和停止条件。

正确的。

这不是 while/case/switch 代码构造

不可能,它比较了数组的不同索引。

我最好的猜测是,这是很多连续的 if/else。你能帮我吗?

看起来可能是这样的代码:

void f(const char* arg_0) {
    if(arg_0[4] == 'I' && arg_0[5] == 'o' && arg_0[6] == 'S') {
        printf("Gratz man :)");
        exit(0); //noreturn, hence your control flow ends here in the assembly
    }
    puts("Wrong password"); // Or `printf("Wrong password\n");` which gets optimized to `puts`
    // leave, retn
}
Run Code Online (Sandbox Code Playgroud)

这是 gcc 在没有优化的情况下编译它的方式

.LC0:
        .string "Gratz man :)"
.LC1:
        .string "Wrong password"
f(char const*):
        push    ebp
        mov     ebp, esp
        sub     esp, 8
        mov     eax, DWORD PTR [ebp+8]
        add     eax, 4
        movzx   eax, BYTE PTR [eax]
        cmp     al, 73
        jne     .L2
        mov     eax, DWORD PTR [ebp+8]
        add     eax, 5
        movzx   eax, BYTE PTR [eax]
        cmp     al, 111
        jne     .L2
        mov     eax, DWORD PTR [ebp+8]
        add     eax, 6
        movzx   eax, BYTE PTR [eax]
        cmp     al, 83
        jne     .L2
        sub     esp, 12
        push    OFFSET FLAT:.LC0
        call    printf
        add     esp, 16
        sub     esp, 12
        push    0
        call    exit
.L2:
        sub     esp, 12
        push    OFFSET FLAT:.LC1
        call    puts
        add     esp, 16
        nop
        leave
        ret
Run Code Online (Sandbox Code Playgroud)

看起来与您的反汇编代码非常相似。

这个比较代码部分看起来效率很低

看起来它是在没有优化的情况下编译的。启用优化后,gcc 将代码编译为

.LC0:
        .string "Gratz man :)"
.LC1:
        .string "Wrong password"
f(char const*):
        sub     esp, 12
        mov     eax, DWORD PTR [esp+16]
        cmp     BYTE PTR [eax+4], 73
        jne     .L2
        cmp     BYTE PTR [eax+5], 111
        je      .L5
.L2:
        mov     DWORD PTR [esp+16], OFFSET FLAT:.LC1
        add     esp, 12
        jmp     puts
.L5:
        cmp     BYTE PTR [eax+6], 83
        jne     .L2
        sub     esp, 12
        push    OFFSET FLAT:.LC0
        call    printf
        mov     DWORD PTR [esp], 0
        call    exit
Run Code Online (Sandbox Code Playgroud)

不知道为什么 gcc 决定跳下来并再次备份而不是直线jnes。此外, theret不见了,你printf得到了尾调用优化,即 a jmp printfi 而不是 acall printf后跟 a ret