c-从GCC中获取函数十六进制代码



现在我遇到了问题。我的项目在组装级别工作。所以我需要汇编级编程,但项目规模太大,无法只在汇编级进行工作。由于这个问题,我决定从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等命令,或者通过libelflibbfd等库)

或者,只使用具有位置无关代码的ELF共享对象,并使用dlopen(3)。参见程序库如何使用

请注意,并不是每个源级C函数都对应于对象文件中的某个函数(例如ELF符号)(例如,因为static函数-它们的名称可能会被遗忘或剥离,或者因为inline函数-它们没有自己的机器代码,它已经内联在调用方中)。假设一个优化编译器(例如gcc -O2)。

请记住,一般来说,反编译是一项不可能完成的任务。要意识到这个悬而未决的问题。

也可以看看这个问题和关于libopcode 的答案

BTW,

write(fd, (char *)function_name, sizeof(function_name))

不会编译(不能使用sizeofsome函数)。也许你会做

write(fd, (char*)function_name, sizeof(char*))

它会写一些地址,这可能没有多大意义(请注意ASLR)。

也许你想要dladdr(3)?您可能需要使用链接时传递的-rdynamic选项来编译程序。

最新更新