
L3HCTF 2025 - heack

文件属性
属性 | 值 |
---|---|
Arch | amd64 |
RELRO | Full |
Canary | on |
NX | on |
PIE | on |
strip | no |
libc | 2.39-0ubuntu8.4 |
解题思路
程序里有一个很明显的栈溢出在fight_dragon
中,但是没有信息,无法直接溢出;
而且返回以后直接exit(0)
了,我们必须覆写返回地址。
观察到game
函数里有许多printf("%lu", ...)
形式的调用,而在我们返回时,
rsi正好是_IO_2_1_stdout_+131
,那么只要我们能跳转到那里,就能泄露libc,
从而实现构造rop链。注意到在溢出时是一个一个字节写入的,而索引放在比缓冲区高的地方,
因此只需要将索引覆盖为返回地址的偏移,我们就可以直接操作返回地址而跳过canary。
原来为了避免爆破,选择跳转到printf("Data: %d\n", ...)
泄露libc,没想到由于%d
只能泄露32位,我们仍然需要爆8位(0x7f?? 或者12位 0x7??? ,取决于内核选项),
相比其跳转到有%lu
的地方,反而白白地增添了爆破的时间,有点得不偿失了说是。
通过爆破4位,我们可以跳转到上述的地方,然后再构造system("/bin/sh")
就可以开shell。
EXPLOIT
1 | from pwn import * |
题外话:丢失的9位ASLR
在和 hkbin 聊爆破几位的时候,猛然发现原来Arch是需要爆12位的,结果现在又变回了8位,
blame一下core/linux
的config记录,发现这个安全措施是在去年的commit中引入的,
然后到了一个月前又把这个操作回滚了,
有个专门的issue讨论这个事,
基本上意思就是遵循上游的原始设定,因为这个选项是开在 CONFIG_EXPERT 一节的,
很多开发者会按照默认配置写代码,然后就出现了libasan段错误的情况,因此就选择回滚默认配置了。
如果为了安全,可以选择linux_hardened
。
issue中还提到了一个有意思的东西, 就是我们打比赛的时候,有时候泄露libc会发现,不只是最后12位是0,而是最后21位都是0。 这其实是因为一些内核的优化,像libc这样超过2MiB的文件,在映射到内存中时,就会使用 Huge Page,导致需要使用21位的对齐,而非常规页的12位对齐,这直接导致了9位ASLR的丢失。 作为补偿,有些发行版设置了32位的mmap随机化,通过增加8位随机来对抗这一特性, 然而Arch竟然回到了28位随机化的默认配置,让人有点匪夷所思。
参考
- 标题: L3HCTF 2025 - heack
- 作者: RocketDev
- 创建于 : 2025-07-18 13:57:00
- 更新于 : 2025-07-18 23:32:00
- 链接: https://rocketma.dev/2025/07/18/heack/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。