首页
社区
课程
招聘
[原创]浅析android手游lua脚本的加密与解密
发表于: 2017-4-11 16:01 114918

[原创]浅析android手游lua脚本的加密与解密

2017-4-11 16:01
114918

2018.05.02更新

        这段时间在翻备份的硬盘,突然发现了以前的分析项目和代码,从里面提取了之前附件的内容,现在上传给大家,真是柳暗花明又一村啊。附件包括201703版本的梦幻手游里面提取的so文件和一些加密后的资源文件(包括lua脚本),并包括了2个扑鱼APK文件,最后还打包了解密代码,供大家参考。

        附件太大,快100MB,上传不来论坛,我又放到百度网盘了......

        链接:https://pan.baidu.com/s/1DVgH0qHYPkiHBIiV2UsU7g 密码:ipt3


2018.04.09更新

附件是真的找不到了, 大家主要理解思路吧。百度网盘的附件好多朋友都下载和保存过,能不能发一份到论坛上传?感谢感谢~


2017.04.15更新

1. 在编辑过程中,5.1后半段内容(解密和反编译部分)被删除了,现在补上。

2. 在3.3里说到,“修改lua项目中的opcode后,编译生成lua.exe再替换到反编译目录下,就可以反编译”,这一句是错误的,正确是“修改lua项目中的opcode后,重新编译反编译工具luadec51项目,就可以反编译了”,已经修改。


0.前言

     

    主要用到的工具和环境:

     在学习lua手游过程中,本人遇到的lua文件大部分是这3种。其中lua是明文代码,直接用记事本就能打开,luac是lua编译后的字节码,文件头为0x1B 0x4C 0x75 0x61 0x51,lua虚拟机能够直接解析lua和luac脚本文件,而luaJIT是另一个lua的实现版本(不是原作者写的),JIT是指Just-In-Time(即时解析运行),luaJIT相比lua和luac更加高效,文件头是0x1B 0x4C 0x4A。


    


     luajit:

     一般有安全意识的游戏厂商都不会直接把lua源码脚本打包到APK中发布,所以一般对lua脚本的保护有下面3种:


     这种情况是指打包在APK中的lua代码是加密过的,程序在加载lua脚本时解密(关键函数luaL_loadbuffer ),解密后就能够获取lua源码。如果解密后获取的是luac字节码的话,也可以通过反编译得到lua源码,反编译主要用的工具有unluac和luadec51,后面会具体分析。


     因为反编译的结果并不容易查看,所以这种情况能够较好的保护lua源码。这个情况主要是先解密后反编译,反编译主要是通过luajit-decomp项目,它能够将luajit字节码反编译成伪lua代码。


     这种情况主要是修改lua虚拟机源码,再通过修改过的虚拟机将lua脚本编译成luac字节码,达到保护的目的。这种情况如果直接用上面的反编译工具是不能将luac反编译的,需要在程序中分析出相对应的opcode,然后修改lua项目的opcode的顺序并重新编译生成反编译工具,就能反编译了,后面会具体分析。     


     一般上面的情况都会交叉遇到。


     这里主要介绍4种方法,都会在第5节中用实例说明。


     这种方法需要把解密的过程全部分析出来,比较费时费力,主要是通过ida定位到luaL_loadbuffer函数,然后往上回溯,分析出解密的过程。


     这里主要通过ida动态调试so文件,然后是定位到luaL_loadbuffer地址,游戏会在启动的时候通过调用luaL_loadbuffer函数加载必要的lua脚本,通过在luaL_loadbuffer下断点 ,断下后就可以运行idc脚本将lua代码导出(程序调用一次luaL_loadbuffer加载一个lua脚本,不写idc脚本的话需要手动导N多遍.....)。


     跟4.2原理一样,就是通过hook函数luaL_loadbuffer地址,将代码保存,相比4.2的好处是有些lua脚本需要在玩游戏的过程中才加载,如果用了4.2的方法,游戏过程中 中断一次就需要手动运行一次idc脚本,而且往往每次只加载一个lua文件,如果是hook的话,就不需要那么麻烦,直接玩一遍游戏,全部lua脚本就已经保存好了。


     这里主要是opcode的顺序被修改了,需要用ida定位到虚拟机执行luac字节码的地方,然后对比原来lua虚拟机的执行过程,获取修改后的opcode顺序,最后还原lua脚本。


     好了,下面用3个例子来说明上面的情况。


    

     一直向上回溯(交叉引用 ),来到下图,发现解密的密钥和签名,其中xiaoxian为密钥,XXFISH为签名

    

 

    接下来直接写解密函数(在cocos2d-x项目里面写的解密函数,很多工具直接可以调用)

    

    解密后的文件如下:

 

    lua版本为5.1


    luajit版本为2.1.0


    反编译本人用到的是luajit-decomp,这里需要注意,luajit-decomp默认的lua版本为5.1,luajit版本为2.0.2,我们需要下载对应lua和luajit的版本,编译后替换luajit-decomp下的lua51.dll、luajit.exe、jit文件夹。反编译时需要注意的文件和文件夹:

    

    这里需要下载版本为2.1.0-beta2的luajit,并且编译生成文件后,复制LuaJIT-2.1.0-beta2\src路径下的lua51.dll、luajit.exe文件和jit文件夹覆盖到luajit-decomp目录中。luajit-decomp用的是autolt3语言,原脚本默认是只反编译当前目录下的test.lua文件,所以需要改一下decoder.au3文件的代码。修改后的代码另存为jitdecomp.au3文件,编译后为jitdecomp.exe。并且增加了data目录,目录下有3个文件夹,分别为:


     将解密后的文件放到luajit文件夹,运行 jitdecomp.exe,反编译的结果在out目录下,结果如下:


