-
-
[原创] 第三题 寻踪觅源 WP
-
发表于: 2020-4-18 09:03 4059
-
注意:本篇 wp 不涉及对题目校验算法的完整分析,请关注我正在抱着的大腿以获得最佳题解。
题目用 quickjs 实现,本人由于过菜,并不会逆其虚拟机字节码。好在作者并没有丧心病狂到将符号去除,通过把在 main 函数内被注册了的 js 函数中看着嫌疑比较大的都稍微下断点调一调跑一跑跟一跟,我们可以发现校验算法与 quickjs 的大整数运算相关。这样一来我将关注重点放在了 BigInt(Float) 的相关函数上,例如 bf_mul
/ bf_cmp
等等,关注程序在哪些地方、以何种顺序调用了这些函数。
有了源码之后我便失去了在 IDA 中打标记的动力,因为可以直接在 quickjs 库中找到 bf_mul
/ bf_cmp
的声明:
可以发现这些函数操作对象是 bf_t
数据类型,它的结构如下:
它是以 hexadecimal floating number(这瞎编的名字是什么?)的形式存储的,limb_t 在我的机器上其实就是一个 DWORD,存的是十六进制的小数有效值部分,len 是 tab 数组的长度。既然打算去跟踪这些函数调用,自然会想到在每一次调用的时候输出调用的参数(比方说打印出 mul 、cmp 的两个操作数),因为已经清楚 bf_t 的结构,我们已经可以直接打印出这个 bf_t。
因为懒惰,写代码之前我在源码中报着期望的目光一瞧瞧二看看,果然在 libbf.c
里我发现了:
于是乎写了个调试器,hook 了 bf_mul
/ bf_cmp
,顺便把 quickjs 的源码拉进来用,在被 hook 函数 hit 的时候输出相应的调用参数:
值得夸奖的是 binary 里面这些函数的头部都留有类似 lea edi, [edi+0]
这样又长又没用的废话指令方便我们进行 hook。
把给的 UserName / SN 拿来跑跑:
经过几轮观察,猜测 UserName 的作用除了计算出一个 BigInt1 之外还对某种形式的表进行了搅乱,这个表用来将 SN 的每 2 个 bytes 置换为一个 100 内的十进制数,然后这些十进制数会被不断拼接成一个 BigInt2,进而与 BigInt1 进行比较。于是我在 UserName 固定时将验证算法简单地抽象成了 assert(f(UserName)==g(SN)),其中 f、g 互不相干,固定 UserName 为 KCTF
后可以得到 BigInt1 为:
现在需要将这个数转换为十进制,Python 直接处理这种数据会丢失精度,因才疏学浅不了解其它更好的方法,我手糊了一个脚本用来生成算式:
然后把输出丢给科学家们用的 Mathematica 求解:
简单地划分一下这个结果得到:02 43 37 77 98 92 55 56 02 64 77 31 43 60
。
接下来便是跑表的过程了,同样因为没有什么好办法,我开始了手动跑表,跑了一会儿发现在每个段(用 ---
隔开的部分)内 in-out 的映射关系是有规律的:
于是后续阶段里每个段只需要跑一个结果即可推出剩余的部分。
得到表之后,把 02 43 37 77 98 92 55 56 02 64 77 31 43 60
映射回来,即为本题的 flag: 40017535dad01714402635730122
。
PS. 我在手动跑表的过程中得知附件被换掉了,内心顿时受到 1w+ 的暴击伤害并直接回到了泉水(指床)开始了为期一晚的挂机疗养,后经美味 pizza 与强壮大腿的滋润才得以康复。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创] 第三题 寻踪觅源 WP 4060
- [原创] 第二题 WP 2732
- [原创]第四题 club_pwn exp 3655
- [原创]第三题 crackMe 2850
- [原创]第二题 ctf2017_Fpc 3919