记录下比赛当时解出来的和后来复现的题目,队内web师傅太顶了!!!
babypwn
read_n
函数输入的size为0时可以溢出show
函数没有检查idx,可以用来泄露libc地址
用堆溢出先在main_arena
里构造出合法的size,在分配到main_arena
上,修改top_chunk
,在用堆溢出劫持__free_hook
1 | from pwn import * |
ezshell
格式化字符串,劫持fini_array
原先用这两个gadget本地打通了:
1 | 0x0000000000424a4a # xchg eax,ebp; ret |
但是由于要一次性发送0x2000字节的数据,好像远程不会一次性接受这么长的数据
后面换了个思路,用:
1 | # 0x0000000000419845: mov rdi, rbp; call qword ptr [rbp + 0x20] ## 0x6ed0c0+0x20 |
然后在rbp+0x20
处写入0x400bd6
,跳转到0x400bd6
成功劫持程序,最后打开flag的fd是5
打通了,脚本就没改了,生怕哪里又出错,好像也没必要泄露
1 | from pwn import * |
childshell
这题和ezshell
很像,但是程序在main函数返回后会马上调用_exit
,这个函数直接就用syscall来退出,所以改思路为劫持stdout的vtable来劫持程序流程,劫持了程序流程之后,我们可以成功执行shellcode,但是程序被chroot了:
1 | v10 = _opendir("./sandbox"); |
比赛的时候死活逃不出去,看了下wp,好像mkdir(".42"),chroot(".42"),chroot("../../../../../../")
这样就逃出去了,也不知道为啥,想起上次也是这样,直接chdir("../../../../../../../")
就逃出去了,本地是不行的,打远程却是可以
这个exp就到能执行shellcode这一步,后面的看Nu1L大佬们的wp把:
1 | from pwn import * |
paperprinter
这题很像2019年*ctf的heapmaster,但是又有点不一样,我们只有一次malloc
的机会,还有一次就是选项4的strdup也会调用malloc,但是调用完之后就退出了,应该是拿来最后劫持程序流程的,比赛的时候没啥思路,赛后看了chamd5
团队的wp,我去,太牛逼了
用的house of orange的思路,程序一开始会给sleep函数的后面几个字节:
1 | printf("0x%lx\n", ((unsigned __int64)&sleep & 0xFFF00) >> 8); |
这样后面爆破的几率提高到了1/16,wp里的思路是一开始free两个0x90和一个0x140大小的堆块,然后用那仅有的一次malloc机会把0x140大小的堆块malloc掉,这样前面两个0x90的堆块就会被置入smallbin
,堆块的bk指针就会是libc的地址,接着在释放一个堆块进入到unsortedbin
,修改其bk指针指向__IO_list_all
,最后用strdup来触发,在触发的时候的堆布局:
1 | LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA |
其中:
1 | pwndbg> telescope 0x49017000 30 |
其中rbx指向的就是我们伪造的io结构,其0xd8的偏移,巧妙的利用了smallbin的bk指针,使其指向0x490170e0
,而0x490170e0+0x18
的位置又是刚刚好另一个chunk的bk指针,用部分写改为了system
,太牛逼了
exp还是看chamd5大佬的wp把