首页
论坛
专栏
课程

[原创]看雪2017CTF秋季赛第三题--实战过反调试、多解分析

2017-10-30 01:44 6501

[原创]看雪2017CTF秋季赛第三题--实战过反调试、多解分析

2017-10-30 01:44
6501

这道题被大家称为反调试大全,我一开始也是被反调试搞得没有信心了于是就去根据ida静态分析的结果去还原算法了,结果又陷入了苦海中,最后一咬牙把反调试全过了才找到了正解和多解。

 

目录

0. 调试前准备工作

0.1 随机基址

  • 用od打开程序后发现进入程序住逻辑后地址不是0x00400000开始的,所以肯定不是固定基址,打开010Editor修改随机基址标志位(PE标志下数一行零六个)由0x02改为0x03,方便以后调试和分析:

    图片描述

0.2 定位窗口回调

  • 定位窗口回调我是一步步跟的,因为在窗口毁掉之前的都是系统函数,也没有什么好说的

  • 跟到0x0043D39D那里后程序跑了起来,所以证明窗口回调是在这里注册的-

  • 跟进去后发现了DialogBoxParamA这个API,这就是在注册窗口回调,根据参数看到注册的窗口回调地址为0x0042E1A3

    图片描述
    图片描述

  • 这个地址是一个jmp 00434EF0说明程序是Debug版编译的(搞不清楚作者为什么要编译Debug版程序)。废话不多说了,找到了窗口回调了就可以开始分析程序了

    图片描述

1. 反调试

1.1 运行检查

  • ida F5大法分析窗口回调中的代码:

    图片描述

  • 可以看到在窗口回调中有检查环境(sub_42D4F1(); sub_42E428(); sub_42D825()里面都有检查,这些检查函数返回值如果为1就调用ExitProcess(0);)这些检查od的反调试插件都可以过掉,但是我发现他是调用ExitProcess来退出程序的,所以就用010Editor把PE文件中所有调用这个API的二进制代码FF15CCF34900改为了0x90 (nop),防止其他地方也有调用该API退出进程

  • 这算是过掉了第一步的反调试

1.2 FindWindow

  • 在一开始运行程序时(没有开od等调试工具),程序是正常的,但一打开od、peid等工具后程序会在按下验证序列号自动退出。这个比较简单,可以通过od跟、查看导入表中有什么奇怪的API后下断点(我就是在导入表的中看到了FindWindow这个API)、在ida中点进函数看:

    • 查看导入表:用od随便双击一条调用系统API的指令查看指令中的地址、在内存窗口跟随地址、右键->反汇编,就可以看到导入表了,在导入表里可以发现该程序调用了那些API(这是个实用的技能)
    • ida看到的:

      图片描述

    • 过这个也很简单,抹掉该函数调用或者改掉字符串,我是在WinHex中找到字符串直接抹掉

1.3 每个关键函数里都有的反调试检查

下图中框住的函数中都有反调试代码

 

图片描述

  • 看到这么多反调试的代码真的无语了,所以我先不管三七二十一看到这些代码就给右键->二进制->使用nop填充使其不能生效。(作者没有在这些反调试代码中做结果验证的相关代码真是给足了面子,不然全nop掉肯定拿不到正确结果)

  • 需要注意的是这次用od nop掉反调试代码后无法保存到可执行文件,所以我就用x32dbg nop掉代码后保存补丁

1.4 一段经典的使用异常链反调试

这个是通过之前od调试时发现的

  • 在函数调用0x42DA78->0x42D294->0x42DA7D中,由于是Debug版函数调用间有jmp所以我只写了关键部分,最终这段反调试的代码地址在0x431070那里

    图片描述
    图片描述

  • 这段反调试代码比较经典,将异常处理绑定到自己的处理位置,然后自己造int3错误和除零异常然后自己收,都可以用专门写一篇文章来分析,只可惜作者没有在这里面写重要处理代码,所以直接在上层调用中nop掉就可以过了。

1.5 小总结

  • 虽然有这么多反调试,但全给nop掉就过了,所以感觉作者这次的反调试没有利用好,如果反调试代码里面又有解密/校验相关的代码或数据,像我这样暴力nop肯定就掉到坑里了

2. 分析密钥

2.1 从memcmp那里拿到关键信息

图片描述

  • 在上面框住的几个是作者的算法函数,下面的memcmp很显眼

  • 在很早就发现了memcmp,但是由于反调试太多了同时也懒得过反调试,而且看到了上面的算法函数就想着我都拿到了算法直接破解算法就拿到密钥了(又陷入了第二题的死磕思路中)。于是在分析算法的苦海中遨游了半天受不了了。。。都分析到了摩斯电码那里了,实在分析不下去了,想想还是过反调试更容易些。扯远了回到正题

  • memcmp那里下断点,输入不同的值来观察:

    图片描述
    图片描述
    图片描述
    图片描述

  • 发现问题了没有?输入123456789111111111的结果是一样的、输入abcdefgaaaaaaa的结果也是一样的

  • 令人好奇了,这是不是算法有问题?突然灵机一现,将输入123456789后传到memcpy的那个长字符串参数(64位长)重新输进去会发生什么?

    图片描述

  • 奇迹发生了,此时出来的结果是一样的!memcpy的另一个参数就是刚才的输入,所以这一层验证就过了

  • 然后跑起来:

    图片描述

  • 过了!难道这就是作者构造的密钥?我有些不敢相信!另外还有疑惑没有解答,因为前面输入的不同内容却产生了相同的输出,所以就怀疑有多解了

