无法从反编译的简单应用程序恢复原始行为

Can't restore the original behavior from the decompiled simple app

我已经开始学习 NASM 汇编程序和 RE。我遇到的第一个问题是下一个(简而言之):

我无法使用 objconv 实用程序.

恢复反编译的程序

我的简单应用程序:

#include <stdio.h>

char* msg = "Hello World!";

int main(void) {
    printf("%s\r\n", msg);
    return 0;
}

1).我所做的第一步是:

gcc -fno-asynchronous-unwind-tables -s -c -o 1.o 1.c

标志:fno-asynchronous-unwind-tables 用于不在输出目标文件中生成不必要的部分。

2).然后,我以这种方式使用 objconv 实用程序:

objconv -fnasm 1.o

NASM汇编程序生成汇编代码,我有下一个:

; Disassembly of file: 1.o
; Sun Aug 27 23:56:53 2017
; Mode: 64 bits
; Syntax: YASM/NASM
; Instruction set: 8086, x64

default rel

global main: function
global msg

extern printf                                           ; near


SECTION .text   align=1 execute                         ; section number 1, code

main:   ; Function begin
        push    rbp                                     ; 0000 _ 55
        mov     rbp, rsp                                ; 0001 _ 48: 89. E5
        mov     rax, qword [rel msg]                    ; 0004 _ 48: 8B. 05, 00000000(rel)
        mov     rsi, rax                                ; 000B _ 48: 89. C6
        mov     edi, ?_001                              ; 000E _ BF, 00000000(d)
        mov     eax, 0                                  ; 0013 _ B8, 00000000
        call    printf                                  ; 0018 _ E8, 00000000(rel)
        mov     eax, 0                                  ; 001D _ B8, 00000000
        pop     rbp                                     ; 0022 _ 5D
        ret                                             ; 0023 _ C3
; main End of function


SECTION .data   align=8 noexecute                       ; section number 2, data

msg:                                                    ; qword
        dq Unnamed_4_0                                  ; 0000 _ 0000000000000000 (d)


SECTION .bss    align=1 noexecute                       ; section number 3, bss


SECTION .rodata align=1 noexecute                       ; section number 4, const

        db 48H, 65H, 6CH, 6CH, 6FH, 20H, 57H, 6FH       ; 0000 _ Hello Wo
        db 72H, 6CH, 64H, 21H, 00H                      ; 0008 _ rld!.

?_001:                                                  ; byte
        db 25H, 73H, 0DH, 0AH, 00H                      ; 000D _ %s...

3).下一步是:

删除不需要的部分,例如:

正在修复 msg: dq Unnamed_4_0。我想过,在使用 objconv.

之后,这部分相当 compromised/broken

所以,我改变了:

dq Unnamed_4_0

给:

db "Hello World",10

尽管有以下部分:.rodata(我在想,我的问题正是错误地使用了输出字符串...)。

4).然后我在 shell:

中使用了下一个命令
nasm -f elf64 1.asm
gcc 1.o

当我在 gcc 之后启动 a.out 文件时,我遇到了下一个错误:

user@:~/Desktop/tmp$ ./a.out
Segmentation fault (core dumped)

这就是我未能从反汇编程序恢复原始行为的原因。原程序编译通过:

gcc -std=c99 -o 1 1.c

它的源代码在我的问题开头发布了。我想要实现的目标很简单:使用 objconv -> nasm 方法构建可执行文件,该方法充当原始可执行文件。

您写了 char* msg = "Hello World!";,因此您有一个指向存储在 read/write .data 部分中的字符串文字的指针。那就是 dq Unnamed_4_0.

如果你写了 char msg[] = "Hello World!";msg 处的字节将是文字字符串,而 main 将使用 [=17= 传递指向 printf 的指针](即 mov r32,imm32)。

您更改了 asm,因此 msg: 处的字节是字符串数据而不是指针。但是您的 main 仍然将存储在 msg 的前 8 个字节作为 指针 (作为 const char *fmt arg)传递给 printf .

printf 试图将那些 ASCII 字节作为指向格式字符串的指针取消引用时,它会出现段错误。 (请记住,在 C 中,字符串是通过引用传递的。)


顺便说一句,我建议至少使用 gcc -Og-O1 进行编译。如果不是 storing/reloading 在每个 C 语句之后将所有内容都放入堆栈,那么阅读 asm 会容易得多(让您可以使用调试器更改任何变量)。另请参阅 了解更多提示。