首页
社区
课程
招聘
[原创]吾爱破解2016安全挑战赛cm7 Android CrackMe 分析详解
发表于: 2016-4-4 22:07 8788

[原创]吾爱破解2016安全挑战赛cm7 Android CrackMe 分析详解

2016-4-4 22:07
8788

CM带OLLVM混淆,搞过android的同学们估计都知道这是一个什么玩意儿。一般来说,假如逆向需要的时间是100%,然后ida的F5插件可以降到20%,那么这个OLLVM就是可以把这20%的可能性给扼杀掉,顺便把时间提升到 10000%的神器。
    举个例子,正常函数的F5代码是这样的

    OLLVM混淆后的代码是这样的

    后面还有好长好长的一段,妈呀画面太美我不敢看
    在这里我想先解释一下这个OLLVM到底是一个什么样的东西,不然看着就只知道是一堆if-else判断,那么后面的分析就不用看了。
    看代码说话

    这是正常的求和代码,当然,我们可以脑洞一开,把它弄得复杂一点。

    怎么样,看懂了吗?看懂了的同学可以直接看下一part了。实际上,这个就实现的功能上来说是和上面的一样。简化一下可以变为这个样子。

    可以看到,函数执行的流程不再是由上到下的顺序流了,而是根据pc的值,动态得选择if块中的语句执行,同时把下一个if块的地址赋予pc指针。这个就是OLLVM大概的思路,当然,我这个是大大简化了的。对此,不得不说,城里人真会玩啊!!!
    咳咳,真实的语句被打乱,隐藏起来。通常,一个if块中只包含一句甚至是半句的指令,而逆向分析人员则不得不花费大量时间去整理程序执行的流程,提取真实的代码。这就是OLLVM的困难所在,也是其设计巧妙之处。
    而这个CM,也就利用了这个技术,把80%的逆向者阻挡了在门外。
    好了,既然知道了这么难,哪就散了吧,做不来的?对吧。如果这就放弃了,那么待得日后出了真正的VM,那么就是不是完全不可能搞定了?咳咳,在这里放弃还是有点早了,鼓起信心迎难而上吧。

    先看看CM的大致验证流程,首先是调用验证的地方0x000125F4 

    非常明显的校验,进去看看,可以知道主要有4个校验的地方。
    直接上F5代码




    首先是对密码进行base64解密放到v360N(8字节)处,然后对v360N进行rsa变换,接着是一个tea变换,得到(“360N”,CheckCode)结构的解码代码,最后对用户名进行hash,得到值与CheckCode比较,正确的话就返回成功。大致的流程是这个样子,这一部分的分析还是挺简单的,        然而要如何正确地分析这几个函数的时候才是困难所在,毕竟这几个变换都不是标准的算法。
    为了方便分析,先使用一组key