2.2 多解分析

  • 对多解的怀疑不仅仅是因为上面的原因,还有在前面对该memcmp比较参数的怀疑:

    图片描述

  • 调试一下就可以发现v5是输入的字符串指针,v6是经过算法编码后的字符串长度(就是前面在memcmp那里断到的64位长度的字符串)

  • 通过下图来理一下逻辑:

    图片描述

  • 所以memcmp比较的参数是移动后的,同时也解释了为什么之前输入内容后memcpy拿到的第一个字符串参数为空了,是因为字符串长度不够64位呀

  • 那推理一下如果字符出串长度超过64位呢?继续看图:

    图片描述

  • 看到这里是不是可以发现如果输入的内容超过64位那就会只判断后64位!

  • 再结合前面发现的输入不同的数字出现的是相同的结果、输入不同的字母出的是相同的结果(经过验证,其实是只要以数字开头就是相同的结果、只要以相同字母开头就是相同的结果)。那么就可以把这两点结合起来,先随便输入一个小段字符拿到经过算法加工的内容,将该内容补到刚才输入的字符后面再次输入。比如输入abcdefg拿到432a34a4946708602bdf52a8b556a3c18ff9ab60c346da83579f149c4f366513,然后构造出abcdefg432a34a4946708602bdf52a8b556a3c18ff9ab60c346da83579f149c4f366513再次输入:

    图片描述

  • 于是memcmp这一层又轻松的过了

  • 但是我们可以发现其实在memcpy后面还有一个校验函数:

    图片描述
    图片描述

  • 这个校验函数返回1为校验成功、0位校验失败,而在实际测试中,这段校验代码“时灵时不灵”,而这段校验代码校验参考的内存则是一大片0加上一个特殊校验值再加上原输入,但是由于不稳定就没有继续分析了这段校验代码了,暂时把这段代码当作失败的校验,静等作者公开出题思路

3. 总结

  • 这次作者在反调试方面下了很大功法,但是由于意外的Bug导致了多解。

  • 到目前做了两道题了,现在在思考,如果能将作者的反调试思路和昨天Fpc的花指令思路结合起来应该可以造出一个比较强大的CrackMe!



[公告]安全测试和项目外包请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-5-20 10:19 被KevinsBobo编辑 ,原因: 修改错误
最新回复 (13)
KevinsBobo 7 2017-10-30 14:46
2
0
原来这道题是个解迷宫的题,一开始发现了迷宫数据和摩斯电码,但由于经验不足没有倒着分析,先去分析了Base64的算法最后痛不欲生,于是就把后面摩斯电码和迷宫的算法给放过去了。
这道题能解出来也是因为运气,作者判断空格结尾,而我输入的里面没有空格,于是走迷宫算法在内存中一直遍历寻找空格,最终溢出。
OnlyForU 2017-10-30 17:28
3
0
多谢分享!
bestriven 2018-5-7 17:29
4
0
请问摩斯加密与国密这些加密算法识怎么看出来的  是采用ida  sig库识别的还是自己人工识别的
KevinsBobo 7 2018-5-7 18:02
5
0
bestriven 请问摩斯加密与国密这些加密算法识怎么看出来的 是采用ida sig库识别的还是自己人工识别的
当时是人工识别的,后来找了一些ida插件尝试自动识别,效果并不理想
feihuasimeng 2019-5-17 16:35
6
1
您经过反调试,nop后的crackme文件可以给一下吗?谢谢
feihuasimeng 2019-5-17 21:26
7
0
版主,用010Editor把PE文件中所有调用这个API的二进制代码FF15CCF3490改为了0x90 (nop)后,crackme无法双击打开
KevinsBobo 7 2019-5-20 10:18
8
0
feihuasimeng 版主,用010Editor把PE文件中所有调用这个API的二进制代码FF15CCF3490改为了0x90 (nop)后,crackme无法双击打开
非常抱歉,我文章中写错了,应该是FF15CCF34900。我之前修改过的文件没有保存
feihuasimeng 2019-5-20 19:46
9
0
我用010Editor把PE文件中所有调用这个API的二进制代码FF15CCF34900改为了0x90 (nop)后,crackme还是无法双击打开。
您经过反调试,nop后的crackme文件的链接可以发一下,方便我学习,谢谢。
feihuasimeng 2019-5-20 19:58
10
0
修改前是FF15CCF34900

修改后是90 

双击打开crackme,无法打开


KevinsBobo 7 2019-5-21 10:00
11
0
feihuasimeng 修改前是FF15CCF34900 修改后是90 双击打开crackme,无法打开
我之前的文件没有保存,所以给不了你。你的修改有问题,要将FF15CCF34900换成6个字节的90,也就是换成909090909090。你现阶段的话建议你先用od在调用位置的汇编上 右键->二进制->使用nop填充 看看效果。
feihuasimeng 2019-5-22 13:52
12
0
我在用od修改后保存到一个新文件。但我再用od打开新文件后发现FF15CC还是FF15CC,没有改成90。od竟然无法保存我的修改
自然dashen 2019-5-22 14:57
13
0
feihuasimeng 我在用od修改后保存到一个新文件。但我再用od打开新文件后发现FF15CC还是FF15CC,没有改成90。od竟然无法保存我的修改
修改好后在反汇编窗口鼠标点击右键->复制到可执行文件->所有修改->然后会弹框点击全部复制
做完上面的反汇编窗口会变小->点击右键->保存文件
建议看下OD入门教程
feihuasimeng 2019-5-22 18:18
14
0
根据您的建议,已解决,谢谢
游客
登录 | 注册 方可回帖
返回