在 .rodata 和 .rodata1 中检索偏移量、字符串和虚拟地址

Retrieving Offsets, Strings and Virtual Address in .rodata and .rodata1

我正在尝试获取 offsets/virtual 地址,.rodata 和 .rodata1 部分中的字符串。

例如:

#include <cstdio>

void myprintf(const char* ptr) {
        printf("%p\n", ptr);
}

int main() {
        myprintf("hello world");
        myprintf("[=10=][=10=]");
        myprintf("ab[=10=]cde");
}

以上程序每个 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++代码来检索:

  1. 所有字符串文字的偏移量(例如上面的 10、14、23 和“[=67=][=67=]”缺少的那个)

  2. 字符串文字(例如上面的“%p\n”、"hello wolrd"、“[=67=][=67=]”)

  3. .rodata文件的偏移量(例如上面的400600;是否保证是虚拟内存地址?至少我看到我的测试代码中的所有字符串文字都是这种情况以上。)

因为我的最终目标是写一个 C/C++ 代码来读入一个 executable 并接受用户的输入作为 offset/virtual 内存地址,如果输入匹配offset/virtual 任何字符串文字的内存地址,然后使用 printf() 打印出来。否则,忽略。 (感谢@Armali 帮我澄清)

我已阅读this article。我可以访问 .rodata 中的整个字符串 table,但不能访问 "string table indexes"。文章提到了"string table indexes",但没有具体说明如何检索索引。

提示?

此外,我想知道为什么会有一个名为 .rodata1 的部分。根据 elf 联机帮助页:

.rodata1

This section holds read-only data that typically contributes to a nonwritable segment in the process image. This section is of type SHT_PROGBITS. The attribute used is SHF_ALLOC.

.rodata的描述完全相同。那么,为什么我们有.rodata1

谢谢!

I am trying to get offsets, strings and virtual addresses in .rodata and .rodata1 sections.

I would like to write a C or C++ code to retrieve:

  1. The offsets of all the string literals (e.g. 10, 14, 23 above and the missing one for "[=22=][=22=]")

  2. The string literals (e.g. "%p\n", "hello wolrd", "[=22=][=22=]" above)

字符串文字 是用双引号括起来的字符序列。我们实际上无法分辨 ELF 数据部分中的什么是字符串文字的表示。考虑将这些行添加到您的 main():

        static const int s = '[=10=]fg[=10=]';
        myprintf((char *)&s);

虽然没有字符串字面量,但是readelf -p .rodata …可能会输出像e这样的一行。 g.

  [    21]  gf

因此,要真正识别数据部分中字符串文字的表示,有必要将数据与源代码标记(困难)或汇编代码(可能更容易)相关联。

it would be an issue to me that if a string literal doesn't exist in .rodata

这很容易发生。考虑:

        static char hello[] = "Hi";
        myprintf(hello);

由于字符串文字用于初始化字符数组,它必须是可修改的,所以它可以进入 .data 而不是 .rodata 部分,因为 readelf -p .data … 可能显示。

if the ELF sections contain all the valid offsets, why not using them?

有效偏移量不会收集到任何可以方便访问的地方,因此出于实际目的,我们可以说ELF部分不包含offsets/indexes 到字符串文字.


I am able to access the entire string table in .rodata but not "string table indexes". The article mentions "string table indexes" but it doesn't specify how to retrieve indexes.

字符串table索引没有在.rodata中提到,但是 字符串 table 部分 .strtab:

This section holds strings, most commonly the strings that represent the names associated with symbol table entries.

Just a side but related question, do you know what the first 16 bytes are in .rodata? I noticed that it has 1 0x1 and 1 0x2 and then the rest is 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 的全局对象,听起来像是标准库中的东西。