5.2 捕鱼达人4


     接着,ida加载libcocos2dlua.so文件,定位到函数luaL_loadbuffer,可以在函数中直接搜索,也可以字符串搜索"[LUA ERROR]"来定位到函数中,函数分析如下:


     所以在ARM汇编中,参数R0为lua_State指针,参数R1为脚本内容,R2为脚本大小,R3为脚本的名称,写一段IDC脚本dump数据即可:


     ida动态调试so文件网上有很多文章,这里就不详细说明了。通过idc脚本获取的部分数据如下:


5.3.梦幻西游手游



 

    这里需要实现Lrc4解密的相关函数,还有Lzma解压函数需要自己实现,其他几个都是cocos2d平台自带的函数,直接调用就可以了。上面的流程图实现的函数如下:


     解密函数过程如下:


     decrypt()实现代码如下:


    Lrc4结构如下:


     其他函数的具体实现请看DecryptData_Mhxy.cpp文件,这里就不贴代码了。解密后的文件如下:


     可以看出,解密后的文件为luac字节码,但是这里直接用反编译工具是不能反编译luac字节码的,因为游戏的opcode被修改过了,我们需要找到游戏opcode的顺序,然后生成一个对应opcode的luadec.exe文件才能反编译。下表为修改前后的opcode:


     lua虚拟机的相关内容就不说明了,百度很多,这里说明下如何还原opcode的顺序。首先需要定位到opmode的地方,IDA搜索字符串"LOADK",定位到opname的地方,交叉引用到代码,找到opmode:


     off_B02CEC为opname的地址,byte_A67C00为opmode的地址,进入opmode地址查看:


     源码用了宏,计算出来的结果就是上表中opmode的结果。这里对比opmode就可以快速对比出opcode,因为opmode不相等,那么opcode也肯定不相等,到这一步,已经能还原部分opcode了,因为有一些opmode是唯一的。比如下面几个:


     接下来就需要定位到luaV_execute函数,然后对比源码来还原其他的opcode,直接IDA搜索字符串"initial value must be a number"可以定位到luaV_execute 函数,再F5一下。接着打开lua源码中的lvm.c文件,找到luaV_execute函数,就可对比还原了。lua源码和IDA F5后的代码其实差别还是有的,而且源码用了大量的宏,所以源码只是用来参考、理解lua虚拟机的解析过程,本人在还原的过程中,会再打开一个没有修改opcode的libcocos2dlua.so文件,这样对比查找就方便多了。

     最后修改lua源码 lopcodes.h中的opcode、lopcodes.c的opname和opmode,重新编译并生成luadec51 .exe(需要将lua源码中的src目录放到luadec51的lua目录下才能编译),就OK了,写个批处理文件就可以批量反编译。一个文件反编译的结果:


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

最后于 2018-7-10 19:32 被littleNA编辑 ,原因:
收藏
免费 7
支持
分享
打赏 + 21.00雪花
打赏次数 3 雪花 + 21.00
 
