无法从反编译的简单应用

时间:2017-08-27 21:22:33

标签: gcc x86 nasm reverse-engineering disassembly

我已经开始学习NASM汇编程序&回覆。我得到的第一个问题是下一个问题(简称):

我无法使用 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)。下一步是:

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

  • 来自.SECTION行的 align = N 执行/不执行字样
  • 来自全球声明的
  • : function
  • default rel

修复msg: dq Unnamed_4_0。我曾经想过,使用objconv之后,这部分会受到损害/破坏。

所以,我改变了:

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方法构建可执行文件,该方法充当原始可执行文件。

1 个答案:

答案 0 :(得分:1)

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

如果您已撰写char msg[] = "Hello World!";,则msg处的字节将为文字字符串,而main会将printf的指针传递给mov edi, msg(即mov r32,imm32)。

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

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

顺便说一下,我建议至少使用gcc -Og-O1进行编译。在每个C语句之后没有将所有内容存储/重新加载到堆栈中时(通过调试器更改任何变量),读取asm将会容易得多。有关更多提示,另请参阅How to remove "noise" from GCC/clang assembly output?