我正在尝试获取.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;是否保证是虚拟内存地址?至少我看到上面的测试代码中的所有字符串文字都是这种情况。)< / p>
因为我的最终目标是编写C / C ++代码以读取可执行文件并接受用户输入作为偏移量/虚拟内存地址,如果输入匹配任何字符串文字的偏移量/虚拟内存地址,则使用{ {1}}进行打印。否则,请忽略。 (感谢@Armali帮助我阐明问题)
我已阅读this article。我可以访问printf()
中的整个字符串表,但不能访问“字符串表索引”。本文提到“字符串表索引”,但未指定如何检索索引。
提示?
我也不知道为什么会有一个叫做.rodata
的部分。根据精灵手册:
.rodata1
此部分保留通常在过程映像中构成不可写段的只读数据。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC。
它的描述与.rodata1
完全相同。那么,为什么我们有.rodata
?
谢谢!
答案 0 :(得分: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
:
此部分包含字符串,最常见的是代表相关名称的字符串 带有符号表条目。
答案 1 :(得分:1)
只是一个侧面但相关的问题,您知道
.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的全局对象,听起来像是标准库中的内容。