游戏安全实验室 首页 游戏漏洞 查看内容

【NGame破解版】Dll加壳保护方案分析

发布于:2017-6-14 15:38   |    211113次阅读 作者: 管理员    |   原作者: TP   |   来自: 原创

分析背景

NGame游戏海外版出现了破解版,该版本在dump出游戏的dll中不能直接通过反编译工具查看修改后的游戏代码,导致无法确定外挂修改的直接逻辑点。本文主要针对AssemblyCSharp.dll模版,分析其dll保护的方法。

分析过程

1、拿到Encrypt_Assembly-CSharp.dll拖进reflector中查看发现文件不能被解析提示说无效的COFF 头

2、用010Editor打开Encrypt_Assembly-CSharp.dll查看文件,如下:

熟悉MZ头后面This program cannot be run in DOS mode”还被改成了https://www.AndroidRepublic.org/网址,看看后面的数据,基本确定是PE格式了。看看这个网址,应该是这个组织游戏给hack了再加上壳的。

3、我们用010Editor来解析下这个PE文件,得到如下图:

可以得出DOS头通过e_lfanew解析出NT头,但是奇怪的是NT头却没有解析出Section,我们查看下NT头是否有不符合COFF格式的项。展开NT头,发现下面的Signature值有误,应该只是“PE”即 0x4550 两个字符,修改之。

修改后,重新运行下PE模板,就可以看到解析的Section了。再次拖进reflector去解析dll,发现有如下错误:

4、我们知道,DataDirectory是PE文件很重要的一个结构,在 IMAGE_OPTIONAL_HEADER下的最后的位置,一般NT头偏移+0x60位置,导入表,导出表,重定位表RVAsize都放在这里。正常DataDirectory16项,分别如下:

以前的第15项是 COM_DESCRIPTOR Directory RVA和size的,后来MS没有用这个,就把这个项装CLR信息了,也就是 .Net的所有信息。如果出现了reflector上面DataDirectory数目不对的问题,那应该就是反编译器读取DataDirectory项数的时候出现了问题,也就是IMAGE_OPTIONAL_HEADERNumberOfRvaAndSizes了,实质上应该0x10才对,修复之保存。

顺便查看一下我们要的CLR数据RVA和size信息:

RVA为0x2008,size为 0x48

5、拖reflector看看解析结果,如下:

出现允许非负情况,在这个时候,首先应该考虑到ILSpy的异常栈回溯查看问题,如下

可以采用log的方式观察ILSpy的Mono.Cecil里面的ReadAssemblyNameDefinition函数问题应该出在这里:

然而笔者觉得log应该也是看不清的但是唯一可以马上得出的两点结论是,metadata数量相关的索引被改成了负数导致越界。

6、一般笔者分析metadata利用CFF Explorer,把修复了部分的Encrypt_Assembly-CSharp.dll拖进CFF Explorer 中,发现了如下异常:

经验告诉我这个是Metadata HeaderNumberOfStream 改大,改回 5就行正常的CLR数据一般只有5个分别为#~,#Strings,#US#Blob,#GUID。

7、下面我们找到CLR的头去修复NumberOfStream,首先已知CLR头0x2008位置,这个是虚拟地址,现在SectionHeader里面看看我们的这个虚拟地址落在上面:

原来是.text段(其实一般也是这个段中),根据虚拟地址0x2000和文件偏移的基址0x200转换下虚拟地址0x2008文件地址,得到其文件偏移为 0x208查看这个位置的数据,如下:

72个字节的结构是这样的:

NumberOfStreamMetaData里面IMAGE_DATA_DIRECTORY结构就是RVA和size组成的所以,CLR头也就是.net目录结构偏移 +8位置可以得到MetaData的RVA为0x2F4E6C,转换成文件地址为 0x2F4E6C – 0x2000 + 0x200 = 0x2F306C我们0x2F306C位置看看:

熟悉BSJB出现在眼前,这个就是Metadata Header。红圈部分就是NumberOfStreams修改成5即可,保存。

