HSCTF2019
前言
emm在ctftime上第一次见到简单的比赛题,后来才知道是High School CTF。不过做了所有的pwn,还是记录一下,最后一个题要总结一下。
nc
nc addr 即可
return to sender
最简单的栈溢出,system(“/bin/sh”)给了,直接return过去
1 | #coding=utf-8 |
combo chain lite
先用给的system地址计算libc基址,算出/bin/sh的字符串地址,用csu rop将syetm_addr+bin_sh_addr写到bss段上,调用bss_base(bss_base+8)即可拿shell
1 | #coding=utf-8 |
combo chain
这个题的rop很巧妙,不用csu,首先pop_rdi存储bss地址,后面跟着gets_plt,调用gets(bss_addr),之后再pop_rdi,call printf(“%3$p”)来泄露地址,最后跳到main执行下一次ROP攻击。在第一次的过程中使用’\n’分隔符输入了%3$p。
第二次pop_rdi将”/bin/sh”的地址写入rdi,之后调用sysem(“/bin/sh”)得到shell
ret 后面可以跟plt(plt里还有call)或者实际的地址
1 | #coding=utf-8 |
story time
先用write泄露出lib基址,之后的做法同combo chain lite
1 | #coding=utf-8 |
bit
这个题给了4次任意地址修改1bit的机会,第一次泄露出puts的地址来计算libc地址,第二次通过environ变量可以得到栈地址,此时i = 0x10,将这个1移位到最高位使得i成为负数,即可任意次数地修改。修改exit_got的地址为shell_addr即可
1 | #coding=utf-8 |
byte
题目里有flag函数,查看调用,发现是在循环那里有个隐藏的触发条件,即i>1且ebp-0x8e的值为0。main函数里有zero(address),用printf泄露出栈地址,再将ebp-0x8e作为输入,即可满足条件执行flag函数
1 | #coding=utf-8 |
caesars revenge
这道题使用凯撒密码对用户输入进行编码,最后printf漏洞,先将puts_got覆写为main函数地址,使得可以多次利用漏洞,之后依次泄露libc和stack的地址。最后将setresgid_got覆写为shell_addr。
1 | #coding=utf-8 |
aria-writer
存在double free的漏洞,且有一个secret的选项可以输出name的值,先在name里构造0x90大小的fake_chunk,用double free+3次malloc修改0x90对应的tcache数量为0xff,从而free这个fake chunk的时候直接把其放入unsorted bin,再利用secret去泄露Libc,修改malloc_hook到gadgets即可。
1 | #coding=utf-8 |
aria-writer-v3
这个题目是上一道的加强版,libc 2.27,依然有double free,但是没有泄露函数,观察之后发现bss段上存储了stdout结构体的地址,这里直接double free再分配到bss这个地址上,再次分配即可分配stdout,修改其内容即可泄露libc。之后的操作同之前一样。
1 | #coding=utf-8 |
hard-heap
前言
这题是之前某个CTF题的变种,第一次学到这种利用方式,可以绕过size的要求。
程序逻辑
程序有Malloc、Free和Show三个功能。
在Malloc中,最多可以分配20个堆块。size[0]存储用户输入的size,要求小于等于0x48,size[1]存储canary防止溢出。全局数组0x202060[index]存储chunk地址,读取size[0]-1大小的数据进入chunk。
Show里对Index做了检查,没有对数组内容做检查,存在UAF。
Free里有double free
漏洞利用
这题开始我以为是2.27的题,还是蛮好做的,到2.23因为malloc的size会有检查,导致之前的思路完全不通。这里用的知识是fast bin和top chunk的地址会存储在main_arena里,如果我们可以修改main_arena,就可以控制fast bin和top chunk的值
观察main_arena的内容,可以看到main_arena+8+5刚好可以凑一个大小为0x56的fake chunk出来。
首先,我们利用double free泄露出heap基址。在某个chunk中构造fake chunk,用刚才的double free分配到这个fake chunk,进而通过输入覆写下面的chunk的prev_size和size(0x91)。将其释放之后即可泄露libc。
程序开了地址随机化,因此heap的第一个字节为0x55或0x56,我们需要绕过检查,因此要等0x56的情况出现。我们将之前申请的0x30的chunk释放,main_arena的对应地址出现了值,再用0x48的double free分配到这个fake chunk。之后我们修改fastbins[0x50]的值为main_arena+0x20,fastbins[0x60]的值为0x51。Malloc(0x48)即可分配到main_arena+0x20的大小为0x50的块,input改掉top_chunk为malloc_hook附近的值(这里为malloc_hook-0x15),再分配一个块即可覆写malloc_hook为shell_addr。
exp.py
因为写了2.27的,就顺便也发出来了
1 | #coding=utf-8 |
And 2.23
1 | #coding=utf-8 |