无法从反编译的简单应用程序恢复原始行为
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).下一步是:
删除不需要的部分,例如:
- align=N 和 execute/noexecute 字来自
.SECTION
行
: function
来自 global 声明
default rel
行
正在修复 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 会容易得多(让您可以使用调试器更改任何变量)。另请参阅 了解更多提示。
我已经开始学习 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).下一步是:
删除不需要的部分,例如:
- align=N 和 execute/noexecute 字来自
.SECTION
行 : function
来自 global 声明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
方法构建可执行文件,该方法充当原始可执行文件。
您写了 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 会容易得多(让您可以使用调试器更改任何变量)。另请参阅