考虑以下
main.c
:
#include <stdio.h>
const char greeting[] = "hello world";
int main() {
printf("%s!\n", greeting);
return 0;
}
我在 Ubuntu 中编译了这个:
gcc -g main.c -o main.exe
我想检索名为
greeting
的变量的值;考虑到它是const
,它不会改变,所以应该可以从可执行文件中检索值“hello world”。
基本上,我可以使用以下命令查看二进制文件中的变量名:
$ readelf -p .rodata main.exe | grep hello
[ 8] hello world
...我可以看到使用的价值:
$ readelf -s main.exe | grep greeting
59: 0000000000002008 12 OBJECT GLOBAL DEFAULT 18 greeting
我可以尝试解析
readelf -s
和 readelf -p
的输出以获得我想要的(检索名为 greeting
的变量的值),但我很确定我会把它搞砸。
那么是否存在 bintools 实用程序(或任何命令行程序)的开关组合,它们将执行与以下伪代码等效的操作:
$ [tool] --get-value-of-variable-name greeting --program=main.exe
"hello world"
甚至:
$ [tool] --verbose --get-value-of-variable-name greeting --program=main.exe
The constant value of the variable "greeting" in `main.exe` is:
"hello world"
是否存在 bintools 实用程序(或任何命令行程序)的开关组合,它们将执行与以下伪代码等效的操作:
当然:
将所有这些放在一起(我的文件与您的数据略有不同):
readelf -Ws main.exe | grep greeting
29: 0000000000002008 12 OBJECT GLOBAL DEFAULT 17 greeting
readelf -WS main.exe | grep '\[17\]'
[17] .rodata PROGBITS 0000000000002000 002000 000019 00 A 0 0 8
这告诉我我需要转储
12
字节(实际上是11,因为我不想要终止\0
),从偏移量0x2000 + (0x2008 (symbol address) - 0x2000 (section address))
开始。
dd if=main.exe bs=1 skip=$((0x2008)) count=11 2>/dev/null
hello world
现在,从
readelf
输出中解析这些数据比它的价值更麻烦——编写一个简单的 C++
程序来产生所需的输出要容易得多。使用 ELFIO 应该使这非常容易。