中动态路径加载_GOT段在linux系统中实现代码动态加载的作用和其他段的说明

上一节我们看到,当程序想调用系统函数时,在编译阶段无法确认被调用函数所在的虚拟地址。因此必须有机制让程序在运行过程中,在调用系统API的时候有办法去确定所调用的系统函数对应的入口地址,这就是代码运行时对应动态加载的过程。

动态加载,也就是在调用系统函数时再去确认所调用的函数地址的技术需要使用两个段,一个是.plt段,一个是.got.plt段。后者其实是.got段的一种特定形式,.got段在程序的加载和执行过程中还有其他形式和作用,在后续章节我们再研究。

上一节我们以调研系统函数puts为例描述了动态加载的基本过程。当我们在代码中使用puts函数时,编译器并不是将代码编译成直接调用该函数的形式。因为编译器根本不知道操作系统将puts函数的代码加载到虚拟内存的哪个位置。所以编译器会在调用puts函数的地方,先自动跳转到.plt段里面的给定位置,这个位置用puts@glt来表示。

从puts@glt对应的地址开始是一段二进制指令代码,其基本内容如下所示:

a8748fa843f535510ff9f7d671148b84.png

上图显示的代码也叫“函数桩”,每个系统函数都对应一段这样的代码。为何要用“桩”来描述这些代码呢,因为这些指令都做了相同的工作,首先他们都将一个数值压入堆栈,这个数值对应该段代码的序号。我们可以把这些“函数桩”集合看成是一个数组,它们都是数组中的元素,push指令压入的数值就是元素对应的下标。

注意到无论是puts@plt,还是__libe_start_main@plt它们对应的代码除了push一个数值后,然后都跳转到地址4003f0,而该地址就落在.plt段里面的某个位置。4003f0这个位置其实对应一段代码的起始地址,这段代码的作用是从.got.plt段里面取出一个数值作为下一步跳转的地址,然后通过Jmp跳转到取出地址所在位置,将程序控制权交给那里的代码。

一开始从.got.plt取出的地址其实是系统动态链接库的入口地址,于是跳转过去之后动态链接库会接管程序的控制权,这时候原来push压入堆栈的数值就产生作用,根据该数值连接器就能知道代码想要调用哪个系统接口。比如连接器看到堆栈上的值是0x0时,它就知道程序想要调用puts函数。于是动态链接库在系统内存里面查找到puts函数的地址,然后将该地址填写到.got.plt里面,所填写的位置正好就是4003f0对应代码从.got.plt里面取出来的数值所在位置。

然后动态连接器再次调用puts@plt这里的指令,于是前面的流程再运行一次。这里需要注意的是,第二次执行4003f0这个位置对应的指令时,从.got.plt取出的数值就不再是动态链接库的入口地址,而是puts函数对应的入口地址,于是动态链接工作完成,代码能够在运行时正确的调用到它想要执行的系统函数。

为何不直接将被调用函数的地址直接写入到ELF文件中,而是要绕一个大弯,先要把函数地址写入.got.plt然后再写入到.plt段里面的“函数桩”呢,主要原因在于安全考虑。由于.text段设置为不可写,如果可写,那么就可能让人直接修改其中代码指令了。.got.plt段属于数据段,因此里面的数据可以修改,绕这个弯的目的就是防止代码被他人直接修改。除了.got.plt段外,还需要理解的是.got段,后者的作用主要在于访问共享代码库到处的变量。两者区别在于.got.plt段包含了代码,而.got段会直接包含共享库到处的变量地址而不是包含代码。

我们再看其他一些重要的段。在后面二进制分析中,我们还需了解.rel.或.rela.这类重定向段。他们的类型属于SHT_RELA,这些段的作用在于帮助链接器实现代码重定向。这些段告诉链接器代码的哪些地方需要进行重定向,以及告诉链接器如何修改需要重定向的代码,我们可以使用命令readelf —relocs a.out来查看ELF文件的重定向段:

