Mini L 2024 小记
♿
Ottoshop ♿
出这个题的第一想法就是出一个 shit 一点的签到题, 最开始想的签到题的想法是无 leak , 就是我不给你输出函数, 但是给你一次溢出的机会, 因为去年 miniL 2023 的 twins 给的印象比较深.
实际上实现一下完全没什么难度, 思路大概可以看一下我博客上的复现.
然后当时的想法是把 twins 给 revenge 一下, 做成 orw + 需要多读一次的那种, 但是实际上也就是需要多调, 也没什么难度, 后来再想就是我 close 1 和 2 , 让你去走 socket sendfile write 的路线, 这其实难度也不大, 只是有一种在锦上添花 (塞 shit) 的感觉, 只要过了无 leak 这一关后续都是一调就出的东西.
想法有了和几个出题人商量一下, 大伙觉得这个不一定算签到题的范畴, 思考难度还是比较高的, 于是我直接跑路, 寻思面向栈上的 trick 出个签到, 于是就有了这个 scanf 绕 canary 的题.
最开始的想法是想些办法做一个迁移 + 绕 canary , 但是实际上做起来发现好像思考成本有点过高了, 想这么结合做个签到题也不现实, 于是我想了想, 把迁移这个点丢了吧, 换了一个更简单的下标越界.
但是下标越界高低得有个载体, 然后就不知道怎么想到的写个菜单的形式了.
于是我把洞按照菜单的逻辑放在了 2 个地方, 一个是在购买的时候检查不严密, 写负数下标即可低地址修改全局变量, 修改 money 这个值, 一个是输入 666 之后会开放购买 golden ♿ , 这里面会允许溢出, 但是开了 canary , scanf输入正负号绕过即可修改返回地址.
那这样大体逻辑就差不多了, 但是只放这么一点东西是不是又有点过于签到了呢 😄
于是开始塞 shit , 大概塞了这么几个 shit :
-
写了一堆狗屎函数, 大概是 100 个, 其中夹杂了一个真的后门函数, 目的就是不让你轻易找到那个后门(
-
后门函数是
execve("/bin/sh")
, 但是我又不能让你直接在 got 表里面看到后门, 于是改成内联汇编的形式, 采用系统调用的形式来做后门, 然后为了防止找到/bin/sh
👴还加了个异或加密, 源码大概长这样:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void o77oOtTo0T70()
{
char *a = flag2;
if (strcmp(a, "otto") == 0) {
for(int i = 0;flag1[i];i++)
flag1[i]^=0xff;
asm volatile(
"mov %rsi,0\n"
"mov %rdx,0\n"
"lea %rax,flag1\n"
"mov %rdi,%rax\n"
"mov %rax,59\n"
"syscall\n"
);
}
} -
然后还在 666 的那个分支那里放了个假的后门, 一个溢出, 但是不给你 canary 估计你也没得用 😄
于是一个塞了 shit 的签到题就出来了, 考点就是 scanf 的 trick 和下标越界.
说下做法, 找后门函数这一块我的预期是你要是有办法就快速找一下, 比如说你可以 CTRL + s 去 data 段里面能看到个 flag1 , 然后交叉引用一下立马就能找到后门函数, 如果你没这样也无所谓, 就 100 个垃圾函数, 翻就完了(
找到后门看到个 execve 的系统调用, 调一下就知道是 shell , 然后如我上面所说, 下标改 money 改 otto , 然后进到 666 分支, 再转回 golden 直接覆盖返回地址即可.
exp:
1 |
|
随便写写就好了.
解题情况和我的预期差不多, 懂 trick 的人随手秒了, 然后几个 23 来做题的也在 get 知识点后很快出了, 挺好.