总的来说这道题是不好的。为什么?因为有bug。后面我会提到。因为这个bug导致这个题很多解(无数个解)。很多人脑子都不动就作出答案了。这个没有达到作者想要达到的目的。然后从正常的设计来说,还算是凑合的。给你打60分,保你及格,不能再多了:)
有很多人说这道题很难,有很多反调试。然而这并没有什么卵用,为什么呢?且看下文
正常的解题思路
首先看下程序:
根据hex可以发现。文件没加壳。没有做任何保护。直接ida怼一波。真正的粉丝,从来都没听说过什么OD和windbg,我们只用hex和IDA。
既然什么保护都没做。那就老规矩。直接看字符串:
也可以直接看导入函数:
然后引用跟一下就可以来到一个地方:
在这里我们看到了“OK”。在往上还能看到:
这种特征非常非常明显了吧?程序主要流程就在这里。。。然后你仔细看看这个函数基本这个题就做出来了(起码你已经找到核心点了)其实这里面我是为了大家理解,才这么写的。我的实际操作比这个要风骚的多啦。我在分析的时候。看到字符串有如下信息:
如上图所示。看到这个消息我就知道算法十有八九就在这里。为什么?因为只有在加密解密还有进行编码和hash的时候才有可能出现buffer太短。(后面会讲到,这里其实是摩尔斯密码的加密算法)长度不够的情况。然后直接跟上去。算法就直接被我定位到啦:)
然后不要着急。再看看字符串。字符串里面有太多信息可以挖掘啦。只要你有想象力:
这已经很明显告诉你这个程序可能会出现base64编码啦。这也是一个重要提示。(虽然你跟进去之后ida不能溯源。但是你知道算法有可能会有base64编码那就已经足够啦。逆向破解思路最重要。只要有一点点思维的火花,就可以解题了:)
除了这些,还能看到什么?如下图:
看到这个想到什么?!没错,就是摩尔斯密码。也许你会质疑:就凭借字符串,你怎么确定程序就是用了摩尔斯密码?没错,确实无法直接下定论。但是,我刚才说了。逆向整个过程就是靠思路。这个思路可能是错的,也可能就是正确答案。这无所谓的。想法对不对并不重要,重要的是你有没有自己的想法?因此思路绝对最重要的。逆向破解,思路为王。所以说在看到这些字符串的时候要大胆猜测。接下来就是小心验证。
好的,我们还没开始分析,光凭借字符串就已经得到很多的信息了。现在先总结一下:
a) 直接找到了关键跳转
b) 定位到了关键算法
c) 可以知道算法中很可能用到了base64编码和摩尔斯密码。
现在继续分析关键跳转所在的函数。这个函数的地址是:0x434EF0。这里面有很多if判定。大多数都是退出代码:
然后跟上去看一看可以发现有反调试的东西
(反调试部分后面详细说)
。然而我逆向程序从来不用动态调试。所以这些东西对我来说并没什么卵用:)
程序的关键逻辑在这里:
基本的流程就是:读取用户收入信息。然后做两次base64编码,再用国密算法SM3计算一个hash(你也可以认为就是用SM3加密)。计算完hash之后转换成16进制。然后将Hash值的后64位和用户输入进行比较。如果正确则进入一个“迷宫”迷宫就是密码学中的小游戏。就像迷宫一样:
大家看到迷宫不要方。相信我,迷宫就是吓唬新手的。其实很简单:
上图就是迷宫图。(这种迷宫还是最简单的迷宫)把里面的数据(byte_49B000)复制处理整理一下:
如上图所示,迷宫就出来了。其中X就是障碍,不能走(为了形象、直观我表示为X。其实原数据是1)0是可以走的位置。然后这个迷宫的解就出来了:
入口→下→右→下→右→右→右→右→下→下→下→左→左→上→左→左→下→下→下→右→右→右→下→右→右→右→下→右→右→上→上→左→上→左→上→上→上→上→上→右→右→上→出口
那么问题来了。我现在自己能走出去。但是具体的操作是什么我不知道。也就是说,上文提及的“上下左右”在编码中是如何表示的?“上下左右”的表示在编码中可不一定真的就是“WSAD”或者“SXZY”哦。因此这就需要分析了。其实也很简单。一看就知道啦:
如上图所示,“上下左右”的按键分别是:
Q=上、z=下、p=左、q=右
总是所述,正确的答案行走路线是:
zlzllllzzzppqppzzzlllzlllzllqqpqpqqqqqllq
注意,路线的末尾必须有一个空格,表示结束。
然后根据上面分析到的结果进行逆运算。它的摩尔斯码如下:
--..
.-.. --.. .-.. .-.. .-.. .-.. --.. --.. --.. .--. .--. --.- .--. .--.
--.. --.. --.. .-.. .-.. .-.. --.. .-.. .-.. .-.. --.. .-.. .-.. --.-
--.- .--. --.- .--. --.- --.- --.- --.- --.- .-.. .-.. --.-/
注意了:在摩尔斯密码中,空格前加‘/’转义表示空格本身。
接着将上述结果进行2次base64编码,结果如下:
最后在末尾附加hash值(就是SM3加密之后的值)就是答案:
一个致命的BUG
这个bug的原因在于memcpy。由于空格会被当作截断。所以我只需要写对一部分答案。然后利用空格就可以构造无数个解了。
这个答案如果想象不了的可以动态调试一下。
其实上图中的答案只是正确答案的前缀。再看第二个验证,能通过是因为传入第二个验证的字符串,都是0x00,一个判断都进不去,肯定就执行函数尾部的return TRUE。
关于反调试
这个题目有很多的反调试。然而,对我来说并没有什么卵用。因为正如大家看到的,全文上下我没有用任何调试技术。纯粹是静态看汇编。有句行话:“菜鸟用OD,高手看汇编。”希望各位逆向届的新人从一开就养成好习惯。不要过于依赖OD、windbg这类的调试器。少去调试,多看静态。(用IDA的时候少去F5,这都是坏习惯)对自己能力的提升很有帮助。由于其以后想从事逆向这个工作的同学,更要注意培养自己这个习惯。为什么?因为以后工程上分析病毒,破解商业软件,对抗外挂等等你会遇到非常非常强大的反分析和反调试技术。(比如高版本的VMP壳、动态移动且运行时解密的shellcode、上千个异常处理等等)在这种情况下。你是不可能动态调试的。这里说的不可能不是说不能做。而是成本太大。在工作中,我们不仅仅要解决问题,还需要尽可能的优化成本。这个成本包括时间成本,人力成本,经济成本等等。所以并不是说我逆向出来了,就万事大吉了。硬碰硬的死磕是非常不明智的。
从字符串里面就可以看到反调试的影子啦:
跟上去就可以发现一些反调试:
上图是窗口检测逻辑。枚举了各种调试器。
这又是另一个反调试逻辑:
它会检测包括SysinternalSuite在内的工具。
其他的几个反调试点如下:
说实话,这里的反调试其实非常简单,很容易passby。作者没有在这里面写重要处理代码,所以直接在上层调用中nop掉就可以过了。(或者使用return大法)如果反调试代码里面又有解密(或者校验)相关的代码或数据,或者在反调试代码里面加入一些关键的逻辑。那像这样暴力nop肯定就GG了。这也可以大大提高难度
。
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。