自己做的时候。

照样IDA先找找字符串,会发现这个。

经常打CTF,做misc和crypto的话,第一反应这是一个莫尔斯电码。可能和加密数据有关系。

OD调试单步可以走到这里来,DialogBoxParamA是弹框的函数。再单步执行点击验证会崩溃。程序大概率是加了反调试的(每次碰到这种我就***了)

IDA里搜索字符串很明显可以找到这么多的动态工具。一定是加了各种反调试的。

始学习之

下面开始学习之路。

官方题解


先来记录下看到的对我印象很大的一句话:新手用OD,高手看汇编!以后会大大改善自己的学习习惯和方法的。

要习惯IDA来找算法入口,直接绕过所有的调试和反调试。

这些函数是可以用来读取用户输入的。

View - Open Subview - Cross References


利用好IDA的字符串功能和导入函数imports和导出函数功能,OD的中文智能搜索也是一个好工具。

提示我们字符串长不够

(从这里就能猜到base64的使用,个人觉得还是很牵强。。。但是可以作为一种思路猜想,去验证)

看到了MessageBoxA的ok!激动不激动,说明找到了正确的处理地方。

在这里

通过交叉引用找到了对的地方。函数434EF0。

这么多的Exit,很明显就是反调试检测到了些什么东西,然后强制程序退出。可以直接看后面的算法部分。


从GetDlgItemTextA看起,第三个参数是我们的输入,标记一下。

然后往下看,哪些地方用了我们的input。

这里为什么是memset和base64的解密函数等会儿解答,从这里我们可以看到是把我们的输入经过了两次相同的处理,然后保存了起来,继续往下看。

然后,我们的inputdecode(就是经过两次相同处理后的input),分别进入了两个不同的函数处理

得到了v19和afterSM3decode(这个等会儿解释)。sub_42DF05函数是把这个值转换成了16进制(02x,不够的前置填充0),所以,SM3Hash这个字符串是64字节长度的。

v6呢,是我们的输入连接上一个啥玩意,相当于输入

这里看到,v6和我们的SM3Hash有个比较,那一定是字符串比较对吧

看到MessageBoxA是输出我们的ok成功字符串,那这个if语句也要成功

基本逻辑分析完了,我们需要解决的几个函数:为什么是base64,SM3,迷宫,还有一开始看到的莫尔斯在哪儿?程序是怎么匹配的。


memset函数戳进去,发现基本都是赋值0的语句。

而且在都是在函数调用和运算之前,那么很大可能性是初始化赋值0的语句

一般写法是memset(a,0,sizeof(a)),正好符合IDA反汇编之后的格式了


base64函数:点进去看到的是sub_434990.

看到了%4,看到了=号,看到了对不同的模数分情况讨论

见过C语言实现的base64encode和base64decode解码的会习惯这种<<和>>去操作每一个字符ascii码值,然后去相加计算的

因为是每次取4个,变成3个。所以是base64的解密过程。


SM3:会跳转到sub_437E70函数。

看到这个玩意,每个函数都点一点,因为是个加密解密模块,可能会有MAGIC(每个加解密函数独有的字段,也就是特征值)

百度一下,发现是SM3压缩加密,是一个摘要算法,弄出来就是64字节,也符合了我们的猜想,为什么转成另外一个数组


迷宫怎么猜到的:

那个if语句需要为真,v19是我们的input经过两次base64解密,再转换的(无论怎么样,都是输入)

那么这个函数和第一个参数就是我们需要认真查看的东西

函数在435400,看到了四个判断,分别是z,l,p,q,猜测是上下左右,那么第一个参数就会是地图

如何对应上呢?

分析一个p作为例子,判断的是v7+v11>=0,发现v7是一个常数-1,那么v11一定是当前坐标的某一个,然后发现v改变的是4个单位,如果是4个单位为一步的话,那么减一步就是向左了。截图如下:

同理分析我们可以得到,z下,l右,q上,p左

那么去数组里找需要的地图


刚才在函数里看到了,4个为一组,40个为行的跳跃。所以10个字符为一行。把数据扣出来得到地图

0111111110
0011111000
1000001011
11111010#1
1000101001
1010001011
1011111001
1000011100
1111000010
1111111000

有个值是不能走的在地图里用#标注,#的本来的意思是排除迷宫的多解,因为有(8,3)的检验。从(0,0)开始,走到终点?

这就是这个题的bug了!只判断了地图中不能走到1的位置,所以从左上角出发,不碰到障碍物即可,不需要走到终点,先按照作者意思来

那么,我的输入转换之后是:

zlzllllzzzppqppzzzlllzlllzllqqpqpqqqqqllq

现在就到了需要研究函数42D96A的时候了,调用的是435DE0.

首先可以看到的是判断字符是空格还是斜杠


然后对于空格的分为三类,42D7B2处理一类,42E414处理一类,另外一个函数是报错的

42D7B2戳开,调用435AA0函数,发现了这个

看到加‘0’,那一定是转换0-9

然后找到if里面的调用的435D00,看到了这个

这个26和‘a’说明了一定是在处理小写字母,我们戳开49B2A0,可以发现:和我们想要的莫尔斯联系上了


综上,我们的逻辑思路和程序的判断思路已经对上了。

输入进来先两次base64的解码,再用莫尔斯电码转成zlpq的方向走迷宫,从左上角到右上角,成功即可

看到匹配时候的负号,说明是倒着匹配的,那么说明SM3作为后缀添加上的


(可能觉得练习得很牵强,怎么就猜到了,逆向提供的只是一个框架,一个思路,剩下的靠验证就可以)

去找到zlpq的莫尔斯

于是得到了这个

s = 'zlzllllzzzppqppzzzlllzlllzllqqpqpqqqqqllq'
m = ""
for i in s:
	if i == 'z':
		m += '--..'
	elif i == 'l':
		m += '.-..'
	elif i == 'p':
		m += '.--.'
	else:
		m += '--.-'
print m
#m = '--...-..--...-...-...-...-..--..--..--...--..--.--.-.--..--.--..--..--...-...-...-..--...-...-...-..
--...-...-..--.---.-.--.--.-.--.--.---.---.---.---.-.-...-..--.-'

以这个字符作为结尾,所以放进去

再用base64两次加密,第一次得到

LS0uLi4tLi4tLS4uLi0uLi4tLi4uLS4uLi0uLi0tLi4tLS4uLS0uLi4tLS4uLS0uLS0uLS4tLS4uLS0uLS0uLi0tLi4tLS4uLi0uLi4tLi4uLS4uLS0
uLi4tLi4uLS4uLi0uLi0tLi4uLS4uLi0uLi0tLi0tLS4tLi0tLi0tLi0uLS0uLS0uLS0tLi0tLS4tLS0uLS0tLi0uLS4uLi0uLi0tLi0v

到了这里,就需要用到patch反调试了,不然没法动态OD看到SM3的加密结果