xiaoxin520 发表于 2015-9-6 00:43

三战分析全民奇迹

本文作者:七少月注:本文为论文性质,请勿转载,作者为七少月;本文涉及的所有游戏均为加密解密技术学习讨论,勿用于其他任何用途,否则与本人无关!!!!
很多人目前都希望了解有关加密解密,加壳脱壳的内幕,或教程,或知识。很抱歉的告诉大家,目前这些东西估计很难学到,会的也不会透漏。因为很多原因,总之是不便发出。在写这篇文章前,我也有很多思想斗争和担心,但还是决定拿捏尺寸,适度写出来,本文只是为了技术交流,勿用于任何用途,否则与作者无关。对应APK脱壳什么的,我是真的不能出教程,可能让大家要失望了,因为繁华也说了,安卓这一块外国是几乎没有壳的,和电脑端的恰恰相反,电脑端的壳大部分是外国,国家或相关权威部门都支持脱壳,而安卓这块外国由于一些大家都知道的问题,他们不会进行代码的盗取,盗版等,恰恰只有国内才兴起加壳加固,所以往往是360,百度,爱加密等,一些大牛本身就在这些单位工作,就更不可能透露核心技术了。所以,我希望还是死心吧。但是,U3D这一块的解密,我不敢说自己是第一个做的,不过也是较早进行尝试和突破关键点的,拥有很大意义上的独立研究版权,比如0X71异或解密的第一个工具实现。我会掌握分寸,共享一些,让大家共同学习和研究,当然,我承认确实是有一定的证明自己实力的意图,希望借此可以引起相关单位对我的支持,但那不是重点,至少我不是很看重,正如我想说,“人应无名,以便安心练剑”。好了,下面我就以全民奇迹为例,说一说加密DLL的问题。全民奇迹,这个游戏肯定都很熟悉,这篇文章就仅从技术层面上,对它的加密算法及相关做一个简要的分析。全民奇迹大体上如果从加密来看,可以分为1.4,1.5,1.6三个时代。三个时代的加密都有自己独立的特色,然而不变的是,每一代全民奇迹都是把解密算法写在了libmono.so的mono_image_open_from_data_with_name函数中。本文的角度是从静态分析为主,主要锻炼加密解密算法的分析能力,而不是用动态调式像脱壳那样直接把壳脱下了。关于U3D游戏的动态加载加密DLL的动态调式和脱壳,我已经在上文《U3D动态调式和脱壳DLL》中为大家把框架展示了出来,有兴趣可以看看。1. 全民奇迹1.40时代这个游戏是U3D开发的不错的游戏,然后它的诞生让我格外引起重视,因为自它诞生开始就注定了一个时代的结束,这个时代就是U3D的DLL再也不是裸奔,丝毫没有保护了,然后拿到reflector中就可以为所欲为了。全民奇迹是第一个进行DLL加密的游戏,那时我和法总他们都有些目瞪口呆,因为第一次发现DLL放到reflector中出现“它不包含MZ头”的错误提示,接着利用winhex打开Assembly-csharp.dll,是下面这种情况:而上文所提到的不包含MZ是什么意思呢,DLL是PE文件,PE文件头的标识位就是MZ。如果没有MZ头,则会认为这个文件不是PE文件,其实意思就是这个PE文件被处理了,有可能混淆,有可能是重写移位,也可能是加密。在电脑领域上,重写移位比较多,也就是利用OD和汇编把PE文件头改造,甚至删除,然后重写在其他区段,再以汇编连接。这种手法常用于免杀,被称为PE文件头免杀,也是中高层技术,PE文件格式及结构也是系统安全领域和免杀技术领域很重要的一块,不熟悉的可以看我的《七少月免杀第一季教程》。而在安卓端,出现这种情况,我们往往是认为被加密了,先来看一看正常的Assembly-csharp.dll文件的HEX:从这里,我们可以看出,4D5A就是MZ头。如果你领悟能力高一点,立刻就会明白,既然是文件格式头,那么只要是DLL或PE文件,可能在前面几十行的HEX应是类似的。这种想法是对的。那么,这有什么作用,我们再看看全民奇迹1.4的加密DLL的HEX,其实你可以发现这种加密是很简单的,凡是原本该00的HEX全部是71,而且两个本来一样的HEX,加密后还是一样,比如第一行的C和D,原来都是FF,加密后都是8E。这告诉我们,这种加密是非常简单的,没有任何的位移替换等,只是把原本的HEX操作数进行一定算法变为另一个而已。我们拿出三个HEX十六进制数对比一下:4D------3C;5A--------2B;00----------71。把它们转为二进制,不难发现,就是进行按位对71进行异或。当然,后来发展为按列异或,隔位异或,等等,但原理一样。而目前,这种简单异或方式已很少使用,但它是一个里程碑,具有重大意义。接下来,我们要找到这个DLL是在哪里解密的呢,找到libmono.so的那个mono_image_open_from_data_with_name关键函数,我们很容易看到以下代码:我分析过 unity3d的mono源码,原生的这个函数中,是不存在任何循环结构体,当然更没有异或,所以这个地方就是重写mono框架,加入解密算法的地方。下面就是动态调式也好,LOG输出也好,静态分析也好,总之最后就能确定这种加密算法就是先把文件转化为byte字节流,然后按位对0x71进行异或。这种加密是对称加密,所以加密一次是加密,加密第二次就是解密,也就是说加密和解密的代码是一样的,关键代码如下,这里我采用的是java,不过在这里要感谢一个逆向未来的朋友,受他的启发,后来我用C#修改重写为工具。我们可以做成工具,进行解密DLL,当修改完后,再点击解密即为加密,替换原DLL: 至此,还并没有结束,我又做了几个实验,其实最重要的是实验的能力和方向的确定,当然这个需要长期的经验。我比较了全民奇迹1.4.0和1.4.3两个版本的libmono.so,发现关键函数及解密算法处是一致的,更大胆一点,进行替换,游戏可以正常打开。再比较1.5.0的libmono.so发现相关代码处存在很大差别,也不能进行替换。2. 全民奇迹1.5时代随着技术发展,异或71加密已经被淘汰,接着你会看到DLL的HEX发生变化,如下:这个非常有意思,应该是特别有意思,如果是新手,你可能觉得,这太简单了,通过观察,除了第1个HEX和正常的DLL的HEX不一样,后面好像是一样的。很多人直接把43改为4D,然后放到reflector中,结果当然是报错,错误是什么呢?变为大概是什么签名错误,这就告诉我们,首先它是处理了加密了,其次即使解密了,也可能需要修复。由于目前该游戏依然是使用这种加密方式,更多细节就不便讲下去,这里我只从代码和算法的技术角度来看一下。我们依然是到libmono.so的关键函数,我在下面图中标注了几处,尤其是函数EncryptXor2是重点,有兴趣可以跟下去分析,还是那句话,我不便多说:我在全民1.5时代里,依旧做了实验,来确定dll解密算法的位置,这次我同时使用1.5.0版本,只不过一个是百度版,一个是360版,我发现两者libmono.so中的关键函数代码一模一样,替换后,游戏都能正常运行,可以进行互换。3.全民奇迹1.6时代这个时代的全民奇迹加密算法和1.50是相同的,然而不同的是,你会发现它多了一些.mdb文件。如下图:.mdb是数据库ACCESS的文件,明显这是个幌子,用HEX打开如下:那么这个文件到底是什么,用来干什么,它加进来这种机制起到什么样的保护呢?我认为,这是一个备份文件,是Assembly-csharp.dll的另一种形式的备份文件,作用当然是增强稳定性,更主要是防修改。为此,我做了一个实验,我将原来的Assembly-csharp.dll删掉,换为一个没有加密的其他游戏的Assembly-csharp.dll,果然不出我所料,一般而言,这游戏肯定是不能运行了,但全民奇迹依然很正常运行着。这就告诉我们,这个.mdb其实就是Assembly-csharp.dll的备份加密文件。我们来到libmono.so中再看看:看了我标记的几个地方,已经很明白了,整个函数意思是copy,就是拷贝,它是什么的拷贝?是对应DLL的拷贝,依然那句话,我不好再多说更多,只能说,跟下去你能发现这个mdb文件是怎么达到备份功能,并当DLL确实出问题,或被检测验证异常时,如何解密拷贝放到内存中,成为DLL进行正常并按原本运行的。最后,来一个图片: 郑重声明:本文仅以技术讨论为目地,请勿用于任何用途!!!!

99399233 发表于 2015-9-9 19:47

haowanggw 发表于 2015-9-6 00:49

沙发,看不懂是什么   不过知道楼主辛苦了

吾爱メ加油 发表于 2015-9-6 01:27

前排 技术文 会火吗?

dywj505 发表于 2015-9-6 01:43

确实牛!!!你可以把这个游戏一下子整垮了~~~

贴纸笔墨 发表于 2015-9-6 09:41

文字太多没有看完我只想知道有没有成品 感谢分享

z6810753 发表于 2015-9-6 09:44

感谢七少|~期待更多精彩文章。。。

风雨飘摇 发表于 2015-9-6 09:49

谢谢分享

MistyRain 发表于 2015-9-6 11:49

gudantegong 发表于 2015-9-6 18:46

支持支持

penghui754 发表于 2015-9-6 19:16

牛B甩甩,下次估计又要更新了
页: [1] 2 3 4
查看完整版本: 三战分析全民奇迹