Hitcon2023 Reverse wps | AK with StrawHat
碎碎念
应该是在 Straw Hat 队认真打的第一场国际赛事吧,可惜半天左右就把逆向全打完了(驾驶员技能发动 我一个人就够了.jpg),有些失望(但是很爽)。
写于 2023-09-09 23:25 离比赛结束还有 1day 左右,但是目前放出的 Reverse 已经全部 AK 了,没事干了写个 Writeups 先。感觉目前放出的 Reverse 难度总体偏易,大概 CrazyArcade < Full Chain - The Blade < LessEQualmore 吧,这里按打题顺序简单写一下复盘。
LessEQualmore
虚拟机的逻辑非常简单,每个指令为 3 个字长a1 a2 a3
,假设存在mem[]
里
逻辑伪代码大概如下:
|
|
然后就是逆向字节码了,这个字节码非常复杂,需要考虑一种方法去除我们不需要的指令。可以运用类似编译原理中常量传播的思想,追踪所有与输入数据相关的数据位置,dump一份只和输入相关的指令:
|
|
上面的代码是经过多次逆向和修改后的最终代码,range(16, 16+8, 1)是在dump指令得出输入数据存储位置之后加上的,这个定位和上面追踪输入的思路类似。
需要注意的是,可以发现对buf[0]~buf[4]的操作非常多,不难发现他们是寄存器类似用途的内存,所以当这部分数据等于0时可以认定它们不再与输入有关并且停止追踪。这样可以dump出一份相对短的代码。
从这段字节码可以看出只涉及简单的加减操作(本来以为有用减法实现其他运算的骚操作),那么最后的算法一定是一个多项式或矩阵。
观察并打印一下算法结束后的buf数组,可以观察到输入位置的数据发生了变化,可以推测加密后的数据是存在原地的。
接下来手动fuzz一下,看看变动输入数据发生的变化。首先以hitcon{test_flag}
为例dump一份加密数据,改为hitcon{sest_flag}
再dump一份加密数据,可以发现只有前8位发生了变化,结合诸多类似方式的验证可以知道flag验证为8位一组。
顺便某一次得到的密文是[16774156, 1396, 16776307, 3691, 1558, 6506, 2587, 10],由于flag开头hitcon{
就占了7位,所以此时得到的密文一定和正确密文相差不大,在chal.txt里面寻找类似的东西,可以找到密文(就在输入数据和输出的字符串中间,肯定没问题)
|
|
得到正确密文之后,由于flag开头只剩一位,可以手动爆破一下知道flag的前8位是hitcon{r
有了一组flag,结合前面加密算法为矩阵方程组的推测,可以直接弄出矩阵的系数。具体来说,对每一位依次加一,例如传入iitcon{r
,那么得到的密文和正确密文的差值便是该项在该方程中的系数。
顺便由于1677….是2^24,简单猜测一下那个是负数标记。
|
|
得到矩阵系数,z3一下就解决了。
|
|
CrazyArcade
给了一个泡泡堂游戏和一个驱动,简单找一下 WIN 逻辑
|
|
要求 dword_7FF63A836238 >= 0x1337 查引用
|
|
尝试触发这个++dword_7FF63A836238
,直接patch掉if ( dword_7FF63A8362E0[15 * lpBytesReturned[1] + lpBytesReturned[0]] == 5 )
的条件变成不等于。
启动游戏发现一开始敌人全死了,Cheat Engine看dword_7FF63A836238变成了4(一共4个敌人)
不小心玩死了自己 GameOver 重来发现 dword_7FF63A836238 变成了 8,可以发现重来之后这个计数不清零。
写个脚本重复炸死自己(这里patch后敌人会被开局杀),挂亿会之后cheat engine在内存里搜hitcon得到flag。
感觉非预期了,开题到出解题思路不到十分钟
Full Chain - The Blade
逻辑在 verify
函数,打乱+逐位数字计算,不用逆直接动调打表就行。
|
|
发现不对,看了一下发现没有比较逻辑,反而是把flag和密文填到了某个东西里,一看是一段shellcode。F5一下
|
|
这里面关键的几个数据
v5 从/bin/sh读入4个字节 \x7fELF
v10 从/etc/passwd读入4个字节 root
v14 读/dev/null/得0,然后计算一下
小逆一下就结束了
|
|
总结
感觉这几个题里就LessEQaulmore需要小看一会吧,如果明天还有题我再来写(如果文章发布的时候你看到了这句话说明我没写)