赞赏  一位没有留下痕迹的看雪读者   +10.00 2021/01/07 可以的话加一下QQ331238483.合作生意 长期买卖。啥也不说了
赞赏  wx小白   +10.00 2020/01/17
赞赏  CCkicker   +1.00 2017/05/08
最新回复 (63)
雪    币: 1039
活跃值: (355)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢分享
2017-4-11 16:08
0
雪    币: 4522
活跃值: (2146)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
谢谢分享  赞一个
2017-4-11 16:45
0
雪    币: 3492
活跃值: (4624)
能力值: ( LV13,RANK:437 )
在线值:
发帖
回帖
粉丝
4
竟然有我梦幻的,必须赞
2017-4-11 17:13
0
雪    币: 7001
活跃值: (4212)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
厉害了我的哥,  谢谢分享
2017-4-11 19:28
0
雪    币: 57
活跃值: (386)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
支持
2017-4-12 11:47
0
雪    币: 1692
活跃值: (2292)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
厉害了我的哥期待下一篇文章
2017-4-12 22:45
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
8
我也看的腾讯那文章,并没有什么卵用,楼主要是早点写,我就懒得自己搞了。。。
2017-4-17 09:42
0
雪    币: 12685
活跃值: (4289)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
谢谢分享~~
2017-4-18 01:45
0
雪    币: 182
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼主,可以留个联系方式吗?我有一个apk  反编译的问题想请教,有偿。我的联系方式是229605841.
2017-4-18 09:06
0
雪    币: 6112
活跃值: (1212)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
11
厉害了我的哥期待下一篇文章 
2017-4-21 10:23
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢分享~~
2017-4-21 10:52
0
雪    币: 6094
活跃值: (3077)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
支持一下!
2017-4-22 03:56
0
雪    币: 783
活跃值: (1121)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
14
luajit反编译出来了的.根本看不懂..而且隔空调用有时候还有问题.师傅是怎么解决的.
2017-4-22 19:31
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
luajit反编译出来的代码可读性实在是太差劲了。
有没有更好的反编译工具?
还有,luajit反编译出的代码,修改后能够再编译成luajit吗
2017-4-24 11:08
0
雪    币: 516
活跃值: (797)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
16
bambooqj luajit反编译出来了的.根本看不懂..而且隔空调用有时候还有问题.师傅是怎么解决的.
确实本文章中的luajit反编译工具反编译的结果很难看,这个我也在研究,你可以试试  @笨笨雄  版主那篇文章中的其他反编译工具。
2017-4-24 22:10
0
雪    币: 516
活跃值: (797)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
17
xxRea luajit反编译出来的代码可读性实在是太差劲了。 有没有更好的反编译工具? 还有,luajit反编译出的代码,修改后能够再编译成luajit吗[em_41]
是的,这个工具不是很好用,你可以试试    @笨笨雄    版主那篇文章中的反编译工具。
反编译出来的代码应该都有各种问题吧,如果没有问题的话那就可以直接用,luajit是支持明文脚本的;如果反编译的结果有问题(编译不再通过),那只能修改luajit的汇编代码了,再生成文件。以上都还只是理论,我没有试过。
2017-4-24 22:28
0
雪    币: 783
活跃值: (1121)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
18
市面上大部分luajit的工具  github能找的  宝宝都试过了..全部基于线性扫描.优化之后的可读性.仍然很差..什么时候能编程.ILCODE转C#的效果就很厉害了.
2017-4-25 15:16
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
19
bambooqj 市面上大部分luajit的工具 github能找的 宝宝都试过了..全部基于线性扫描.优化之后的可读性.仍然很差..什么时候能编程.ILCODE转C#的效果就很厉害了.
做肯定能做的,就是没有经济利益,基本都是坑。讲道理,看雪要是能把各种坑掉的项目都接手继续做下去,就可以圈更多的用户了
2017-5-2 09:42
0
雪    币: 268
活跃值: (3233)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
问下楼主,,梦幻你修改的lua源码lopcode.c哪个版本的,,我对比了一下5.1.3的,,区别很大。。感觉不太对~~求指点点
2017-5-17 16:42
0
雪    币: 516
活跃值: (797)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
21
gtict 问下楼主,,梦幻你修改的lua源码lopcode.c哪个版本的,,我对比了一下5.1.3的,,区别很大。。感觉不太对~~求指点点
5.1.5,里面的代码放到了lopcodes.def和lopmodes.def文件,修改下就好了。
另外直接修改opcode和opmode达到的效果不好(存在bug),想到另外一种方式(在加载code之后再替换),而且反编译工具luadec有一些bug,目前正在写相关的文章,之后会发上来。
2017-5-20 22:08
0
雪    币: 191
活跃值: (195)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
22

网上jit的资料太少了,之前看见jit都害怕,现在看着楼主写的感谢爽多了,谢谢分享,好东西啊,收藏了

2017-5-21 10:00
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
关于对解密lua后的实际应用能写一个栗子嘛?
2017-6-2 22:14
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
必须点个赞
2017-6-21 00:06
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
  连接挂了  能传一份吗
2017-6-23 10:23
0
游客
登录 | 注册 方可回帖
返回
//