L3Hctf 2025 heack_revenge 复现
checksec
1 | |
IDA
main
1 | |
game
1 | |
其中 attack_training 和 hp_training 会让 v2,也就是 [rbp-0x28] 增加 0x10 和 0x100
fight_dragon
1 | |
跟上面一题相比,栈溢出变了,只能溢出一次且修改一个字节
寻找0x18附近的gadgets
发现game函数开头有许多奇怪的数字
1 | |
将其转换为数据

将 0x186a 处转换为代码,发现有一个 gadgets 可以用

得到了一个 pop rbp 的 gadget
note_system
1 | |
本身不存在什么漏洞
不过这里传进来的参数也就是 game 里的 s(栈上)这里将 s 作为 note_list 其中 index 可以由我们自己来输入
漏洞
我们可以使用栈溢出,将 rbp 改为 s 的地址,也就是 chunk[0] 的地址。然后可以利用 attack/hp_training 来使上面的数据变大,如果我们刚好让这个地址为一个 chunk 的 size ,我们就可以将该 chunk 的 size 变为很大,然后 free 掉,再次 malloc 就可以让 fd、bk 进入到一个已分配的 chunk,就可以 view 来泄露,然后由于 rbp 已经被我们控制,我们可以往 rbp 后面写上 one_gadget
- 首先构造堆块
1 | |
其作用都写在后面了
这样构造完 pop rbp 后 [rbp-0x28] 就是 chunk1 的size了,就可以增加
此时的堆块

- 然后让该返回地址为 pop rbp,执行pop rbp 让 rbp 为 chunk0 地址
1 | |
执行完后

可以看到被改成了 chunk0 地址
- 然后把chunk(1,4)分配回来,回到 game 函数来执行 hp/attach_training 来增加 chunk1 的 size
1 | |

可以看到 chunk1 的 size 被我们增加到了 0x550
- 然后 free(1) 后 malloc(0x30) 就可以让 fd bk 进入到 chunk4 里面,就可以 view(4) 来泄露 libcbase
- 接着修改 rbp+8 为 ogg
1 | |
回到 game 函数里,输入一个非法的执行 sad 后面的 ret 就可以执行 one_gadget 了(其他函数里执行 ret 不会执行one_gadget,只有回到 game 里 rbp 才是直接 chunk0,此时 ret 才可以 one_gadget)
官方exp
1 | |