8、拖进CFF Explorer正常解析了然后结果如下图:

9、这个时候用反编译器还是不能解析的,因为游戏逻辑是保存在#~中的,那么我们进入#~里面的Tables看看是否解析成功,发现CFF Explorer卡死和预期一样。正常dll文件应该在点击Tables的时候会显示出每一个Table及其

这里说一下MaskValid的意义,把这个值变成二进制表示为:

上面的最右边(最低位索引00,该值为 1,表示存在该表(为0即表示不存在,该表名为Module,如下:

其余类推。统计了一下,总共24个1。是不是理论上会有24个存在呢?其实不是的,细心的读者会发现第43个1没有对应表,所以0x1E093FB7BF57只能代表23个表。

10、我们看看#~保存的表位置:

可以看到,在MetaData头偏移 +0x6C 位置保存着我们的#~的header也就是0x2F306C + 0x6C = 0x2F30D8 位置。如下蓝色覆盖的地方为我们的#~的header:

紧接header的是23个tables,顺序4字节为单位存储每个table项数, 如上图红色的地方。仔细观察里面的23个DWORD,会发现三个数据出现了问题其中有两个是负数,如下:

这个时候很容易就想到了为什么reflector会出现这样的情景:

其实很容易能够想到只要把这三个数据的高位字节(小端存储patch成00就可以了,然而抱着严谨的态度我们还是去看看NGame破解版libmono.so到底是怎么解析这一块数据的查看开源的mono代码找到相关的解析位置load_tables然后反汇编libmono.so即可,如

这个函数破解版和原版的解析方式是一致的可以看出load_tables取了低位24个字节。而到了这里我们可以知道reflector和ILSpy解析32个字节所以导致出错了我们把这三个数据的高位字节patch00,保存下。

11、reflector或者ILspy查看修复后的Encrypt_Assembly-CSharp.dll如下:

修复完毕。


原理总结

外挂针对dll的保护处理主要包括如下四个方面:

1、修改NT头的Signature。

2、修改IMAGE_OPTIONAL_HEADERNumberOfRvaAndSizes。

3、修改CLR头指向MetaData中的NumberOfStream

4、修改MetaData指向#~堆中的tables数据项数。

外挂保护dll工作本质还是对抗主流的反编译器,防止其他对外挂进行分析实质上mono源码基本没有进行的修改。只要掌握一定的PE和.Net文件结构格式知识,就可以直接修复被修改的数据。

外网也存在一些修改elf文件的so保护机制针对的是链接视图甚至是执行视图的修改,也是防止静态分析工具如IDA等进行分析,但是本质也是没有linker所需要用到的数据。


 *转载请注明来自游戏安全实验室(GSLAB.QQ.COM)

分享到:
踩0 赞4

收藏

上一篇:【漏洞挖掘教程】文本校验类风险

最新评论
引用 Brian 2018-1-30 10:13
你好 我第一次尝试反编译一个加密的游戏dll

我按照您的方法 一步步恢复了NT header 和 metadata stream

然后reflector 显示object reference not set to an instance of an object

想问一下这种情况下一步该怎么办
引用 55666788 2017-11-3 17:43
感谢大大分享,

大大能另写一个这类加密的教程吗?

本人想学这种方法,但技术不佳,向过国外的此修改论坛请教,但他们不对外教授,所以一直学不到技术



另外还有一种是修改.so档, 但他们不是直接修改该档,而是创建一个新.so档来达到修改效果(并加密了该档),这种方法也想学到
引用 404228858 2017-7-1 00:40
请问这个是用什么加壳软件加壳的
引用 Clumsybird 2017-6-29 20:41
郁闷我这个比你还要蛋疼,你改的那些我都知道,我这个他把.rsrc节给干掉了,不知道怎么还原唉,看看你的文章看有办法没有!
引用 New 2017-6-28 00:38
學習,

查看全部评论(5)

B Color Image Link Quote Code Smilies

发表评论

top 问题反馈

返回顶部