安洵杯2019-crackMe
一、题解
主函数的伪代码如下:
可以看出整个流程是:先输入flag,然后弹出一个警告弹窗,之后有sub_41100F
和sub_411136
两个函数。第一个函数比较复杂,可能是一堆加密操作,在最后面会进行分析。第二个函数是最终是将两个字符串相比较,如下图所示:
Str2
已知,而Str1
未知,但是可以发现它在另一处被引用了,如下图所示:
问题就来了,这个函数是怎么被调用的呢,目前来看是不可能执行这个函数的。所以我们下一步的目标就是分析它是如何被调用的。
在字符串窗口中,可以发现base64的对照表,跟随该字符串可以找到这样一个函数,如下图所示:
该函数首先是对base64对照表中的小写字母大写化,大写字母小写化,然后弹出提示hook成功的弹窗,最后执行AddVectoredExceptionHandler
函数。
这应该说明了通过hook技术执行了原本不应该执行的函数。
AddVectoredExceptionHandler
函数用于注册异常处理程序,第二个参数Handler是要调用的处理程序的指针,详细介绍可见AddVectoredExceptionHandler 函数 (errhandlingapi.h) - Win32 apps | Microsoft Learn。
那我们跟进这个Handler
函数看一看,代码如下图所示:
0xC0000005
是一个访问冲突代码(访问冲突 C0000005 | Microsoft Learn),也间接说明了这是一个异常处理函数。整个代码的流程为:先判断是否是访问冲突错误,如果是,则将已知字符串的前16个字节复制给v2
,然后调用sub_411172
函数进行SM4
密钥生成,dword_41A218
(后面会提及)用于存储生成后的密钥,v2
作为初始密钥传入。这个函数是靠Findcrypt
插件识别出来的,具体加密代码如下图所示:
(这里我参考了(六)国密SM4算法 - 知乎 (zhihu.com)进行比对)
回到Handler
函数中,SetUnhandledExceptionFilter
函数会在异常发生时,调用由TopLevelExceptionFilter
参数指定的函数,详细见SetUnhandledExceptionFilter 函数 (errhandlingapi.h) - Win32 apps | Microsoft Learn。
因此,我们需要进入到TopLevelExceptionFilter
函数中查看,最终如下图所示:
首先是将Str2
(最开始提及过)字符串两两对调。然后是byte_41A180
字符串(待会还会提及到)进行非正常base64加密得到Str1
(最开始提及过),之所以叫非正常base64加密,是因为它把表进行了循环右移24位,并且将 ‘=’ 换成 ‘!’ 。
到这里,hook的部分就结束了。
奇怪吧!做了这么多事情,但并没有对我们的输入做任何处理,而且也还存在未知的数据,例如用于base64加密的byte_41A180
字符串。那么就看看这个字符串还在哪里被引用了。可以发现实是在sub_41100F
函数中被引用了,如下图所示:
这些参数我们在上面都提及过,dword_41A218
是生成的sm4密钥,unk_41A1E4
是我们输入的字符串,byte_41A180
为生成Str1
的明文。
sub_411131
这个函数主要是进行SM4加密,unk_41A1E4
作为明文,使用dword_41A218
密钥,生成byte_41A180
密文,具体代码如下图所示:
上图中sub_411700
函数:
上图中sub_4111760
函数
上图中用到的 s 盒:
总结一下整个过程。flag通过sm4加密,得到密文,密文进行base64加密(注意对照表被改变了,大小写字母互换,循环右移24位,’!’ 代替 ‘=’),得到Str1
,并且Str1
与Str2
(注意Str2
两两交换了)相等。
所以解密脚本比较简单,如下所示:
1 |
|
二、题外话
在写题过程中,我曾困惑于以下两个问题,后经询问汪佬才得知是怎么回事。
2.1 MessageBoxw是怎么被hook的?
我们回到这个hook后代替执行的函数中,对函数名按 x
追溯来源,结果如下图所示:
我们有理由怀疑GetModuleHandleW
函数是在获取User32.dll
模块,然后再在该模块中寻找MessageBoxw
函数地址的地址。最后修改函数地址达到hook目的。
这里我们进行动调试一试。结果如下图所示:
图1:
图2:
这里已经验证了一部分猜想。接下来我们就可以再次追溯a3
的来源,因为它是作为参数传入的,所以相当于追溯函数调用。追溯结果如下图所示:
同样也下断点进行动调,结果如下图所示:
通过LoadLibraryA
载入User32.dll
库,然后再通过GetProcAddress
获取MessageBoxw
函数的地址,也就是a3
的来源。
到这里我们就理清了MessageBoxw
是如何被hook的了!
2.2 明明只是赋值sub_41100F函数地址,它怎么就被调用了呢?
在main_0
函数中,跟sub_41100F
函数有关就是那行赋值代码,显然不可能让它执行,但是我们来看它的汇编代码:
1 |
|
这是一个SEH异常处理。而sub_5F100F
正好作为异常处理程序被调用。
借用某网友的一句话:FS常用于异常处理,这里是异常处理程序的指针入栈,以便STACK rewind。
也参考了[原创]windows-SEH详解-软件逆向-看雪-安全社区|安全招聘|kanxue.com。
至于具体的细节这里就不再展开了。(因为我也不会)