(d3ctf)d3syscall赛题复现
程序逻辑分析
先打开d3syscall文件,发现.init_array的初始化函数中释放了my_module文件,查找了kallsyms中的sys_call_table地址,并将其作为参数magic初始化内核模块my_module。
dump下来my_module进行分析
在init_module中,程序先保存了0x14f-0x153处的sys_call_table内容(至于为什么没有0x154…我只能猜是出题人忘了),保存cr0,然后更改cr0寄存器的bit16为0(WP写保护位)使sys_call_table所在的内存页可写,劫持0x14f-0x154的syscall为模块内部的函数,最后还原cr0。
由此我们分析若干syscall handler,分析过程中要注意传入syscall的参数rdi, rsi, rdx等被放置在了栈上,rdi指向栈的一个位置,因此handler一开始取[rdi+xxh]值的操作就是在找参数。通过简单的分析很好猜出来对应关系,或者搜一下__fentry__
/找找内核实现/内核调试应该也能出。
分析可知模块内部实现了一个简单的vm,syscall number对应操作如下:
14fh: mov
150h: 算术运算
151h: push
152h: pop
153h: 清空寄存器
154h: 检查栈上内容是否符合要求
假设vm的四个通用寄存器为r0-r3,分析sub_13f5
1 | mov r0, rdi |
肉眼翻译为C代码
1 | void sub_13f5(__int64 x, __int64 y){ |
所以可以通过栈上的tmp1, tmp2值和计算出x,再由tmp1和x计算出y
解题脚本
1 | from Crypto.Util.number import long_to_bytes |