8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在我的程序中获取_GLOBAL_OFFSET_TABLE_地址?

Djam75 1月前

65 0

我想获取程序中 _GLOBAL_OFFSET_TABLE_ 的地址。一种方法是使用 Linux 中的 nm 命令,也许将输出重定向到文件并解析该文件以获取

我想在我的程序中获取 _GLOBAL_OFFSET_TABLE_ 的地址。一种方法是使用 nm 命令,也许将输出重定向到文件并解析该文件以获取 _GLOBAL_OFFSET_TABLE_ 的地址。但是,这种方法似乎效率很低。有哪些更有效的方法可以做到这一点?

帖子版权声明 1、本帖标题:如何在我的程序中获取_GLOBAL_OFFSET_TABLE_地址?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Djam75在本站《linux》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 接受的答案解决了使用 -fPIC -fPIE 获取地址的问题 _GLOBAL_OFFSET_TABLE_ .

    如果您必须在不使用 -fPIC -fPIE 启用的情况下进行编译,则 _GLOBAL_OFFSET_TABLE_ 符号将相对于当前指令进行引用。因此检索到的值实际上是偏移量,而不是绝对地址。

    我们仍然可以通过利用扩展来获取实际地址,该扩展允许您获取标签的地址,以便可以通过值将其提供给语句 goto

    void *got_offset, *got_start;
    l1:
        got_offset = &_GLOBAL_OFFSET_TABLE_;
    got_start = (void *)((uintptr_t)&&l1 + (uintptr_t)got_offset);
    

    表达式 &&l1 给出了标签代码段中的地址,我们在该地址中获取 的地址 _GLOBAL_OFFSET_TABLE_ 。然后,我们可以将此地址的值添加到存储的偏移量,以得到 的实际地址 _GLOBAL_OFFSET_TABLE_ .

  • 问题标记为 x86-64,因此您可以使用 RIP 相对寻址,如 lea HEREIS(%rip)、%rsi / ... / call printf@plt。或者只是 _GLOBAL_OFFSET_TABLE_(%rip)。但是,如果您要使用 32 位绝对地址,请始终选择 mov $HEREIS, %eax。除了 RIP 相对地址外,LEA 对于静态地址毫无意义。(使用 [disp32] 寻址模式执行相同操作需要更大的代码大小)

  • 如果你使用汇编语言,你可以 _GLOBAL_OFFSET_TABLE_ 不用 get_pc_thunk .
    这是一个棘手的方法。:)


    以下是示例代码:

    $ cat test.s
    
    .global main
    main:
     lea HEREIS, %eax   # Now %eax holds address of _GLOBAL_OFFSET_TABLE_      
    
    .section .got
    HEREIS:
    
    $ gcc -o test test.s
    

    这是因为 .got 部分与 <.got.plt>
    因此符号 HEREIS _GLOBAL_OFFSET_TABLE_ 位于同一地址。


    PS. 你可以使用 objdump 检查它是否正常工作。

    Disassembly of section .got:
    
    080495e8 <HEREIS-0x4>:
     80495e8:   00 00                   add    %al,(%eax)
        ...
    
    Disassembly of section .got.plt:
    
    080495ec <_GLOBAL_OFFSET_TABLE_>:
     80495ec:   00 95 04 08 00 00       add    %dl,0x804(%ebp)
     80495f2:   00 00                   add    %al,(%eax)
     80495f4:   00 00                   add    %al,(%eax)
    
  • @ZeZNiQ 感谢您对这个旧答案的编辑,但通常(在现代 Linux 上)-fPIE -pie 已经是默认设置,所以我认为我应该进行一些调整。我可以确认 -fno-pie -no-pie 的奇怪之处,例如在 64 位模式下打印出 0x2ed6,在 -m32 模式下打印出 0x2e76。我不完全理解这一点,所以您能看看我的编辑并确保我没有弄错您提出的重要观点吗?

  • @trojanfoe 只需添加 R.. 所示的“&”符号,我相信这样就可以解决问题。

  • 这段代码肯定不对。你打印的是 GOT 的第一个条目,它可能是指向 DYNAMIC 的指针,而不是 GOT 的地址。要打印 GOT 的地址,你应该使用 &_GLOBAL_OFFSET_TABLE_。

  • 这似乎有效:

    // test.c
    #include <stdio.h>
    
    extern void *_GLOBAL_OFFSET_TABLE_;
    
    int main()
    {
        printf("_GLOBAL_OFFSET_TABLE = %p\n", &_GLOBAL_OFFSET_TABLE_);
        return 0;
    }
    

    为了获得一致的地址 _GLOBAL_OFFSET_TABLE_ ,匹配的 nm 结果,您需要使用 编译代码以 -fPIE 执行代码生成,就像链接到与位置无关的可执行文件一样。(否则,您会得到一个像 一样的小整数 0x2ed6 -fno-pie -no-pie 。大多数现代 Linux 发行版的 GCC 默认值是 -fPIE -pie ,这将使 nm 地址只是相对于图像基址的偏移量,并且运行时地址是 ASLRed。(这通常对安全性有好处,但您可能不想要它。)

    $: gcc -fPIE -no-pie test.c -o test
    

    它给出:

    $ ./test
    _GLOBAL_OFFSET_TABLE = 0x6006d0
    

    然而,却有 nm 不同的看法:

    $ nm test | fgrep GLOBAL
    0000000000600868 d _GLOBAL_OFFSET_TABLE_
    

    或者使用太旧的 GCC,它根本不知道 PIE,更不用说将其 -fPIE -pie 作为默认设置, -fpic 也可以工作。

返回
作者最近主题: