现在我遇到了问题。我的项目在组装级别工作。所以我需要汇编级编程,但项目规模太大,无法只在汇编级进行工作。由于这个问题,我决定从gcc制作的c源文件中获取六进制代码。但是怎么做呢如何使用gcc获取特定函数的HEXCODES
我有个主意,
int function_name(){
int a=1;
return a;
}
write(fd, (char *)function_name, sizeof(function_name))
这样做之后,我会得到函数名的六进制代码。但这不是解决这个问题的好方法,当我需要很多函数作为目标时,它会让我需要处理很多文件。
有其他好办法解决这个问题吗?我认为理想的解决方案只需要函数名(如果需要,还需要输出文件名),并且可以在命令行上工作。理想的解决方案是我认为不可能的吗?
此外,我认为编译器的优化选项已关闭所以我会从函数名得到六进制代码是'\x55\x8B\xEC\x83\xEC\x04\xC7\x45\xFC\x01\x0\x00\x00\x8B\x45\xFC \x58\x5\x5D\xC3'function_name的程序集代码如下。
PUSH EBP
MOV EBP, ESP
SUB ESP, 4
MOV DWORD PTR[EBP-4], 1
MOV EAX, DWORD PTR[EBP-4]
MOV ESP, EBP
POP EBP
RETN
gcc从每个源文件中生成一个汇编文件,作为编译工具链的一部分。该文件通常是临时的,因此会立即删除。如果您想将其保存为myfile.s
,可以使用以下命令:
gcc -S -o myfile.s myfile.c
尝试
objdump-D-Mintel您的文件.o
转储将看起来像(由免费pascal编译器生成的.O,但gcc将基本相同)
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 8d 64 24 ec lea esp,[esp-0x14]
7: 53 push ebx
8: 89 45 fc mov DWORD PTR [ebp-0x4],eax
b: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0
12: 31 c0 xor eax,eax
14: 68 00 00 00 00 push 0x0
19: 55 push ebp
1a: 68 00 00 00 00 push 0x0
1f: 64 ff 30 push DWORD PTR fs:[eax]
22: 64 89 20 mov DWORD PTR fs:[eax],esp
25: c7 45 f8 00 00 00 00 mov DWORD PTR [ebp-0x8],0x0
2c: 8b 45 fc mov eax,DWORD PTR [ebp-0x4]
2f: 8b 50 04 mov edx,DWORD PTR [eax+0x4]
代码仍然是可重定位的,因此引用将为零字节。
为了解决这个问题,您需要objdump二进制文件(.exe)而不是.o,但这样的输出通常很大,并且会使查找特定位置变得更加困难。
我猜您在Linux上,因为您使用的是gcc
你可以运行
gcc -Wall -O -c myfile.c
从源C文件myfile.c
中获取对象文件myfile.o
;该对象文件在ELF中,因此包含明显的二进制代码和重新定位顺序。您可以解析ELF对象文件(例如,使用objdump(1)或readelf
等命令,或者通过libelf
或libbfd
等库)
或者,只使用具有位置无关代码的ELF共享对象,并使用dlopen(3)。参见程序库如何使用
请注意,并不是每个源级C函数都对应于对象文件中的某个函数(例如ELF符号)(例如,因为static
函数-它们的名称可能会被遗忘或剥离,或者因为inline
函数-它们没有自己的机器代码,它已经内联在调用方中)。假设一个优化编译器(例如gcc -O2
)。
请记住,一般来说,反编译是一项不可能完成的任务。要意识到这个悬而未决的问题。
也可以看看这个问题和关于libopcode
的答案
BTW,
write(fd, (char *)function_name, sizeof(function_name))
不会编译(不能使用sizeof
some函数)。也许你会做
write(fd, (char*)function_name, sizeof(char*))
它会写一些地址,这可能没有多大意义(请注意ASLR)。
也许你想要dladdr(3)?您可能需要使用链接时传递的-rdynamic
选项来编译程序。