CTF权威指南 笔记 -第二章二进制文件- 2.4 -动态链接
目录
静态文件的缺点
动态链接
位置无关代码
延迟绑定
_dl_runtime_reslove 函数定义
深入审视
静态文件的缺点
随着可执行文件的增加 静态链接带来的浪费空间问题就会愈发严重
如果大部分可执行文件都需要glibc 那么在链接的时候就需要把 libc.a链接进去
如果一个libc.a为5M 那么100就是 5G 例如下面的左边
静态链接的一个很明显的缺点 对标准函数进行一点点 的修改 都需要重新编译整个源文件
动态链接
如果不把系统库和自己编写的代码链接到一个可执行文件 而是分割到两个独立的模块 等到程序进行运行了 再进行链接 这样就可以节省硬盘空间 并且在内存中一个系统库可以被多个程序使用 这样还会节省物理空间
在这种 运行和加载的时候 在内存中完成链接的过程叫做动态链接这些用于动态链接的系统库 我们叫做共享库 或者 共享对象这个过程我们通过 动态链接器完成
例如上图的右边
func1.elf func2.elf 不再包含单独的testLib.o
当程序运行func1.ELF的时候 系统将func1.o和依赖的testLib.o载入内存中
进行动态链接
完成后 系统将控制器交给程序入口点 程序开始执行后面func2.ELF开始执行 因为内存中已经有testLib.o 不需要重复加载 所以直接链接即可
继续使用之前静态链接的例子
这里我们把func.c编译为共享库
gcc -shared -fpic -o func.so func.c-shared 生成共享库
-fpic 生成和位置无关的代码
gcc -fno-stack-protector -o func.ELF2 main.c ./func.somain.c 和func.so进行动态链接
生成 func.ELF2
我们查看 func.ELF2的链接格式
查看 汇编格式
objdump -d -M intel --section=.text func.ELF2 |grep -A 11 "<main>"
这里我们就能发现 call 后面跟上了偏移量 地址等
位置无关代码
可以加载而无需重定位的代码就是位置无关代码PIC
通过gcc -fpic就可以生成位置无关代码
一个程序的代码段和数据段的相对位置都是保持不变的 所以指令和变量之间的距离是一个运行时常量 与绝对内存地址无关
于是就有了全局偏移量表 GOT
GOT表位于 数据段的开头
用于保存全局变量和库函数的引用每个条目占8字节 在加载时会重定位并且填入符号的绝对地址
为了RELRO保护
GOT 被拆分为 .got 和.got.plt.got 用于保存全局变量引用 写入内存为只读 不需要延迟绑定.got.plt 用于保存函数引用 具有读写权限 需要延迟绑定
我们可以看看func.o的情况
objdump -h func.so
readelf -r func.so| grep tmp
R_X86_64_GLOB_DAT 表示 动态链接器找到 tmp的值 存入0x3fd8
我们使用汇编可以看看代码
objdump -d -M intel --section=.text func.so |grep -A 20 "<func>"
这里我们能发现 调用函数 rip+0x2ead的地方 rip为下一条指令的地址 这里是 112b
112b + 2ead =3fd8
所以汇编我们能发现调用函数就是指向 实际地址 3fd8
延迟绑定
如果动态链接是要通过动态链接器加载进行 如果要重定位的符号(库函数)多了之后 肯定会影响性能
延迟绑定就是为了解决这个问题
延迟绑定的思想就是如果函数是第一次被调用 动态链接器才进行符号查找 重定位的操作
如果没有调用就不进行绑定
ELF文件通过 PLT和GOT的配合来实现延迟绑定
每一个被调用的库函数都有一组 GOT 和PLT
位于代码段.got.plt节 是一个PLT数组 每一个条目占16字节
PLT[0] 跳转到动态链接器
PLT[1] 调用系统启动函数 _libc_start_main()函数
main函数就是从里面进行调用PLT[2] 开始就被调用的各个函数条目
位于数据段.got.plt节的GOT也是一个数组 每条占8字节
GOT[0]和GOT[1]
包含着动态链接库解析函数地址所需要的两个地址 (dynamic和relor条目)GOT[2] 是动态链接器 ld-linux.so的入口点 GOT[3] 开始就是各个条目这些条目默认指向对应PLT条目的第二条指令
绑定后才会修改函数的实际地址
我们使用例子说明
#include<stdio.h>
void print_bananer(){printf("Welcome got and plt");
}
int main(void){print_bananer();return 0;
}
进行编译
gcc -Wall -g -o test.o -c test.c -m32gcc -o test test.o -m32 -no-pie
我们直接通过反汇编进行查看
objdump -d test
我们先看到main函数
看到call
11d8: e8 c0 ff ff ff call 119d <print_bananer>
这里地址送11d8
e8为call的机器码c0ffffff为printf_bananer的地址 这里第一次调用 不知道地址 所以用这个代替119d是去的地址 指向 print_bananer函数
我们去看119d的地址
发现119d是print_bananer的地址
然后我们看到里面的关键调用
11ba: e8 91 fe ff ff call 1050 <printf@plt>
11ba地址
e8 ->call
91 fe ff ff 为函数地址
我们去看看1050地址
我们发现是
printf.plt地址 就是
然后我们进行代码审计
这里我们可以通过另一个编译 让pie停止
gcc -o test test.o -m32 -no-pie
然后重新进行查看
objdump -d test
发现一个地址 我们使用gdb进行查看这个地址
gdb test
b mianr
x/x 0x804c010
这里是printf的got表
这里得到另一个地址 我们回去反汇编看看
发现就是下一条 push 0x8这个地址 所以第一个代码是返回 printf@plt的push
然后执行完push
又进行跳转
这里有一个地址 我们去看看
发现是main的共享库文件-0x10偏移量 的地址
然后进行push 0x804c004
又跳到0x804c008
gdb test
x/x 0x804c008
我们发现 这里是0
因为第一次执行 还没有找到printf函数
我们让他执行起来
b main
r
x/x 0x804c008
发现得到了地址 这个地址就是 printf的地址
0x804c008这个的地址 其实就是指向 _dl_runtime_resolve函数
这个函数在动态链接里有着很重要的作用
计算出地址 更新got表等
我们现在来梳理一下
printf.plt ->printf.got.plt -> printf.plt->公共plt->_dl_runtime_reslove函数
这就是printf函数调用过程
这里我们还需要知道
_dl_runtime_reslove 怎么找到printf函数地址
这个是因为在之前我们执行printf@plt的时候 push了0x8
这个就类似于 printf的id 让 _dl_runtime_reslove去找这个id的函数
_dl_runtime_reslove 函数定义
_dl_runtime_resolve(link_map_obj, reloc_index)
reloc_index 这个参数是来寻找 .rel.plt表的 这个表是ELF rel结构体
这个结构体为
typedef struct
{ELF64_Addr r_offset ELF64_Xword r_info
}ELF64_Rel
r_offset是用于保存 需要进行重定位和重定位写入内存的位置
r_info的高三位是保存 符号在.dynsym里的下标
通过上面的图像 我们可以发现 r_info又指向 .dynsym中的ELF_sym结构体
这个结构体的内容为
typedef struct
{ELF64_Word st_name; 符号名称在字符串表中的偏移量unsigned char st_info; 包含符号类型和捆绑信息unsigned char st_other; 保留位ELF64_Half st_shndx; 指向和该符号关联的段/节索引值ELF64_Addr st_value; 该符号的值 就是地址ELF64_Xword st_size; 符号所占的字节
}ELF64_Sym
st_value和st_name为重要成员
st_value是符号导出时存放的虚拟地址 不能导出为null
st_name 是相对.dynstr的偏移
然后就是去.dynstr找函数
这个表中存放着 函数地址
所以我们从函数开始导入开始看
程序导入函数 .dynstr中增加一个函数名字符串
在.dynsym中增加一个ELF Sym的结构体 其中 S_name指向 .dynstr
然后又在.rel.plt中增加一个 ELF Rel结构体 其中 r_info指向 .dynsym的 ELF Sym结构体
最后 r_offset 构成 GOT表 存储在 .plt.got段的地址上
这样 我们函数就可以在程序的.plt.got中了
在我们明白这个了 我们重新对test进行审视
深入审视
这里第一个跳转 是无条件跳转到 GOT[0]处
但是GOT[0]在初始化的时候 默认指向 plt的第二条 就是PLT[1]->push 0x8
然后进行跳转到公共的PLT 然后去找_dl_runtime_reslove函数
这里的执行就是
无条件跳转到 xxx.got 把link_map_obj压入栈内
然后开始调回 plt 然后压入 函数id push 0x8
然后进行跳转去找_dl_runtime_reslove函数 并且执行
这样就实现了 函数通过动态链接寻找
相关文章:
CTF权威指南 笔记 -第二章二进制文件- 2.4 -动态链接
目录 静态文件的缺点 动态链接 位置无关代码 延迟绑定 _dl_runtime_reslove 函数定义 深入审视 静态文件的缺点 随着可执行文件的增加 静态链接带来的浪费空间问题就会愈发严重 如果大部分可执行文件都需要glibc 那么在链接的时候就需要把 libc.a链接进去 如果一个libc…...
C++:计算机操作系统:多线程:高并发中的线程
高并发中的线程 一切要从CPU说起PC 程序计数器从CPU到操作系统从进程到线程 从这篇开始,我将会开启高性能,高并发系列,本篇是给系列的开篇,主要关注 多线程以及线程池。 一切要从CPU说起 你可能会有疑问,讲多线程为何…...
大数据Doris(十一):Aggregate 数据模型
文章目录 Aggregate 数据模型 一、导入数据聚合 二、保留明细数据...
osg::Drawable类通过setDrawCallback函数设置回调函数的说明
osg::Drawable类可以通过该类的setDrawCallback函数设置回调函数类对象。被设置的回调类对象必须从osg::Drawable::DrawCallback类派生,并重写drawImplementation函数,以实现自己特定的需求。这个回调函数在每次帧事件中都会被调用(如:在帧的…...
Python基础合集 练习17(类与对象)
class Dog: pass papiDog() print(papi) print(type(papi)) 构建方法 创建类过后可以定义一个特殊的方法。在python中构建方法是__init__(),init()必须包含一个self参数 class pig(): #def__init__(self) -> None: print(‘你好’) pipgpig() 属性和方法 cl…...
再多猜一次就爆炸(小黑子误入)
目录 猜数字游戏 游戏设计思路 1.电脑随机生成一个数 2.猜数字 3.输入我是ikun,泰裤辣! 否则电脑将在一分钟后关机 游戏运行效果 源码 代码分析 代码实现关键语句 strcmp() rand()与srand() 时间戳time() 寄语 猜数字游戏 游戏设计思路 1.电脑随机生…...
图像超分辨率简单介绍
文章目录 图像超分辨率简单介绍什么是图像超分辨率?常见的图像超分辨率算法插值算法基于边缘的图像重建算法局部线性嵌入(LLE)拉普拉斯正则化 基于深度学习的超分辨率算法超分辨率CNN超分辨率GAN 步骤1. 收集数据2. 选择算法3. 训练模型4. 测…...
【Liunx】进程的程序替换——自定义编写极简版shell
目录 进程程序替换[1~5]1.程序替换的接口(加载器)2.什么是程序替换?3.进程替换的原理4.引入多进程5.系列程序替换接口的详细解析(重点!) 自定义编写一个极简版shell[6~8]6.完成命令行提示符7.获取输入的命令…...
c++标准模板(STL)(std::array)(三)
定义于头文件 <array> template< class T, std::size_t N > struct array;(C11 起 std::array 是封装固定大小数组的容器。 此容器是一个聚合类型,其语义等同于保有一个 C 风格数组 T[N] 作为其唯一非静态数据成员的结构体。不同于 C 风格数组…...
c#笔记-创建一个项目
创建一个项目 创建控制台程序 在你安装完成Visual Studio后打开它,你会的到一个启动窗口 点击创建新项目,选择右上角c#的没有Framework的控制台应用。 项目名称,位置自己随意。 目标框架选择NET7.0。 项目创建完成后应该你的界面应该类似…...
Photoshop如何使用图像调色之实例演示?
文章目录 0.引言1.将一张偏冷调的图像调整成暖调2.将图像调整成不同季节色彩倾向3.变换花朵的颜色4.创建人像轮廓风景5.修饰蓝天白云6.调换花草颜色 0.引言 因科研等多场景需要进行绘图处理,笔者对PS进行了学习,本文通过《Photoshop2021入门教程》及其配…...
IDEA中使用Git提交代码提示:您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。
IDEA中使用Git提交代码提示:您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。 问题背景: 在IDEA中,使用Git提交代码到远程仓库时,结果弹出一个警告窗口 问题原因: …...
ArduPilot之开源代码LibrarySketches设计
ArduPilot之开源代码Library&Sketches设计 1. 简介1.1 Core libraries1.2 Sensor libraries1.3 Other libraries 2. 源由3. Library Sketches设计3.1 设计框架3.2 Example Sketches3.3 AP_Common Sketches3.3.1 配置sitl环境3.3.2 编译AP_Common3.3.3 运行AP_Common3.3.4 代…...
第一章:概述
1,因特网概述 1.网络、互联网和英特网 网络(Network)由若干结点(Node)和连接这些结点的链路(Link)组成。 多个网络还可以通过路由器互连起来,这样就构成了一个覆盖范围更大的网络,即互联网(或互连网)。因此,互联网是“网络的网络…...
MySQL --- DDL图形化工具表结构操作
一. 图形化工具 1. 介绍 前面我们讲解了DDL中关于数据库操作的SQL语句,在我们编写这些SQL时,都是在命令行当中完成的。大家在练习的时候应该也感受到了,在命令行当中来敲这些SQL语句很不方便,主要的原因有以下 3 点:…...
归一化处理(2023寒假每日一题 14)
在机器学习中,对数据进行归一化处理是一种常用的技术。 将数据从各种各样分布调整为平均值为 0 0 0、方差为 1 1 1 的标准分布,在很多情况下都可以有效地加速模型的训练。 这里假定需要处理的数据为 n n n 个整数 a 1 , a 2 , ⋯ , a n a_1,a_2,⋯…...
无公网IP,外网远程连接MySQL数据库
哈喽~大家好,这篇来看看无公网IP,外网远程连接MySQL数据库。 文章目录 前言1. 检查mysql安装状态2. 安装配置cpolar内网穿透3. 创建tcp隧道,映射3306端口4. 公网远程连接4.1 图形化界面4.2 使用命令行远程连接 5. 配置固定tcp端口地址5.1 保留…...
OJ刷题 第十四篇(递归较多)
23204 - 进制转换 时间限制 : 1 秒 内存限制 : 128 MB 将一个10进制数x(1 < x < 100,000,000)转换成m进制数(2< m < 16) 。分别用 ABCDEF表示10以上的数字。 输入 x m (1 < x < 100,000,000, 2< m < 16) 输出 m进制数 样例 输入 31 16 输出 1F 答…...
FileZilla读取目录列表失败(vsftpd被动模式passive mode部署不正确)
文章目录 现象问题原因解决方法临时解决(将默认连接方式改成主动模式)从根本解决(正确部署vsftpd的被动模式) 现象 用FileZilla快速连接vsftpd服务器时,提示读取目录列表失败 问题原因 是我vsftpd服务端的被动模式没…...
【Java面试八股文】数据库篇
导航: 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线MySQL高级篇设计模式牛客面试题 目录 请你说说MySQL索引,以及它们的好处和坏处 请你说说MySQL的索引是什么结构,为什么不用哈希表 请你说说数据库索引的底…...
Android Glide加载图片、网络监听、设置资源监听
再搞事情之前首先创建一个项目,就命名为GlideDemo吧。 一、项目配置 创建好之后,在app模块下build.gradle的dependencies闭包中添加如下依赖: //glide//glideimplementation com.github.bumptech.glide:glide:4.11.0annotationProcess…...
等保定级报告模版
等保定级怎么做_luozhonghua2000的博客-CSDN博客 上篇给大家说清楚了,等保定级怎么做,但在日常工作中,需要向上级或甲方输出定级报告,这篇我降弄个模版供大家参考。 信息系统安全等级保护定级报告 XX 平台系统描述 (一) 2023年5月,XX 正式上线,XX 隶属于深圳 XX 科技…...
计算机组成原理4.2.2汉明码
编码的最小距离 奇校验和偶校验 看1的个数是奇数 还是偶数 汉明码 汉明码的配置 根据不等式,确定增添几位,根据指数放置增添位 汉明码的检错 分不同检测小组 分组规则:哪位为’1‘就是哪组元素。 1号位为‘1’的都是第一组元素&#…...
JavaScript全解析——本地存储的概念、用法详解
本地存储概念: 就是浏览器给我们提供的可以让我们在浏览器上保存一些数据 常用的本地存储 localStorage sessionStorage localStorage 特点: 1.长期存储,除非手动删除否则会一直保存在浏览器中,清除缓存或者卸载浏览器也就没有了 2.可以跨页面通讯,…...
对象浅拷贝的5种方式
参考原文:浅拷贝的五种实现方式 - 掘金 (juejin.cn) 哈喽 大家好啊 最近发现自己对对象都不是很熟练,特别是涉及到一些复制,深浅拷贝的东西 1.Object.assign 首先 我们创建一个空对象obj1 然后创建一个对象obj2 用object.assign(目标对象,…...
Java每日一练(20230504)
目录 1. 位1的个数 🌟 2. 移除元素 🌟 3. 验证二叉搜索树 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 位1的个数 编写一个…...
【深度学习】计算机视觉(13)——模型评价及结果记录
1 Tensorboard怎么解读? 因为意识到tensorboard的使用远不止画个图放个图片那么简单,所以这里总结一些关键知识的笔记。由于时间问题,我先学习目前使用最多的功能,大部分源码都包含summary的具体使用,基本不需要自己修…...
项目经理在项目中是什么角色?
有人说,项目经理就是一个求人的差事,你是在求人帮你做事。 有人说,项目经理就是一个与人扯皮的差事,你要不断的与开发、产品、测试等之间沟通、协调。 确实,在做项目的时候,有的人是为了完成功能&#x…...
【技术分享】防止根据IP查域名,防止源站IP泄露
有的人设置了禁止 IP 访问网站,但是别人用 https://ip 的形式,会跳到你服务器所绑定的一个域名网站上 直接通过 https://IP, 访问网站,会出现“您的连接不是私密连接”,然后点高级,会出现“继续前往 IP”,…...
Baumer工业相机堡盟相机如何使用偏振功能(偏振相机优点和行业应用)(C#)
项目场景: Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外࿰…...
wordpress弹出层插件/品牌推广运营策划方案
1、题目描述 给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。 如果数组元素个数小于 2,则返回 0。 示例 1: 输入: [3,6,9,1] 输出: 3 解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。…...
做p2p网站的公司/东莞做一个企业网站
知识章节参考:【六】Java面向对象...
企业信息年报系统/seo网站推广招聘
在国内7个城市启动建设后,中国人工智能技术受邀参与国外的城市治理。 1月29日,马来西亚数字经济发展机构(MDEC)和吉隆坡市政厅(DBKL)联合宣布引入阿里云ET城市大脑,人工智能将全面应用到马来西亚…...
网站建站对象/快速搭建网站的工具
K-means聚类算法(事先数据并没有类别之分!所有的数据都是一样的)1、概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成…...
南山做网站多少钱/可以进入任何网站的浏览器
上一篇的内容中,我们已经基本上完成了一个简单的项目,现在我们要学习Django中MVT中M的部分 -- 模型模型准确的描述了一条数据,Django使用ORM(对象关系映射)技术来将一个python类映射为数据库的一张表,而类中的每个类属性映射为表中…...
个人网站icp备案网/百度一下点击搜索
题目背景 学生在我们USACO的竞赛中的得分越多我们越高兴。 我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助 题目描述 我们可以从几个种类中选取竞赛的题目,这里的一个"种类"是指一个竞赛题目的集合,解决集合中的题目需要相同多的时间并且能得到相同…...