
陇剑杯 2025 初赛 - MagicBox

第一次在大型比赛中拿一血,纪念一下😋
某用户在自定义硬件上运行了一份程序, 该程序怀疑有后门序列
题解
逆向 SOC_run_sim
,可以看到主项目是由 https://github.com/Nambers/0dMIPS
派生出来的,从中可以找到项目的使用方法。和分发的源码对比,不难发现多了 magic 指令,
当向魔法地址范围写入内容时,会取出低 16 位数据,然后放入 magic_out
中,分四次填充满。
注意 magic_out
和 buffer
是同步的。
1 | end else if (enable & (addr >= MAGIC_BASE_ADDR && addr < MAGIC_BASE_ADDR + 8)) begin |
类比成C语言就是下面这样:
1 | uint8_t magic_out[8]; |
接下来观察给的 memory.mem 文件,开头 8 字节是内核代码地址,即从 syscall
进入的位置,0x390。
根据 configure.sv
,主代码从 0x100 开始,由于项目代码针对的是 MIPS 架构 64 位小端,
所以我们可以使用 Capstone 来反汇编指令,得到
1 | _start: |
利用 0dmips 的基础设施,定位好函数后,整段反汇编写到 magic.S
中,
要把0x390处的 mfc0
指令删除,因为无法正常汇编(可能是反汇编的问题)。
接下来将 memory.mem
中的数据放到文件开始的数据声明区,并将硬编码的地址换成标签,
就可以借助项目,将文件编译为 magic.elf
,放在 build/example_asm
下。
将其拖入Ghidra,可以大致反编译得到如下信息:
其实从官方给的案例中可以看出,题目是写了C文件编译成的,由于我们是在逆向回去, 因此不能做到各部分地址和题目给的memory一样,请根据我的解释分析。
1 | void print(char *param_1) { |
对于这种向标准输出打印内容是向 0x20000010
写地址,程序中还有裸的 syscall 的情况,
反编译确实不能做得尽善尽美,但至少能看个逻辑。 interupt_handler
,即内核代码的逻辑,
是向 0x20000018
写系统调用号的( mfc0
和后面那条指令是无效的,被接下来的指令逻辑覆盖了)。
结合反编译,以及 magic
单元,可以知道这是在往 magic_out
中填充数据。
主函数除了系统调用写数据以外,还会拿系统调用号和密文做异或,每次异或半字,
每轮异或三次,总共4轮,4个密钥,最后全部异或完24字节密文。
接下来从 0x20000018
处抽取出了双字,先将其低32位用16进制打印出来,
再判断这个双字是否和 -0xb6569c1e7c98ad4
相等,如果不相等,就打印 HALT
,
然后进入死循环。我们看到的情况就是运行模拟器,打印 00000000
和 HALT
,
模拟器终止。难道写入 magic_out
都是无效的吗?那多这一段判断有什么必要呢?
反编译中的 0x417
是 :) flag=
的地址,0x411
是 HALT
的地址。
MIPS 一个“字”是4个字节。模拟器支持 syscall
和 break
两种方式陷入内核,
不用管反编译的结果,关注反汇编中调用时携带的数据即可。
难道 magic 单元就没有工作?使用 GTKWave 检查输出的 trace.vcd
,可以发现是有值的。

既然 magic_out
正常工作,那可能只是因为无法读取这个地址,因此显示为全0,
不影响逻辑,接着分析当 magic_out
是 -0xb6569c1e7c98ad4
的情况,发现先打印了 :) flag=
,
然后打印了解密后 flag 的位置(这部分在反编译中没有显示,对应 0x360-0x37c 处的反汇编),
也就是说,将正确的 flag 打印出来。要注意的是打印 flag 的逻辑,并非从低地址到高地址依次打印,
而是按两个字节为一组,组内交换打印的方式,说人话即索引从0开始,按 1, 0, 3, 2, 5, 4
顺序去打印 flag 字节。
结合这个逻辑,可以推测出之前用来解密的密钥是错误的,所以拿那些密钥来还原密文自然是不可读的, 用正确的密钥,按逻辑解密密文,就可以打印出真正的 flag。例如可以用 Python 写以下解密脚本:
1 | from pwn import * |
题外话
原本是想把 magic 单元编译到 0dMIPS 中的,但是怎么改 CMakeLists.txt 都会报一个 verilator 编译失败的错误,导致我没法一步一步跟调, 就只能用这种比较麻烦的办法。
一些吐槽
说起这赛制也是难为人,总共8关,每关3题,需要在一关里面先过一题才开放下一关, 导致只要有卡住的题,后面的题就做不了,太折磨了。
更不用说py的人,看看图里蓝色线的队伍就知道了,最后半个小时加了3000分,纯纯顿悟哥。
参考
Nambers/0dMIPS WIP in-order 5-stages pipeline MIPS64r6el SoC implementation
- 标题: 陇剑杯 2025 初赛 - MagicBox
- 作者: RocketDev
- 创建于 : 2025-09-06 23:37:00
- 更新于 : 2025-09-11 01:11:00
- 链接: https://rocketma.dev/2025/09/06/MagicBox/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。