DubheCTF-Destination&Moon
DubheCTF-Destination&Moon
前言
第一次给这么大的比赛出题,一想到能够折磨这么多人,就觉得浑身舒畅,虽然看这个解出数量并没有折磨到任何人。。。
源码在此(屎山罢了,你不会想看的)
Destination
程序加入的反调可以在41E000-41E138里面找到,全都改成0即可绕过。
在main函数中可以找到如下代码:
程序手动注册了异常处理函数sub_4140D7,但是这个函数夹带了大量的跳转语句和花指令,可以使用以下idc脚本去花:
1 |
|
此后,这个函数可以恢复成这样:
由于SEH的展开操作,这个自己注册的函数会被执行两次。详见这篇文章。
接下来程序采用天堂之门技术,让32位程序执行64位代码。jmp far ptr loc_4142A7
应当理解为jmp 0x33:413F77
,即跳转至0x413F77同时将cs寄存器由0x23转变为0x33。将此段代码dump下来喂给64 位IDA即可得到:
其中0x4234A8即为输入。汇编代码最后的push 23h; push 4179F3h; retfq;
在跳转回0x4179F3的时 候又将cs寄存器转为了0x23,此后执行32位代码。据此,我们可以写出解题脚本:
1 |
|
运行得出flag:DubheCTF{82e1e3f8-85fe469f-8499dd48-466a9d60}
Moon
程序存在大量的大数运算,所有数据全都是反着存储的。主要逻辑集中在sub_140001B20中:
应当可以看出程序中有这么一个结构体:
1 | struct BigNumber{ |
在主要逻辑函数中,可以发现:
其中sub_140001780是高精度快速幂,sub_140001000是高精度乘法,sub_140001260是高精度除法,xmmword_140007848是一个大质数,Src是做除法时生成的余数。最后可以得到程序在干这么个事:
把这一坨喂给一个密码手,可以得到:
由此可知,程序在试图求解:
其中a位输入,p给定,判断解出的x是否与预设的值相同。据此写出解题代码:
1 | x = 885929268745208437773737031796868079277836491798608104263226417228443603006843430266722004055919359990 |
输出的md5值即为flag:DubheCTF{c58a378bec96b92d8e19b2e7dbddc4ff}
如果没有发现这一点也没有关系,从x[i]
逆推到x[i+1]
无非就j=0
和j=1
两种情况,从x[0]
推到x[9]
总共也就种情况,我们完全可以爆破。以下是S1uM4i战队的代码:
1 | x = 885929268745208437773737031796868079277836491798608104263226417228443603006843430266722004055919359990 |
后记
天堂之门之后的部分写的还是太简单了。虽然我特意使用的rdi,rsi,r14,r15这四个寄存器,让它在32位里面看起来是edi和esi两个寄存器,试图混淆选手的视听,但是依旧有队伍靠着剩余的代码猜了出来。下次一定要上自己魔改的乱七八糟的算法。
本来想着Moon出成这么一个数论的样子会被骂惨了的,但是好像这次比赛的web和misc更加逆天,再加上总共就256种路径,可以爆破,也就没有什么人骂我这道题了,诶嘿~
某种意义上这也算是载入历史了,往外就说”这是XCTF的历年真题"!