34d1919ff26f0b4f28b4ed53cad2ded2.png

上图展示的是重定向段中的两条记录,其中展示了需要重定向的地址在内存中的偏移,其中显示的是两个地址分别为0x601018和601020,这两个地址其实都落在.got段里面。重定向段又分为不同种类,最常见的种类是R_X86_64_GLOB_DAT和R_X86_64_JUMP_SLO,前者主要用于查找链接库里变量的地址,后者主要用于查找链接库中的函数入口。

另外还需要关注的是.dynamic段,使用命令 readelf —dynamic a.out可以查看:

3e3ef0391c8a644f818a0afc370265b4.png在TYPE一栏为NEED的表明,对应共享库需要在代码运行时加载到系统内存。可以看到第一行对应的libc.so.6就表明该ELF文件如果要加载运行就必须确保共享库libc.so.6要被加载到内存里

需要关注的还有.init_array和.fini_array段,前者包含了一系列代码在运行前需要执行的一系列初始化函数,在.init_aray中包含了一系列初始化函数入口地址所构成的数组,在main函数执行时,数组中的函数会被提前调用进行初始化,我们可以使用命令objdump -d —section .init_array.out来查看其内容:

b342503973c45b7670331c1fdcc02513.png上图表明.init_array中只有一个函数地址,对应的是0x400400,也就是函数__libc_start_main的入口地址。同理.fini_array段也包含了一系列函数地址,他们在代码运行结束后会被系统调用,下一节我们再回头看看程序表头。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构件化软件生产

前面提到的是个人理想,那个是远景的。近期能够触摸到的就是构件化的软件生产了。先摘抄一句我非常喜欢的话:“软件工厂一定不是源代码拼装起来的,而是目标代码拼装出来的。就像零件生产一样,给你一个螺丝就可以拧上,而…

[vue] 你有写过自定义组件吗?

[vue] 你有写过自定义组件吗? 写过,随便说点组件的引入问题、注册问题、传值问题吧个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

GitLab结合Eclipse的简单使用 - 20190211

需求: 移动端的值班经理视图调用了三个接口,需要在移动段的应用下加上三个接口的路由,分别是: /xxx-mvc/dutyView/getProviderSysDeal /xxx-mvc/dutyView/getSysAlarmData /xxx-mvc/dutyView/getSysStaffInfo package com.xxx.xxx…

单片机shell命令_MCU调试大法:使用串口实现简单shell功能

MCU调试大法:使用串口实现简单shell功能[复制链接]MCU程序调试方法有很多,比如软/硬件仿真、添加数据打印等。像Keil MDK就支持不少单片机的软件仿真,在没有拿到单片机的情况下,就可以先仿真调试部分功能,查看代码逻辑…

Google Desktop 果然

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />如果是真的&#xff0c;那么果然可怕&#xff0c;还好没有安装&#xff0c;诸位有安装和使用的有没有如下的体验&#xff1f; http://blogs.salon.com/0001561/categories/visual…

[vue] 怎么在vue中使用插件?

[vue] 怎么在vue中使用插件&#xff1f; npm 安装 然后再main.js 引入 最后 vue.use(插件名)个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

中文整合包_MIMOSA2: 基于微生物组和代谢组数据的整合分析

MIMOSA2&#xff1a;基于微生物组和代谢组数据的整合分析MIMOSA2 升级自MIMOSA1。是 Borenstein 实验室(http://borensteinlab.com/ , 专注宏基因组系统 生物学)最新开发的工具。用于微生物群落和代谢组的整合分析&#xff0c;寻找微生物和代谢产物之间的关系。先前Borenstein …

微软建议的ASP性能优化28条守则

二十八条改善 ASP 性能和外观的技巧 Len Cardinal&#xff0c;高级顾问&#xff0c;Microsoft Consulting Services George V. Reilly Microsoft IIS Performance Lead 改编自Nancy Cluts 的文章 开发人员技术工程师 Microsoft Corporation 2000 年 4 月 摘要&#xff1a;本文介…

