有没有办法以编程方式从 x86 架构上的二进制可执行文件中读取给定数量的指令?
如果我有一个简单的 C 程序 hello.c
的二进制文件:
#include <stdio.h>
int main(){
printf("Hello world\n");
return 0;
}
使用 gcc
编译后,反汇编函数 main
如下所示:
000000000000063a <main>:
63a: 55 push %rbp
63b: 48 89 e5 mov %rsp,%rbp
63e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6e4 <_IO_stdin_used+0x4>
645: e8 c6 fe ff ff callq 510 <puts@plt>
64a: b8 00 00 00 00 mov $0x0,%eax
64f: 5d pop %rbp
650: c3 retq
651: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
658: 00 00 00
65b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
在 C 中是否有一种简单的方法来读取例如前三个指令(表示字节 55, 48, 89, e5, 48, 8d, 3d, 9f, 00, 00, 00
)来自 main
?不能保证该函数看起来像这样 - 第一条指令可能具有所有不同的操作码和大小。
最佳答案
这通过获取函数的地址并转换为 unsigned char
的指针来打印 main
函数的前 10 个字节,以十六进制打印。
这个小片段不算指令。为此,您需要一个指令大小表(不是很困难,只是很乏味,除非您发现该表已经完成,What is the size of each asm instruction?)才能在给定第一个字节的情况下预测每条指令的大小。
(当然,除非你的目标处理器有固定的指令大小,这使得问题很容易解决)
调试器也必须对操作数进行解码,但在某些情况下,例如步进或跟踪,我怀疑他们有一个方便的表来计算下一个断点地址。
#include <stdio.h>
int main(){
printf("Hello world\n");
const unsigned char *start = (const char *)&main;
int i;
for (i=0;i<10;i++)
{
printf("%x\n",start[i]);
}
return 0;
}
输出:
Hello world
55
89
e5
83
e4
f0
83
ec
20
e8
似乎与反汇编相匹配:)
00401630 <_main>:
401630: 55 push %ebp
401631: 89 e5 mov %esp,%ebp
401633: 83 e4 f0 and $0xfffffff0,%esp
401636: 83 ec 20 sub $0x20,%esp
401639: e8 a2 01 00 00 call 4017e0 <___main>
关于c - 如何通过指令读取二进制可执行文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49153556/