Name:360
Key:=6@LdGUI1qEN
    ①变形base64算法
    第一个变换是变形的base64变换。这有非常明显的特征,在进行密码测试时,解密长度变化为4变3,8变6,12变9。然而这又不是标准base64算法,毕竟第一个字符为’=’号。这也好办,只要在内存中dump出转换表,结合key算一下组合方法,就完事了。然而这才是难点所在,算法的代码是这样的。
    里面调用到 0x0000C6EC 这个地址进行真实的转换

    神马鬼,这么多的跳转,都跟踪到头晕了。其实这里就是真实的OLLVM,此时R0就是上面代码中的PC指针,然后这里就是一堆if - else 语句的跳转。

    这里则是算出下一步函数地址的地方。上一点的地方则是这一节的真实指令。
    因为这个函数体比较大,而且还有循环的指令,所以一步步跟踪起来代码可能会有上十万行。接下来就是耐心的比拼了,记住我们的目标,就是dump转换table,很简单,所以大可以一步一步地进行跟踪。当然,这并不是做好的方法。总体地看一下,OLLVM中,真实的代码是隐藏在if 的块里面,所以我们只需要从中dump出真实的指令出来就可以了。
    这方面的工作有不少人已经做过了,参考一下,可以写一个脚本来进行提取,脚本效果大致如下:

    类似于ida的跟踪功能,只是跳过了无用的跳转指令,顺便打印寄存器的变化。虽然代码依旧丑的很,不过可阅读性已经提高了不少了。以时间来说的话,就是把10000%的时间缩短到300%了。对于这个cm来说,这样就差不多了,好吧,上吧。
    因为base64里面有循环取出加密数据,取置换表,然后写解密数据的操作,所以我们优先找到取加密数据的位置,以及写解密数据的位置,那么在这之间的便是解密操作了。直接搜索dump出来的trace文件,查找传递进去的R0(未解密密码地址)的值。这里就是搜索4D7C8,得到:


    得到取pass数据的地址为DCD4,并且可以看到每次循环都是使用4个字节,从这个位置跟踪下去可以发现

    根据输入在内存中取表置换,对base64熟悉的同学应该知道这就是取表运算的地方,直接把内存中的表dump(0xBEA85108)出来,然后根据合法key的转换可以发现这个base64的组合和标准的base64是反序的。结果算法如下:

        这个算法和PYG上的随机base64算法十分相似,估计就是用同样的工具生成的。然后标准12字节变8字节,填充字节为1个,那么填充的字符自然就是最后的N了。
    ②标准rsa64算法
    Rsa算法部分最为简单,里面对base64解密的结果通过str2hex转换为字符串后,直接推送到解密函数处

    函数内没有任何混淆,直接分析即可。

    内存中的大数数据。

    以及将其转换为大数的函数。跟进去可以发现相关提示

    恩,是openssl的大数库。
    中间大数的各种加减乘除运算后得到模数n和指数e,然后对v360N进行rsa变换

    公钥解密算法,好在这里只是一个64bit的RSA(长一点就无解了),可以用工具来分解。


    ③tea变形算法
    接着是一个变形tea算法的解密算法。
    先对name进行hash,取得加密表,然后利用加密表对上一步得到的8字节密码进行tea解密,得到(“360N”,CheckCode)
    这里变形tea算法的求逆这里我们可以取巧,首先通过用户名计算出0x20的hash值,我们可以在加密算法中直接使用。这样就省去了逆向这个HASH算法。其次验证第二部分的数值第一个DWORD是固定值‘360N’,第二个dword是用用户名计算的一个hash值,这里我们也可以直接使用,同样地省去一步的逆向。估计这里是设计者由于比赛时间原因,故意留下的一些破绽。
    好,正式上吧。
    首先函数内会再次初始化一个寻址表addr,然后调用真正的解密函数。

    这里输入的R0,R1,R2数据如下
    R0,待解密的key, unsigned v[2]

    R1, 地址table -> addrtable, unsigned char addr[0x20]

    R2,nameHashTable, unsigned k[8]

    记录下来这几个地址以及数据,对后面的分析会大有帮助的。
    里面全是OLLVM混淆,直接跑脚本进行分析吧。
    直接搜索R0,R1,R2的地址,获取它的运算流程。
    初始化

    交换v[0]与v[1]的值,然后后面就是一个长0x20的大循环
    可以看到一次循环如下:

    循环开始,i=0,下一次经过的时候则会变为1

    取R0 = k[addr[0x1F-i]],得到中间值k1,用于后面的计算,
    I=0时,得到值DF6450CB,直接搜索这个值。

    K2 = chgR0(k1 + v[1]),chgR0这个函数后面再分析,现在搜索中间key,k2的值9EF4E7CC,其实就在下面一段。

      更新v[0],v[1]然后又喜闻乐见地开始下一个循环。
    好了,这个函数算是完了,翻译后c代码如下:

    那么就只剩最后一个unsigned chgR0(unsigned )函数了。
    依旧是跑脚本,此时注意将脚本的PC指针从R0切为R7
    这里以R0=17CD18FB为示例,跑脚本
    搜索17CD18FB,查找处理的地址

    首先是将输入的k每个字节取出来,放到内存BE92E294  --> uk中

    变成这个样子,因为当前SP为:BE92E1E8,而BE92E294-SP= AC,所以下面搜索AC,查找引用地方。

    取出uk数据,在根据置换表4C0D6取出相应的数据,保存在B6中。

    置换表如上,是一个[8][0x10]的置换表,相信大家都已经猜到是怎么转换的吧。
    所有数据转换完成以后,重新组合为unsigned F993DE9C
    最后还有移位,



    两者求或,完事,完整的c代码如下:

    于是,把整个算法逆一下,得到其加密算法如下:


    ④最后对用户名求hash,与上一步解密得到的CheckHash进行对比。这里没有逆下去,因为根据前面弄出来的算法,已经足够去求出一个有效key了。
    (⊙v⊙)嗯,由于时间关系,对于这个cm的分析也只能到此为止了,没能写出keygen,算是有点可惜。只能下次努力了。相信大家都会有个感觉,一开始总觉得这个cm很复杂,又是OLLVM,又是修改算法之类的。但是分析下来,就会发现这其实还是做得中规中矩的,并没有特别难,特别复杂的地方。而又不会特别简单以至于不需要分析就能弄懂其算法。当然,其中一部分的强度都是由OLLVM所提供的,这对于有心想要搞OLLVM的同学来说,相信还是能够从中学到不少东西的。
最后放出2组key
①F8LEFT
3Mbf#wOwS3%N
②CURRWIN
$IrLqsfZ$<XN
    上面分析中用到的脚本可以在我的GitHub上下载得到:
    https://github.com/F8LEFT/DecLLVM
    排版有问题的可以直接下载doc文档
分析.doc


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 4
支持
分享
最新回复 (11)
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
赞,楼主逆向功底相当厉害啊,佩服!
2016-4-4 23:26
0
雪    币: 53
活跃值: (106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
确实厉害,从windows到android都精通。
2016-4-4 23:44
0
雪    币: 4580
活跃值: (4009)
能力值: ( LV8,RANK:138 )
在线值:
发帖
回帖
粉丝
4
厉害!!
2016-4-5 03:28
0
雪    币: 250
活跃值: (65)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
膜拜楼主,感谢分享
2016-4-5 09:00
0
雪    币: 387
活跃值: (822)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
膜拜楼主
2016-4-5 10:08
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
路过,分析得很好
2016-4-5 11:49
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
佩服,佩服,看了感觉很受用啊
2016-4-5 14:33
0
雪    币: 3
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
啊啊、、顶礼膜拜!
2016-4-5 14:37
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
哎,我基础太差,没看懂
2016-4-5 15:01
0
雪    币: 35
活跃值: (139)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
分析的漂亮
2016-4-8 09:16
0
雪    币: 38
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
楼主 你好   可以讲解下GIT上DecLLVM脚本嘛?对py不熟悉   想了解下  脚本提取真实指令的过程.
2016-7-11 11:52
0
游客
登录 | 注册 方可回帖
返回
//