首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么linux在x64中使用两个GOT部分?.GOT与.got.plt

在x64架构中,GOT(Global Offset Table)和.got.plt(Procedure Linkage Table)是Linux中用于实现动态链接的重要机制。

GOT是一个全局偏移表,用于存储程序中所有全局变量和函数的地址。它的作用是在程序运行时,将全局变量和函数的引用地址与实际地址进行动态绑定。GOT的设计是为了解决程序中全局变量和函数的地址无法在编译时确定的问题。通过使用GOT,程序可以在运行时根据需要动态地获取全局变量和函数的地址。

在x64架构中,由于指令集的限制,无法直接使用绝对地址进行跳转和访问全局变量。因此,GOT采用了两个部分的设计:一个是.got.plt,用于存储函数的地址;另一个是.got,用于存储全局变量的地址。

.got.plt是GOT的一部分,用于存储函数的地址。它在程序运行时被动态链接器(dynamic linker)填充,以实现函数调用的动态绑定。当程序中的函数被调用时,实际上是通过.got.plt中存储的函数地址进行调用。

.got是GOT的另一部分,用于存储全局变量的地址。它在程序运行时被动态链接器填充,以实现全局变量的动态绑定。当程序需要访问全局变量时,实际上是通过.got中存储的全局变量地址进行访问。

总结起来,Linux在x64中使用两个GOT部分是为了实现动态链接的需要。.got.plt用于存储函数的地址,实现函数调用的动态绑定;.got用于存储全局变量的地址,实现全局变量的动态绑定。

腾讯云相关产品和产品介绍链接地址:

  • 腾讯云云服务器(CVM):https://cloud.tencent.com/product/cvm
  • 腾讯云云原生容器服务(TKE):https://cloud.tencent.com/product/tke
  • 腾讯云数据库(TencentDB):https://cloud.tencent.com/product/cdb
  • 腾讯云CDN加速(CDN):https://cloud.tencent.com/product/cdn
  • 腾讯云人工智能(AI):https://cloud.tencent.com/product/ai
  • 腾讯云物联网(IoT):https://cloud.tencent.com/product/iot
  • 腾讯云移动开发(移动开发):https://cloud.tencent.com/product/mobdev
  • 腾讯云对象存储(COS):https://cloud.tencent.com/product/cos
  • 腾讯云区块链(BCS):https://cloud.tencent.com/product/bcs
  • 腾讯云元宇宙(Metaverse):https://cloud.tencent.com/product/metaverse
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

深入了解GOT,PLT和动态链接

至于为什么要这么绕, 后面会说明具体原因. 这是链接器执行链接时实际上要填充的部分, 保存了所有外部符号的地址信息....有两个RELRO的等级, 部分RELRO和完全RELRO....将.got.plt合并到.got, 所以.got.plt将不复存在. 因此可以看到, 只有完全RELRO才能防止攻击者覆盖.got.plt, 因为链接期间 就对程序符号进行了解析.....plt.got: 数据段(r-x),.plt类似,不过是保存外部变量的 其中.plt和.plt.got地址相邻,统称为PLT;.got.got.plt地址相邻,统称为GOT。...一般而言x64函数调用通过寄存器传递参数,但是dlresolve为了避免备份原始调用的参数寄存器, 而选择了使用自己的调用约定,即还是和x86一样通过栈来传递参数。

1.4K10

hook的几种方式及原理学习

重定位动态链接 当多个 .o 文件链接或 运行时需要动态库的时候,都有重定位的概念,链接的时候,多个.o之间 相互依赖的变量和函数 要找到实际的地址, 同样运行时依赖动态库的函数,一般是记录在全局偏移表...及 PLT 表 Linux下,GOT被拆分成”.got”和”.got.plt”2个表。...导入表对应在动态链接段.got.plt(DT_PLTGOT)指向处,但是每项的信息是和GOT的表项对应的,因此,解析动态链接段时,需要解析DT_JMPREL、DT_SYMTAB,前者指向了每一个导入表表项的偏移地址和相关信息...,包括GOT偏移,后者为GOT表。   ...为什么开头调用一个函数就会core呢? gdb 打印拷贝后的函数原函数 对比,发现 调整后的指令如果有 %rip relative的地址(offset),那么这个地址是需要对应调整的。 ?