[vue] vue如何监听键盘事件?

[vue] vue如何监听键盘事件&#xff1f; 那要看你怎么监听了, 比如 keyup.enter, 或者直接全局监听个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

同余逆元简单总结

# 同余&逆元 1. 同余 1. 同余的基本概念及性质 若\(x\)%\(ma\)即m是 x-a 的一个因子, 则称x与a关于m同余,记作:\[x \equiv a(mod \;m)\]同余基本性质:○1. 自反性:\(a \equiv a(mod\;m)\) ○2. 对称性:\(a \equiv b(mod\;m) \rightarrow b \equiv a(mod\;m)\) ○3. 传递性:…

python二级简书_12月4日,总结发现杯,备战python二级

上午看二级第一二章下午查询成绩夜晚看第三章做笔记&#xff0c;回看笔记总结&#xff1a;整体不是很理想&#xff0c;但感觉都比我高&#xff0c;呜呜呜他们的成绩一个个的都出来了&#xff0c;我的呢……为什么&#xff0c;还查不到&#xff0c;我知道我考的差&#xff0c;但…

编写高性能 Web 应用程序的 10 个技巧 (转)

http://www.microsoft.com/china/msdn/library/webservices/asp.net/us0501ASPNETPerformance.mspx本文讨论&#xff1a;常见的 ASP.NET 性能神话 有用的 ASP.NET 性能技巧和诀窍 在 ASP.NET 中处理数据库的一些建议 缓冲以及用 ASP.NET 进行后台处理 本文使用下列技术&#xf…

[vue] 怎么在watch监听开始之后立即被调用?

[vue] 怎么在watch监听开始之后立即被调用&#xff1f; let vmnew Vue({el:"#first",data:{msg:liuneng},watch:{msg:{handler (newMsg,oldMsg){console.log(newMsg);},immediate:true}}})设置immediate属性为true个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前…

关于 spring 使用 mongodb 的 mongotemplate 对象操作数据库,对象注入问题(即该对象能否正常的调用相应的CRUD方法来处理数据)...

通过 spring 框架&#xff0c;直接调用一些处理对象的方法和数据库交互&#xff0c; http 接口从 controller 层调用开始&#xff0c; 如果是&#xff1a;controller --> service --> dao --> entity 这个流程正常调用&#xff0c;则&#xff1a; &#xff08;1&#…

二叉搜索时与双向链表python_【剑指offer】26 二叉搜索树与双向链表

- 题目描述输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点&#xff0c;只能调整树中结点指针的指向。- 解题思路递归- Java实现/**public class TreeNode { int val 0; TreeNode left null; TreeNode right nul…

碎片脚本注解(后续整理)

#!/bin/bash#"${1:0:1}"的意思表示提取$1中的第一个字符&#xff0c;变量$1表示的是命令行输出的第一个字符串&#xff0c;#变量$0表示从输出的$1字符传中的第一个字符开始截取&#xff0c;最后一个$1表示只截取一个字符。if [ "${1:0:1}" - ]; then   …

标准配置的Windows平台上潜在可用屏幕区域

经常在windows开发网站的朋友&#xff0c;在开始设计网站时&#xff0c;最需要知道的就是一个图片的大小和尺寸。我本人也是在windows上玩弄了几年的&#xff0c;虽然没有什么正规的证书之类的&#xff0c;但是自己对windows的东西&#xff0c;一些基本的还是知道的&#xff0c…

iframe带了token不显示_不就是登录吗,能有多复杂?sa-token带你轻松搞定多地登陆、单地登录、同端互斥登录...

前言在java的世界里&#xff0c;有很多优秀的权限认证框架&#xff0c;如Apache Shiro、Spring Security 等等。这些框架背景强大&#xff0c;历史悠久&#xff0c;其生态也比较齐全。但同时这些框架也并非十分完美&#xff0c;在前后台分离已成标配的互联网时代&#xff0c;这…