2017-08-27 106 views
1

我已经开始学习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)。下一步是在:

卸下不必要的部分,如:

  • 对齐= N.SECTION线从全球声明
  • 执行/ NOEXECUTE词语
  • : function
  • the default rel line

修复msg: dq Unnamed_4_0。我曾经想过,在使用objconv之后,这部分是相当妥协/损坏的。

所以,我已经改变:

dq Unnamed_4_0 

到:

db "Hello World",10 

尽管对具有部分:.rodata(我在想,我的问题是究竟有不正确的使用字符串输出...)。 4)。然后我用在外壳的下一个命令:

nasm -f elf64 1.asm 
gcc 1.o 

时,我发起的gcc后a.out文件,我已经得到了一个错误:

[email protected]:~/Desktop/tmp$ ./a.out 
Segmentation fault (core dumped) 

这是怎么了我失败了恢复反汇编程序的原始行为。原始程序编译通过:

gcc -std=c99 -o 1 1.c 

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

+0

你拆卸,不反编译。这通常是不安全的,因为NASM语法不能表示可能例如不同的指令编码选择。在PLT中留下必要的填充。如果你只是保留拆解的'main',那应该没问题。可能你破坏了某些东西,你应该使用'gdb ./a.out'来找出结果。 (见ASM提示GDB在[x86的标签维基(http://stackoverflow.com/tags/x86/info)的底部) –

+0

感谢好与建设性的答案@PeterCordes – Neverlands

回答

1

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

如果写char msg[] = "Hello World!";,在msg字节将是文字串,并且将main指针传递给printfmov edi, msg(即mov r32,imm32)。

你改变了ASM所以在msg:字节字符串是数据,而不是一个指针。但你的main仍通过储存在msgprintf作为指针(作为const char *fmt ARG)的前8个字节。

printf当试图取消引用那些ASCII字节的指针格式字符串,它出现segfaults。 (请记住,在C,字符串通过引用传递。)


顺便说一句,我建议用gcc -Og-O1至少编译。在每次C语句之后,如果没有将所有东西存储/重载到堆栈(让您使用调试器更改任何变量),读取asm会更容易。有关更多提示,另请参阅How to remove "noise" from GCC/clang assembly output?