PassWordBox_ProVersion
1 | ➜ 桌面 ./pwdPro |
1 | pwdPro: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0cf87abb0c2c119db0081f9c5e07fd0f028a5480, for GNU/Linux 3.2.0, stripped |
64位,dynamically,全开
1 | GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release versi |
漏洞分析
1 | unsigned __int64 delete() |
UAF漏洞
入侵思路
本题目可以控制的东西很多,就是这个加密函数有点烦:
1 | __int64 __fastcall code(__int64 pwd, int size) |
- 解密函数和它一模一样
- 它是以8字节为单位进行加密的
- 异或加密比较好破解,但需要获取“randomkey”
1 | unsigned __int64 add() |
执行“申请模块”后会对数据进行一次加密,但同时也会泄露加密后的数据(仅限第一次),这就可以计算出“randomkey”了,然后 libc_base 和 heap_base 都可以泄露了:
1 | add(0,0x448,"\x00"*8) |
House Of Banana
本程序可以主动 exit ,并且申请的空间足够大,所以先尝试一下 House Of Banana
1 | pwndbg> distance &_rtld_global &(_rtld_global._dl_ns._ns_loaded->l_next->l_next->l_next) |
House Of Banana 的关键就是那个 largebin attack:
1 | unsortedbin /* fake _rtld_global结构体 */ |
largebin attack 发生在 chunk 从 unsortedbin 进入 largebins 的一瞬间,large chunk 会把“自己的chunk->head”写入“目标地址”(“chunk->BK_size”指向的地址,next_node)
完整exp:
1 | from pwn import* |
mp_.tcache_bins劫持 + Tcache attack
这里的 mp_.tcache_bins 的作用就相当于是 global max fast ,将其改成一个很大的地址之后,再次释放的堆块就会当作 tcache 来进行处理
1 | pwndbg> p &mp_.tcache_bins |
1 | pwndbg> p &mp_.tcache_bins |
前面部分和 House Of Banana 一样,只是换一下攻击对象就可以了
此后释放的 chunk 都会放入 tcache(小于mp_.tcache_bins)
1 | pwndbg> /* 在tcache_perthread_struct看到的信息(它的tcache_entry和main_arena很像) */ |
1 | Allocated chunk | PREV_INUSE |
因为 libc-2.31 的 tcache 中加了 key 来检测 Double free,所以这里直接攻击 tcache_entry
1 | pwndbg> /* tcache_entry(0x510) */ |
- 这里最好不要在 chunk7 中写入free_hook,因为 tcache_perthread_struct->count 会记录各个 tcachebin 中的 chunk 数量(其实也可以伪造 count,就是有点麻烦)
注意:这里我尝试使用“one_gadget”没有打通(可能是条件不符合)
完整exp:
1 | from pwn import * |
House Of Husk
在常规 House Of Husk 中,需要先攻击 global_max_fast
1 | pwndbg> p &global_max_fast |
1 | pwndbg> p &global_max_fast |
然后就是计算两个表的偏移:
1 | pwndbg> distance &__printf_function_table &main_arena |
1 | pwndbg> distance &__printf_arginfo_table &main_arena |
可惜的是,程序对 size 进行了限制,那么常规的 House Of Husk 就无法实施了(利用 main_arena 覆盖 __printf_function_table
和 __printf_arginfo_table
),但是可以用连续的 largebin attack 来代替这个过程
注意:libc-2.31版本下 largebin attack 的条件(必须小于 largebin 中所有的 chunk)
1 | pwndbg> p __printf_arginfo_table |
1 | pwndbg> p __printf_function_table |
当我执行到最后一步时,悲剧还是发生了:
- 所有 one_gadget 的条件都不满足
- Rdi 指向栈上的一个地址,导致 system 的参数不可控
看来 House Of Husk 打不通这个题,完整exp:
1 | from pwn import * |
小结:
本题目很灵活,可以用多种方法求解,于是我把学过的技术都用了一遍(House Of Pig 还没有搞过)
- House Of Banana:
- 本地还好,不过远程需要爆破 ld_base
- mp_.tcache_bins劫持 + Tcache attack:
- 最简单的办法,复习了一下 tcache attack
- House Of Husk:
- 好不容易成功进行了两次 largebin attack,最后还是因为各种原因没有打出来
- 两次 largebin attack 真的有点不容易,关键就是在第一次攻击后,让被修改的那个 large chunk 复原,然后才开始第二次攻击
- 因为 printf 里面会控制 Rdi 寄存器,所以只能考虑用“one_gadget”,但是 libc-2.31 的“one_gadget” 条件苛刻,所以就失败了
以后会优先考虑 mp_.tcache_bins劫持,然后才是 House Of Husk,House Of Banana