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

Get function hex-codes from GCC

现在遇到问题了。我的项目在汇编级别工作。 所以我需要汇编级编程,但项目规模太大,无法仅在汇编级进行工作。由于这个问题,我决定从 gcc 制作的 c 源文件中获取十六进制代码。但是怎么办? 如何使用 gcc 获取某些函数的 HEXCODES

我有个想法,

int function_name(){
    int a=1;
    return a;
}
write(fd, (char *)function_name, sizeof(function_name))

这样做之后我会得到 function_name 的十六进制代码。 但这不是解决这个问题的好方法,当我需要很多功能作为目标时,它会让我需要处理很多文件。

请问还有其他好的方法可以解决这个问题吗?我认为理想的解决方案只需要函数名(和输出文件名,如果需要)并在命令行上工作。我认为不可能的理想解决方案?

我还假设编译器的优化选项已关闭 所以我会从 function_name 得到 hexcodes'\x55\x8B\xEC\x83\xEC\x04\xC7\x45\xFC\x01\x00\x00\x00\x8B\x45\xFC\x8B\xE5\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

我猜你在 Linux,因为你正在使用 gcc

你可能 运行

 gcc -Wall -O -c myfile.c

从源 C 文件 myfile.c 获取目标文件 myfile.o ;该目标文件在 ELF so contains notably binary code and relocation orders. You could parse that ELF object file (e.g. with commands like objdump(1)readelf 中或通过某些库,如 libelflibbfd)

或者仅在具有 position independent code and use dlopen(3). See program library howto

的 ELF 共享对象上工作

请注意,并非每个源代码级 C 函数都对应于目标文件中的某个函数(例如 ELF 符号)(例如,由于 static 函数 - 它们的名称可能会被遗忘或 stripped, or because of inline functions - they don't have their own machine code, it has been inlined in the caller). Assume an optimizing compiler (例如 gcc -O2).

记住 decompilation is an impossible task in general. Be aware of the halting problem which is undecidable.

另请参阅 this question 以及有关 libopcode

的答案

顺便说一句,

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

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

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

这将写入一些地址,这可能意义不大(请注意 ASLR)。

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

尝试

objdump -D -Mintel yourfile.o

转储看起来像(.O 由 free pascal 编译器生成,但 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,但这样的输出通常很大,并且会使查找特定位置变得更加困难。