1.9K30
  • 【图片+代码】:Linux 动态链接过程的【重定位】底层原理

    ld-linux.so.2也是一个动态链接库,部分情况下动态链接库已经被加载到内存中了(动态链接库就是为了共享),操作系统此时只需要把动态链接库所在的物理内存,映射到 main进程的虚拟地址空间中就可以了...并且,一个动态库文件,有两个特殊的段(.rel.dyn和.rel.plt)来告诉链接器:.got和.got.plt两个,有哪些符号需要进行重定位,这个问题下面会深入讨论。...和.got.plt数据段一样,都是可读、可写的,所以被当做同一个 segment被加载到内存。...那么:liba.so通过什么方式来告诉动态链接器:需要对.got和.got.plt两个的表项进行地址重定位呢?...,画成内存模型图就是下面这样: 暂时只专注表项的红色部分:.got的b, .got.plt的func_b,这两个符号都是libb.so中导出的。

    2.3K11

    PWN 利用mprotect函数进行.got.plt地址段的读取

    mprotect函数详解 Linux,mprotect()函数可以用来修改一段指定内存区域的保护属性 函数原型如下: #include #include <sys/mmap.h...prot可以取以下几个值,并且可以用“|”将几个属性合起来使用: PROT_READ:表示内存段内的内容可读; PROT_WRITE:表示内存段内的内容可写; PROT_EXEC:表示内存段的内容可执行...; PROT_NONE:表示内存段的内容根本没法访问。...= 0x080EB000 # .got.plt表的起始地址 got_plt_size = 0x100 # 内存长度 got_plt_type = 0x7 # 内存权限,读写执行 def main...got.plt表进行内容的读取 payload构建流程: 垃圾数据 --> mprotect函数地址 --> 三个连续的pop地址 --> .got.plt表起始地址 --> 内存长度 --> 内存权限

    60710

    GOTlinux系统实现代码动态加载的作用和其他段的说明

    动态加载,也就是调用系统函数时再去确认所调用的函数地址的技术需要使用两个段,一个是.plt段,一个是.got.plt段。...后者其实是.got段的一种特定形式,.got程序的加载和执行过程还有其他形式和作用,在后续章节我们再研究。 上一节我们以调研系统函数puts为例描述了动态加载的基本过程。...于是动态链接库系统内存里面查找到puts函数的地址,然后将该地址填写到.got.plt里面,所填写的位置正好就是4003f0对应代码从.got.plt里面取出来的数值所在位置。...上图展示的是重定向段的两条记录,其中展示了需要重定向的地址在内存的偏移,其中显示的是两个地址分别为0x601018和601020,这两个地址其实都落在.got段里面。...init_aray包含了一系列初始化函数入口地址所构成的数组,main函数执行时,数组的函数会被提前调用进行初始化,我们可以使用命令objdump -d —section .init_array.out

    2.3K20

    ELF文件及android hook原理

    第二步 符号解析重定位 使用第一步收集到的信息,读取输入文件中段的数据、重定位信息,并且进行符号解析重定位、调整代码的地址等 使用ld链接器将”a.o”和”b.o”链接起来: $ld a.o b.o...Linux下,ELF可执行未见默认从地址0x08048000开始分配。 符号解析重定位 编译器将”a.c”编译成指令时,它如何访问”shared”变量?如何调用”swap”函数?...Linux下,可以通过查看”/proc”来查看进程的虚拟空间分布: ? 我们可以看到进程中有5个VMA,只有前两个是映射到可执行文件两个Segment。...GOT 位于 .got.plt section ,而 PLT 位于 .plt section。这些都是数据段,不同进程拥有其副本。...假设链接器全局符号表里面找到”printf”的地址为0x08801234,那么链接器就会将这个地址填入到”.got.plt偏移为0x000015d8的位置中去,从而实现了地址的重定位。

    3.8K81

    《程序员的自我修养》笔记

    使用objdump查看mach-o文件 objdump -h:查看段信息 vma是指的不同段的地址入口,可以看到虽然段有很多,但是type类型大部分都一样,比如代码段类型分为了两个段描述更加细致;数据段更夸张用了五个段存储初始化了的变量...现在的Linux系统,一个普通程序会使用到的C语言静态库至少1 MB以上,那么,如果我们的机器运行着100个这样的程序,就要浪费近100 MB的内存;如果磁盘中有2 000个这样的程序,就要浪费近...这样got表里面存的就是 真实的内存地址,也就实现了 共享库的代码指令部分 是真正共享的,只需要在内存一次即可 延迟加载技术:PLT 为什么出现延迟加载 动态链接比静态链接慢的两个主要原因: 动态链接的符号...该函数会找到存储函数符号的got项地址: 如果got没有加载这个符号(这个符号没有记录地址,因为符号对应的模块还没有加载到内存)那么函数就会返回继续执行之后的代码,首先把该符号got.plt的下标索引和该符号所处的动态共享库...表里该符号got.plt的对应项,每个延迟绑定的符号got.plt段中都有一个 相应的plt项存储,会存储dynamic段的地址(关于动态链接相关的参数和设置项,在这不考虑)和该符号所在的模块地址

    9110

    栈溢出漏洞的利用和缓解

    简而言之, 动态链接的可执行程序, 其使用到的外部变量的偏移存放于GOT(global offset table) , 而使用到的外部函数存放于PLT(Procedure Linkage Table)..., 其中PLT又实现了延时加载, 只会在第一次时将用到的函数地址加载到某个地方(.got.plt), 之后直接从该地方读取....之前也说了, 外部函数会被动态加载到.got.plt对应的偏移, 它的本质也只是一个含有众多函数指针的数组. 所以, 如果我们能通过溢出来改写这个表对应函数的地址, 不就可以实现执行了吗?...RELRO 2001年, teso安全团队的文章描述了覆盖.got.plt段来截获控制流的方法. 而在2004年, 就有了这种利用手法的防护, 称为重定向只读, 即RELRO....链接时解析所有符号. 将.got.plt合并到.got. 因此, Full RELRO可以防止.got.plt的函数指针被覆盖. 如何绕过?

    1.1K10

    现代Linux系统上的栈溢出攻击

    主要我们必须要写入80个字节(64+8+8)因为指针64位机器上面是8个字节的,为什么要加两个8呢 因为我们的缓冲区和返回地址之间还保存着一个指针 有木有注意到go函数的第一条指令 push ebp....got.plt 是一个地址表,城市使用它来跟踪库的函数,我前面已经说过ASLR确保每一个动态链接库文件每一次程序加载的时候都会被映射到不同的基址上面。...这个指针,让它指向 .got.plt exit的入口,然后使用hax()的地址来覆盖掉此处exit()函数的地址。...,我们使用48个字节的无用数据然后使用.got.plt表入口的地址来覆盖掉next指针。...记住由于我们是小端机器上面,所以地址的字节顺序是反着的。第二个文件包含了函数 hax() 的指针,也就是要被写到 .got.plt的 exit 入口的地址。

    1.2K10

    RT-thread finsh移植到linux平台

    C 语言解释器模式下,FinSH 能够解析执行大部分 C 语言的表达式,并使用类似 C 语言的函数调用方式访问系统的函数及全局变量,此外它也能够通过命令行方式创建变量。...我们已经代码中指定了FSymTab和VSymTab, 还需要在链接脚本定义这两个段(为什么需要在链接脚本定义这两个段呢,是因为这两个段是我们自定义的, 缺省的链接脚本缺少对自定义数据段的声明),...12 : 0, .); .got.plt : { *(.got.plt) *(.igot.plt) } .data : { *(.data .data...SECTION: FSymTab和VSymTab,这两个最终的ELF文件,位于.data段之后, .bss段之前,同时,我们定义了4个变量,我们可以c代码中使用这4个变量实现对SECTION的控制...Fsymtab段定义的函数 上述两个技巧可以主流的编译器链接器上适用, 利用编译器的特性我们很容易实现将函数放在指定的段,然而每次都要修改链接脚本就显得不那么方便(想要了解linux默认链接脚本的同学可以参考

    3.2K10

    编译、链接到载入、运行的大致过程----2.链接

    这些目标文件 和需要的其他资源被整合到一起,最终才生成我们常见的程序(典型的比如windows下的各种exe文件,linux 下的elf LSB executable 文件,linux 下的elf LSB....got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr...000000000060bfb8 0000bfb8 0000000000000030 0000000000000008 WA 0 0 8 [25] .got.plt...的地址: 直接读取程序头的segment ,获得的地址是: 0x400000~0x40adcc 通过计算segment所包含的section, 获得的地址是: 0x400238~0x40adcc 为什么上述两种方式得到的同一个...如果segment 的开始地址不是page的开头,结束地址不是page的结尾,那么这两个地址都需要 进行page 对齐的调整;所以对上述的地址按照page对齐(4KB对齐就是 以0x1000为单位进行对齐

    83930

    探索ELF可执行文件的“干货”:段头表和段的基本介绍

    uint64_t sh_offset; #段对应数据ELF文件的偏移 uint64_t sh_size; #段的大小 uint64_t sh_link; #该段有关系的其他段对应的段头段头表的下标...init段包含了程序执行前所需要的初始化操作,使用C语言编程时入口是main,这部分代码就是main执行前所需要运行的指令。当程序运行结束后,.fini对应的代码会被执行已完成资源回收等操作。...ELF文件帮助系统进行延迟绑定的有两个段分别为.plt和.got。...上图中我们可以看到puts,它是linux系统中常用的将信息输出到控制台的函数。如果我们代码调用puts函数时,实际上编译器会先调用上图里面的puts@plt这部分的指令。...,然后读取所在地址的数值,我们通过指令objdump -M intel -section .got.plt -d a.out来看对应地址的数值: ?

    1.5K20

    Linux64位程序的漏洞利用

    不过, 现在毕竟已经是2018年了, 64位程序也逐渐成为主流, 尤其是Linux环境. 因此本篇就来说说64位下的利用32位下的利用和缓解绕过方法有何异同....深入了解GOT,PLT和动态链接我们知道, 每个函数的PLT只包含几行代码, 作用是设置参数并跳转到GOT, 而对应GOT解析前包含了对应PLT的下一条指令....32位情况下和64位情况下利用方式大同小异, 可以参考x86漏洞利用的ASLR 部分, 这里就不赘述了. offset2lib offset2lib是2014年提出来的一种x64下绕过ASLR的方法...文章最开始的部分我们说了, x64下调用约定是用寄存器 rdi,rsi,rdx…来传参, 所以关键是怎么把可控部分(栈)的值传给寄存器....可惜使用常见的自动化rop工具小型程序难以找到合适的gadget.

    1.2K70

    linux的so注入热更新原理

    ,才能知道地址在哪里,比如main使用了一个头文件定义的函数int add(),最后编译成了main.outadd.so两个elf文件。...如果找的是foo2,foo2是另一个elf定义的,例如之前提到的,调用add.so函数的add函数。那么就需要左边的rela.plt(重定向信息)以及got.plt(位置偏移信息)。...这里派生出几个问题 为什么要动态链接? 为了解决重复代码、更新难的问题,把代码按模块分开。(实际上linux各种运行时库的版本也很难受) 为什么不做成机器码直接jmp就好了?...第二行和第三行传参调用libc完成了绑定puts的过程,并且更新got。 后续再调用第一行,就直接跳转到了目标函数了。 为什么plt里不直接存放地址,要搞个got?...理论上是可以got里的每个地址拆分放到plt,可能是出于逻辑数据分离考虑,并且分开后内存页的读写权限更好管理,毕竟一个是可执行,一个是可写。

    11.3K50

    linux装载和启动可执行程序的过程

    x86结构GOT表的前三项保留,用于保存特殊的数据结构地址,其它的各项保存符号的绝对地址。...实际的可执行程序或者共享目标文件GOT名称为.got.plt的section,PLT表名称为.plt的section。   ELF文件符号动态解析的过程 ?   ...链接器把所需要的共享库加载到内存后,并没有把共享库的函数的地址写到GOT,而是延迟到函数的第一次调用时,才会对函数的地址进行定位。...pushl n的地址,实际上就是顺序执行下一步 (3)执行pushl n,n为puts函数地址GOT的位置,向堆栈压入这个偏移量的主要作用就是为了找到puts函数的符号名以及puts函数地址...load_elf_binary代码 load_elf_binary(struct linux_binprm *bprm) { …… if(elf_interpreter) //使用动态链接

    3.1K40

    高级ROP技巧:ret2_dl_runtime_solve

    延迟绑定概念 由于Linux下的程序采用了延迟绑定机制,这就使得程序在运行后需要有专门的函数去根据程序的符号(可以看成一个入口)把内存运行库libc真实的变量或函数的地址计算出来并保存在特定的位置...got[1]和got[2]: .got.plt:0804A004 dword_804A004 dd 0 ; DATA XREF: sub_8048380↑r...//got[1] .got.plt:0804A008 dword_804A008 dd 0 ; DATA XREF: sub_8048380+6↑r //got...接下来的步骤,_dl_runtime_solvelibc搜索这个字符串对应的函数的地址,并将其存入write对应的got。...至此逻辑发生了闭合,回到第一步,write对应的plt表的第一个语句jmp到got表保存的地址处就相当于直接jmp到了write函数在内存真正的位置,完成了函数的符号和地址的链接,往后再次使用该函数不会再发生链接

    43010
    领券