检索 .rodata 和 .rodata1 中的偏移量、字符串和虚拟地址
Posted
技术标签:
【中文标题】检索 .rodata 和 .rodata1 中的偏移量、字符串和虚拟地址【英文标题】:Retrieving Offsets, Strings and Virtual Address in .rodata and .rodata1 【发布时间】:2018-08-19 16:52:08 【问题描述】:我正在尝试获取偏移量/虚拟地址、.rodata 和 .rodata1 部分中的字符串。
例如:
#include <cstdio>
void myprintf(const char* ptr)
printf("%p\n", ptr);
int main()
myprintf("hello world");
myprintf("\0\0");
myprintf("ab\0cde");
上面的程序每个readelf -a
的输出都有.rodata:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[16] .rodata PROGBITS 0000000000400600 00000600
readelf -W -p .rodata
给了我偏移量和相关的 non 空字符串:
String dump of section '.rodata':
[ 10] %p^J
[ 14] hello world
[ 23] ab
[ 26] cde
我想写一段 C 或 C++ 代码来检索:
所有字符串字面量的偏移量(例如上面的 10、14、23 和 "\0\0" 缺少的一个)
字符串字面量(例如上面的“%p\n”、“hello wolrd”、“\0\0”)
.rodata 文件的偏移量(例如上面的 400600;它保证是虚拟内存地址吗?至少我看到上面测试代码中的所有字符串文字都是这种情况。)
因为我的最终目标是编写一个 C/C++ 代码来读取可执行文件并接受用户的输入作为偏移量/虚拟内存地址,如果输入与任何字符串文字的偏移量/虚拟内存地址匹配,则使用 @ 987654328@打印出来。否则,忽略。 (感谢@Armali 帮助我澄清)
我已阅读this article。我可以访问.rodata
中的整个字符串表,但不能访问“字符串表索引”。文章提到了“字符串表索引”,但没有具体说明如何检索索引。
提示?
另外,我想知道为什么会有一个名为.rodata1
的部分。根据精灵手册页:
.rodata1
此部分包含只读数据,这些数据通常构成过程映像中的不可写段。此部分的类型为 SHT_PROGBITS。使用的属性是 SHF_ALLOC。
它的描述与.rodata
完全相同。那么,为什么我们有.rodata1
?
谢谢!
【问题讨论】:
解析system("readelf -W -p .rodata")
和system("readelf -a | grep .rodata | awk 'print $4'");
的输出还不够吗?
@KamilCuk 我在网上遇到了来自 readelf -a 的不同输出。所以我认为通过elf.h基于ELF解析更安全。
@KamilCuk 我也刚刚发现readelf -W -p .rodata
不输出空字符串的偏移量(例如“\0\0”和“\0”)。因此,我不能使用 readelf。让我更新我的问题。谢谢你的建议!
是的,readelf -p
的输出确实让我觉得偏移量存储在 elf 中。而readelf source code 相当复杂(见dump_section_as_strings()
),这让我觉得我不能只使用\0
作为分隔符来解析字符串表。
@Armali 你介意用“ELF 部分不包含字符串文字的偏移量/索引”来更新你的答案吗?那么,我会接受你的回答。谢谢。
【参考方案1】:
我正在尝试获取 .rodata 和 .rodata1 部分中的偏移量、字符串和虚拟地址。
我想写一段 C 或 C++ 代码来检索:
所有字符串字面量的偏移量(例如上面的 10、14、23 和 "\0\0" 缺少的一个)
字符串字面量(例如上面的“%p\n”、“hello wolrd”、“\0\0”)
字符串文字是用双引号括起来的字符序列。我们实际上无法分辨 ELF 数据部分中的什么是字符串文字的表示。考虑将这些行添加到您的main()
:
static const int s = '\0fg\0';
myprintf((char *)&s);
虽然没有字符串字面量,readelf -p .rodata …
可能会输出类似 e 的行。 g.
[ 21] gf
因此,要真正识别数据部分中字符串文字的表示,有必要将数据与源代码标记(困难)或汇编代码(可能更容易)相关联。
如果
.rodata
中不存在字符串文字对我来说将是一个问题
这很容易发生。考虑:
static char hello[] = "Hi";
myprintf(hello);
由于字符串字面量用于初始化字符数组,它必须是可修改的,它可以进入.data
而不是.rodata
部分,正如readelf -p .data …
可能显示的那样。
如果 ELF 部分包含所有有效的偏移量,为什么不使用它们?
有效的偏移量没有收集到任何可以方便访问的地方,所以出于实际目的,我们可以说ELF部分不包含字符串文字的偏移量/索引.
我可以访问
.rodata
中的整个字符串表,但不能访问“字符串表索引”。文章提到了“字符串表索引”,但没有具体说明如何检索索引。
字符串表索引没有与.rodata
相关,但与
字符串表部分 .strtab
:
此部分包含字符串,最常见的是表示相关名称的字符串 带有符号表条目。
【讨论】:
感谢您的回复。我实际上不介意在.rodata
部分看到非字符串文字。但是,如果.rodata
中不存在字符串文字(假设仅链接到静态库),这对我来说将是一个问题。所以你是说.strtab
部分有.rodata
的字符串表索引?但是根据您引用的内容,听起来.strtab
仅包含字符串,但不包含偏移量/索引。也许我误解了。你介意详细说明吗?谢谢!
不,我不是说.strtab
部分具有.rodata
的字符串表索引,而是.strtab
拥有符号表 名称,因此那些 字符串表索引 与您的目标无关。
关于提到的issue,我会修改答案。
您的反例(静态数组)非常好。感谢您指出了这一点。然后,现在,我也必须考虑如何处理它。谢谢!
感谢更新。只是一个侧面但相关的问题,你知道.rodata
的前 16 个字节是什么吗?我注意到它有 1 0x1 和 1 0x2,然后其余的是 0x0。提前致谢。【参考方案2】:
只是一个侧面但相关的问题,你知道
.rodata
的前 16 个字节是什么吗?我注意到它有 1 0x1 和 1 0x2,然后其余的是 0x0。
并非总是如此;它仅取决于程序使用的只读数据。例如,如果我编译您的示例程序,字符串%p\n
从偏移量 4 开始,在此之前我还有 1 和 2(作为 16 位字),但没有零。进一步查看.rodata
开头的符号可能是
> readelf -s … | grep 400738
14: 0000000000400738 0 SECTION LOCAL DEFAULT 14
59: 0000000000400738 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
(400738
是这里的.rodata
起始地址),我得到_IO_stdin_used
,一个大小为 4 的全局对象,听起来像是标准库中的东西。
【讨论】:
以上是关于检索 .rodata 和 .rodata1 中的偏移量、字符串和虚拟地址的主要内容,如果未能解决你的问题,请参考以下文章