SCTF2019 writeups
TOC
题目文件:sctf2019.zip 。
pwn: easy_heap
靶机的glibc是2.23
。
安全防护
ex@Ex:~/sctf/easy_heap$ checksec easy_heap |
溢出点
off by one 漏洞。
unsigned __int64 __fastcall sub_E2D(__int64 a1, unsigned __int64 a2) |
分析
不能泄露libc地址,需要部分覆盖。
思路
- unlink
- unsorted bin attached
unlink
对index_1
进行unlink
,使得index_0
指针可控,实现任意地址写。
image_base_addr = Alloc(0x38) - 0x202068 # index 0 |
执行后:
pwndbg> pr |
unsorted bin attached
利用unsorted bin attached
将main_arena+88
写入到index_0
中,然后部分覆盖,将main_arena+88
覆盖为__malloc_hook
,在把mmap_addr
地址写入即可。
Fill(1, p64(0x100) + '\x68') |
执行后:
pwndbg> pr |
完整脚本
#!/usr/bin/python2 |
运行实例
ex@Ex:~/sctf/easy_heap$ python exp.py |
pwn: two_heap
靶机的glibc是2.26
。
安全防护
ex@Ex:~/sctf/two_heap$ checksec two_heap |
溢出点
main
中有明显的格式化字符串漏洞:
read_n(&v4, 11); |
delete
函数中存在double free
。
void delete() |
思路
- 泄露地址
- double free
泄露地址
利用格式化字符串漏洞泄露libc基地址,由于使用的是__printf_chk
函数,所以我们利用printf
的浮点特性来泄露rsp + 0x50
之后的值。
pwndbg> stack |
通过上面的调试发现,0x70
也就是第三个浮点参数那里可以泄露地址。
脚本
#!/usr/bin/python2 |
pwn: one_heap
靶机环境是glibc-2.27。
安全防护
ex@Ex:~/sctf/one_heap$ checksec one_heap |
溢出点
delete
函数中存在double free
漏洞。
void __cdecl delete() |
程序的难点在于可以free
的次数只有4次,而且没有明显的泄露点。
思路
- tcache perthread corruption
- attack stdout leak libc base
- hijack hook
tcache perthread corruption
每个线程通过一个tcache_perthread_struct线程本地变量保存tcache bin以及相关的chunk计数。如果我们能够修改tcache_perthread_struct这个结构体的内容,就可以完全控制malloc的内存分配。
tcache_perthread_struct保存在heap的头部,所以可以直接double free
后进行部分覆盖从而控制tcache_perthread_struct
。
New(0x68, '\n') |
调试结果如下:
pwndbg> tcachebins |
之后 free
掉 tcache_perthread_struct
,使其放入usorted bin
,然后tcache
上就会因为usorted bin
的 分配而被写上main_arena
的地址,在对main_arena
的地址进行部分覆盖,实现控制_IO_2_1_stdout_
。
New(0x68, '\xFF' * 0x40 + '\n') |
调试结果:
pwndbg> tcachebins |
attack stdout leak libc base
修改stdout
的_IO_write_base
来实现地址泄露,通过调试发现可以泄露出_IO_2_1_stdin_
的地址。从而计算出libc地址。
pwndbg> p stdout->_IO_write_base |
对应的脚本:
layout = [ |
完整脚本
总共需要两次部分覆盖,所以概率是1/256
。
#!/usr/bin/python2 |
运行实例:
ex@Ubuntu:~/test$ ./exp.sh ./exp.py |
RE:babyre
就是三个挑战
三维迷宫
反汇编可得迷宫:
***** |
方法:
w -5 |
所以路径是ddwwxxssxaxwaasayywwdd
。
字符处理
我们输入的字符将在loc_C22
函数进行处理,然后和sctf_9012
进行匹配。
.text:0000000000000ADE lea edi, aPlzTellMeThePa ; "plz tell me the password2:" |
调试发现loc_C22
是一个4字节向三字节映射的关系,进行爆破。
// gcc -fPIC -O3 -shared hook.c -c -o hook.o |
运行实例:
ex@Ex:~/sctf/babyre$ LD_PRELOAD=./hook.so ./babygame |
所以第二问是c2N0Zl85MTAy
。
可逆函数
分析发现第三问是一个可逆函数。
array[30] |
f(x)
函数依赖于x
。所以直接将公式倒置即可。
// gcc -fPIC -O3 -shared hook2.c -c -o hook2.o |
运行实例:
ex@Ex:~/sctf/babyre$ LD_PRELOAD=./hook2.so ./babygame |
所以第三问答案就是fl4g_is_s0_ug1y!
。
结果:
ex@Ex:~/sctf/babyre$ cat answer | ./babygame |