放置江湖html5源码,codearchive/reverse/放置江湖 at master · crazyyao0/codearchive · GitHub...
放置江湖
000
放置江湖是深圳小猴跳跳出品的一款文字类武侠Mud游戏。我在TapTap上下载的。玩了之后一下子就触动了我一段久远的记忆。这个游戏非常像我高中时候在文曲星上玩得叫gmud的游戏。记得当时花了非常多的时间在这个游戏上(其实是因为上课太无聊)。当时的文曲星用的是2032的纽扣电池,一节电池要5块钱。我在这个游戏上用光了几十节电池。那时候为了能干掉武学修为达到返璞归真级别的张三丰,我开始修改游戏。从修改游戏数据到修改游戏图片到直接修改游戏代码。最后我练就了可以人肉6502指令集的汇编和反汇编技术。我会把大段代码抄在纸上分析,然后改完以后再写回到Rom里。现在想想真是疯狂啊。
言归正传。我玩了几天后发现网上的攻略都没有具体数值。于是想把这个游戏拆开看看。
001
放置江湖目前只能通过TapTap下载. 在TapTap里设置禁用自动删除安装包后, 游戏安装包可以在下面这个位置找到。
Android/data/com.taptap/files/Download/taptaptmp/
下载安装包后解压缩。首先看到的是这个文件
lib/armeabi/libcocos2dlua.so
看来游戏应该是基于cocos2dx的。随后在assets目录下发现了很多lua脚本以及图片资源。图片没有加密,直接都可以看到,但这不是我想要的。随便打开一个Lua脚本。看到如下内容
不认识这个文件。网上搜索ABCTJM也没有发现任何线索。看一下每个字节出现的频率
这个文件不是压缩了就是加密了。加密的可能性更大一些。鉴于lib下的那个文件的文件名是libcocos2dlua.so,这些扩展名是lua的文件应该是处理过的脚本文件。现在目标是弄明白这个文件是怎样压缩和加密的。不用废话了,直接开始反汇编吧。
objdump -CT libcocos2dlua.so > fzjh.sym
objdump -Cd libcocos2dlua.so > fzjh.asm
从cocos2d::cocos2dVersion()看到如下反汇编:
007364f8 <:cocos2dversion>:
7364f8:4801ldrr0,[pc,#4]; (736500 <:cocos2dversion>)
7364fa:4478addr0,pc
7364fc:4770bxlr
736500地址的值是47F533。将这个值加上7364fe等于BB5A31
这里就是版本号了。可以看到版本号是cocos2dx 3.9。来到cocos2dx的github上把3.9下载下来开始对照代码读汇编,效率果然高。
https://github.com/cocos2d/cocos2d-x
通过在符号表中搜索"key", "decrypt"等关键字,很快就找到了一些线索。
cocos2d::LuaStack::executeScriptFile() 会调用 cocos2d::LuaStack::luaLoadBuffer() 然后调用了 xxtea_encrypt()进行解密。貌似对lua加密是cocos2dx内置的功能。
int LuaStack::executeScriptFile(const char* filename)
{
CCAssert(filename, "CCLuaStack::executeScriptFile() - invalid filename");
std::string buf(filename);
//
// remove .lua or .luac
//
size_t pos = buf.rfind(BYTECODE_FILE_EXT);
if (pos != std::string::npos)
{
buf = buf.substr(0, pos);
}
else
{
pos = buf.rfind(NOT_BYTECODE_FILE_EXT);
if (pos == buf.length() - NOT_BYTECODE_FILE_EXT.length())
{
buf = buf.substr(0, pos);
}
}
FileUtils *utils = FileUtils::getInstance();
//
// 1. check .lua suffix
// 2. check .luac suffix
//
std::string tmpfilename = buf + NOT_BYTECODE_FILE_EXT;
if (utils->isFileExist(tmpfilename))
{
buf = tmpfilename;
}
else
{
tmpfilename = buf + BYTECODE_FILE_EXT;
if (utils->isFileExist(tmpfilename))
{
buf = tmpfilename;
}
}
std::string fullPath = utils->fullPathForFilename(buf);
Data data = utils->getDataFromFile(fullPath);
int rn = 0;
if (!data.isNull())
{
if (luaLoadBuffer(_state, (const char*)data.getBytes(), (int)data.getSize(), fullPath.c_str()) == 0)
{
rn = executeFunction(0);
}
}
return rn;
}
int LuaStack::luaLoadBuffer(lua_State *L, const char *chunk, int chunkSize, const char *chunkName)
{
int r = 0;
if (_xxteaEnabled && strncmp(chunk, _xxteaSign, _xxteaSignLen) == 0)
{
// decrypt XXTEA
xxtea_long len = 0;
unsigned char* result = xxtea_decrypt((unsigned char*)chunk + _xxteaSignLen,
(xxtea_long)chunkSize - _xxteaSignLen,
(unsigned char*)_xxteaKey,
(xxtea_long)_xxteaKeyLen,
&len);
r = luaL_loadbuffer(L, (char*)result, len, chunkName);
free(result);
}
else
{
r = luaL_loadbuffer(L, chunk, chunkSize, chunkName);
}
return r;
}
仔细读了一下源代码,发现密钥 xxteaKey必须要通过调用setXXTEAKeyAndSign()方法来设置。但是奇怪的是全局搜了都没有找到有调用过这个函数的地方。寻找密钥的过程在这里遇到了第一个困难。
002
回来继续看反汇编代码。因为objdump对arm的代码识别不怎么好,所以里面有很多错误的symbol。这个需要注意识别。比如说cocos2d::TextureAtlas::increaseTotalQuadsWith(int)+0xf54 就完全不知所云。而在源代码里面这里写的是strncmp()。进去看了一下,这个地方有点像plt table,但又不是plt。最糟糕的是那里应该是ARM指令而不是Thumb指令,objdump完全搞错了,所以没有办法深究了。
00471f7c <:luastack::lualoadbuffer const>:
471f7c:b5f0push{r4,r5,r6,r7,lr}
471f7e:1c1e addsr6,r3,#0
471f80:7f03 ldrbr3,[r0,#28]
471f82:b087subsp,#28
471f84:1c05 addsr5,r0,#0
471f86:1c0f addsr7,r1,#0
471f88:1c14 addsr4,r2,#0
471f8a:2b00cmpr3,#0
471f8c:d013 beq.n471fb6 <:luastack::lualoadbuffer const>
471f8e:6ac3 ldrr3,[r0,#44]; 0x2c
471f90:6aa9 ldrr1,[r5,#40]; 0x28
471f92:1c10 addsr0,r2,#0
471f94:1c1a addsr2,r3,#0
471f96:9303strr3,[sp,#12]
471f98:f298 fd46bl70aa28 <:textureatlas::increasetotalquadswith>
471f9c:2800cmpr0,#0
471f9e:d10a bne.n471fb6 <:luastack::lualoadbuffer const>
471fa0:9b03 ldrr3,[sp,#12]
471fa2:9005strr0,[sp,#20]
471fa4:6a2a ldrr2,[r5,#32]
471fa6:18e0 addsr0,r4,r3
471fa8:ac05addr4,sp,#20
471faa:1af1 subsr1,r6,r3
471fac:6a6b ldrr3,[r5,#36]; 0x24
471fae:9400strr4,[sp,#0]
471fb0:f08c fb50bl4fe654
471fb4:e00c b.n471fd0 <:luastack::lualoadbuffer const>
471fb6:2300movsr3,#0
471fb8:1c20 addsr0,r4,#0
471fba:1c31 addsr1,r6,#0
471fbc:9305strr3,[sp,#20]
471fbe:f7e5 fdebbl457b98 <:isencrypted char>
471fc2:2800cmpr0,#0
471fc4:d010 beq.n471fe8 <:luastack::lualoadbuffer const>
471fc6:1c20 addsr0,r4,#0
471fc8:1c31 addsr1,r6,#0
471fca:aa05addr2,sp,#20
471fcc:f7e5 fe92bl457cf4 <:decrypt char>
471fd0:1c05 addsr5,r0,#0
471fd2:9a05 ldrr2,[sp,#20]
471fd4:1c38 addsr0,r7,#0
471fd6:1c29 addsr1,r5,#0
471fd8:9b0c ldrr3,[sp,#48]; 0x30
471fda:f298 fb03bl70a5e4 <:textureatlas::increasetotalquadswith>
471fde:1c04 addsr4,r0,#0
471fe0:1c28 addsr0,r5,#0
471fe2:f297 fe2bbl709c3c <:textureatlas::increasetotalquadswith>
471fe6:e006 b.n471ff6 <:luastack::lualoadbuffer const>
471fe8:1c21 addsr1,r4,#0
471fea:1c38 addsr0,r7,#0
471fec:1c32 addsr2,r6,#0
471fee:9b0c ldrr3,[sp,#48]; 0x30
471ff0:f298 faf8bl70a5e4 <:textureatlas::increasetotalquadswith>
471ff4:1c04 addsr4,r0,#0
471ff6:1c20 addsr0,r4,#0
471ff8:b007addsp,#28
471ffa:bdf0pop{r4,r5,r6,r7,pc}
认真看了一遍才发现,这个竟然和cocos2dx的源代码不一样。看来小猴跳跳的人是修改了cocos2dx的源代码。他们没有使用原先解密方法,取而代之的是调用了一个JM::decrypt()的方法。确认传入的三个参数分别为密文,密文长度和明文长度,明文是通过返回值传出的。所以密钥应该是在这个函数内部取得。
00457cf4 <:decrypt char>:
457cf4:b5f0push{r4,r5,r6,r7,lr}
457cf6:4e18 ldrr6,[pc,#96]; (457d58 <:decrypt char unsigned int>)
457cf8:b0a7subsp,#156; 0x9c
457cfa:1c05 addsr5,r0,#0
457cfc:447eaddr6,pc
457cfe:6836ldrr6,[r6,#0]
457d00:1c0c addsr4,r1,#0
457d02:6833ldrr3,[r6,#0]
457d04:1c17 addsr7,r2,#0
457d06:9325strr3,[sp,#148]; 0x94
457d08:f7ff ff46bl457b98 <:isencrypted char>
457d0c:9603strr6,[sp,#12]
457d0e:2800cmpr0,#0
457d10:d00f beq.n457d32 <:decrypt char>
457d12:ae05addr6,sp,#20
457d14:1c21 addsr1,r4,#0
457d16:1c32 addsr2,r6,#0
457d18:ab04addr3,sp,#16
457d1a:1c28 addsr0,r5,#0
457d1c:f7ff fe9cbl457a58 <:gdk char>
457d20:9904ldrr1,[sp,#16]
457d22:9700strr7,[sp,#0]
457d24:1c32 addsr2,r6,#0
457d26:1868addsr0,r5,r1
457d28:2380movsr3,#128; 0x80
457d2a:1a61 subsr1,r4,r1
457d2c:f0a6 fc92bl4fe654
457d30:e009 b.n457d46 <:decrypt char>
457d32:1c20 addsr0,r4,#0
457d34:f2b1 ff4ebl709bd4 <:textureatlas::increasetotalquadswith>
457d38:1c06 addsr6,r0,#0
457d3a:1c29 addsr1,r5,#0
457d3c:1c22 addsr2,r4,#0
457d3e:f2b1 ff51bl709be4 <:textureatlas::increasetotalquadswith>
457d42:1c30 addsr0,r6,#0
457d44:603cstrr4,[r7,#0]
457d46:9b03 ldrr3,[sp,#12]
457d48:9a25 ldrr2,[sp,#148]; 0x94
457d4a:681b ldrr3,[r3,#0]
457d4c:429acmpr2,r3
457d4e:d001 beq.n457d54 <:decrypt char>
457d50:f2b1 ff7cbl709c4c <:textureatlas::increasetotalquadswith>
457d54:b027addsp,#156; 0x9c
457d56:bdf0pop{r4,r5,r6,r7,pc}
457d58:5264strhr4,[r4,r1]
457d5a:0086lslsr6,r0,#2
最终还是调用了xxtea_decrypt这个函数来解密的。这个函数的第三个参数就是密钥。
457d12:ae05addr6,sp,#20
457d24:1c32 addsr2,r6,#0
457d28:2380movsr3,#128; 0x80
通过以上这几行可知密钥被存在了局部变量sp+20的位置上。他的长度是128字节。显然这个密钥是通过JM::gdk的第三个参数传出的。让我们看一下JM::gdk这个函数做了什么?
00457a58 <:gdk char>:
457a58:b5f0push{r4,r5,r6,r7,lr}
457a5a:4d2f ldrr5,[pc,#188]; (457b18 <:gdk char unsigned int>)
457a5c:1c14 addsr4,r2,#0
457a5e:447daddr5,pc
457a60:682d ldrr5,[r5,#0]
457a62:b093subsp,#76; 0x4c
457a64:1e01 subsr1,r0,#0
457a66:682a ldrr2,[r5,#0]
457a68:9211strr2,[sp,#68]; 0x44
457a6a:d04c beq.n457b06 <:gdk char>
457a6c:780a ldrbr2,[r1,#0]
457a6e:2a41cmpr2,#65; 0x41
457a70:d126 bne.n457ac0 <:gdk char>
457a72:784a ldrbr2,[r1,#1]
457a74:2000movsr0,#0
457a76:2a42cmpr2,#66; 0x42
457a78:d145 bne.n457b06 <:gdk char>
457a7a:788a ldrbr2,[r1,#2]
457a7c:2a43cmpr2,#67; 0x43
457a7e:d142 bne.n457b06 <:gdk char>
457a80:78ca ldrbr2,[r1,#3]
457a82:2a54cmpr2,#84; 0x54
457a84:d13f bne.n457b06 <:gdk char>
457a86:790a ldrbr2,[r1,#4]
457a88:2a4acmpr2,#74; 0x4a
457a8a:d13c bne.n457b06 <:gdk char>
457a8c:794a ldrbr2,[r1,#5]
457a8e:2a4dcmpr2,#77; 0x4d
457a90:d139 bne.n457b06 <:gdk char>
457a92:2001movsr0,#1
457a94:2c00cmpr4,#0
457a96:d036 beq.n457b06 <:gdk char>
457a98:2206movsr2,#6
457a9a:4e20 ldrr6,[pc,#128]; (457b1c <:gdk char unsigned int>)
457a9c:af01addr7,sp,#4
457a9e:601astrr2,[r3,#0]
457aa0:447eaddr6,pc
457aa2:1c31 addsr1,r6,#0
457aa4:2240movsr2,#64; 0x40
457aa6:1c38 addsr0,r7,#0
457aa8:f2b2 f89cbl709be4 <:textureatlas::increasetotalquadswith>
457aac:1c31 addsr1,r6,#0
457aae:1c20 addsr0,r4,#0
457ab0:3140addsr1,#64; 0x40
457ab2:2240movsr2,#64; 0x40
457ab4:f2b2 f896bl709be4 <:textureatlas::increasetotalquadswith>
457ab8:1c20 addsr0,r4,#0
457aba:1c39 addsr1,r7,#0
457abc:3040addsr0,#64; 0x40
457abe:e01e b.n457afe <:gdk char>
457ac0:2000movsr0,#0
457ac2:2a54cmpr2,#84; 0x54
457ac4:d11f bne.n457b06 <:gdk char>
457ac6:784a ldrbr2,[r1,#1]
457ac8:2a4acmpr2,#74; 0x4a
457aca:d11c bne.n457b06 <:gdk char>
457acc:788a ldrbr2,[r1,#2]
457ace:2a4dcmpr2,#77; 0x4d
457ad0:d119 bne.n457b06 <:gdk char>
457ad2:2001movsr0,#1
457ad4:2c00cmpr4,#0
457ad6:d016 beq.n457b06 <:gdk char>
457ad8:2203movsr2,#3
457ada:4f11 ldrr7,[pc,#68]; (457b20 <:gdk char unsigned int>)
457adc:ae01addr6,sp,#4
457ade:601astrr2,[r3,#0]
457ae0:447faddr7,pc
457ae2:1c39 addsr1,r7,#0
457ae4:2240movsr2,#64; 0x40
457ae6:1c30 addsr0,r6,#0
457ae8:f2b2 f87cbl709be4 <:textureatlas::increasetotalquadswith>
457aec:1c39 addsr1,r7,#0
457aee:1c20 addsr0,r4,#0
457af0:3140addsr1,#64; 0x40
457af2:2240movsr2,#64; 0x40
457af4:f2b2 f876bl709be4 <:textureatlas::increasetotalquadswith>
457af8:1c20 addsr0,r4,#0
457afa:1c31 addsr1,r6,#0
457afc:3040addsr0,#64; 0x40
457afe:2240movsr2,#64; 0x40
457b00:f2b2 f870bl709be4 <:textureatlas::increasetotalquadswith>
457b04:2001movsr0,#1
457b06:9a11 ldrr2,[sp,#68]; 0x44
457b08:682b ldrr3,[r5,#0]
457b0a:429acmpr2,r3
457b0c:d001 beq.n457b12 <:gdk char>
457b0e:f2b2 f89dbl709c4c <:textureatlas::increasetotalquadswith>
457b12:b013addsp,#76; 0x4c
457b14:bdf0pop{r4,r5,r6,r7,pc}
这个函数最开始一部分代码检查了密文的前六个字符是不是“ABCTJM”,这正好是那个加密过的lua文件的前六个字节。So Excited! 胜利就在眼前。457ad6这条指令判断了返回指针是否为空。然后代码从数据区加载了一个指针到r7。经过计算这个指针的值是BB64AC
457ada:4f11 ldrr7,[pc,#68]
457ae0:447faddr7,pc
察看一下这个地址的内容,发现这个指针指向的这堆数据很可疑
放置江湖html5源码,codearchive/reverse/放置江湖 at master · crazyyao0/codearchive · GitHub...相关推荐
- 3款动态网页时间时钟HTML5源码
介绍: 3款动态网页时间时钟HTML5源码 网盘下载地址: http://kekewangLuo.cc/H5VLrhVBiis0 图片:
- 实现太阳系行星公转动画实例(CSS+HTML5 源码)
实现太阳系行星公转动画实例(CSS+HTML5 源码) 效果图 源代码(CSS+HTML5) 效果图 源代码(CSS+HTML5) <html> <head> <styl ...
- 分享79个ASP江湖论坛源码,总有一款适合您
分享79个ASP江湖论坛源码,总有一款适合您 79个ASP江湖论坛源码下载链接:https://pan.baidu.com/s/1CcDFNCbVqZGX9m2cZzhlsg?pwd=bov2 提取 ...
- 分享77个PHP江湖论坛源码,总有一款适合您
分享77个PHP江湖论坛源码,总有一款适合您 77个PHP江湖论坛源码下载链接:https://pan.baidu.com/s/1dLuixhvCs4Pp27BU6pJq6Q?pwd=1d2o 提取码 ...
- 一个简单漂亮的网址导航HTML5源码
正文: 一个简单漂亮的网址导航HTML5源码页面自适应,手机电脑都自动适应大小. 纯HTML代码,然后一个CSS一个JS文件,根据设备自适应,更多信息自行研究,修改index.html内容. 字节网盘 ...
- 分享73个ASP江湖论坛源码,总有一款适合您
分享73个ASP江湖论坛源码,总有一款适合您 73个ASP江湖论坛源码下载链接:https://pan.baidu.com/s/1cvtPY2s9kwM_L9sVRxI_xw?pwd=k08d 提取 ...
- 分享66个ASP江湖论坛源码,总有一款适合您
分享66个ASP江湖论坛源码,总有一款适合您 66个ASP江湖论坛源码下载链接:https://pan.baidu.com/s/1QuQTTtYlDPu8vT_a2PNsyg?pwd=wg6r 提取 ...
- 我的CSDN笔记总索引(阅读量降序,代码自动遍历生成HTML5源码)
Python代码用"命令容器"方法os.system(),调用Linux命令行工具crul获取CSDN博文页面源码,Python内置re正则解析出博文笔记信息,按阅读量降序模块输出 ...
- 分享53个ASP江湖论坛源码,总有一款适合您
分享53个ASP江湖论坛源码,总有一款适合您 53个ASP江湖论坛源码下载链接:https://pan.baidu.com/s/1FZ3LLkL2eeSCqXUuLfbPQQ?pwd=5x9x 提取 ...
- 分享72个ASP江湖论坛源码,总有一款适合您
分享72个ASP江湖论坛源码,总有一款适合您 72个ASP江湖论坛源码下载链接:https://pan.baidu.com/s/1mnIn_CiMunHiFgmovsIADw?pwd=de5e 提取 ...
最新文章
- 跟我学交换机配置(三)
- Linux下的XAMPP基本配置技巧(设置虚拟主机、添加FTP账户等)
- linux用户开放crontab权限,linux – / etc / crontab权限
- C#设计模式之20-状态模式
- 进程/线程间的同步方式
- 看不起胖子?自如员工爆料身高、体重决定能否晋升,官方回应侧面实锤?
- UI设计干货模板|引导网格系统
- 一般处理程序在VS2012中打开问题
- 骑士CMS模版注入+文件包含getshell漏洞复现
- Air720UGUH 极简封装 LTE Cat.1 bis 模块[合宙通信]
- 百度招聘实习生:网页搜索部_语法研究实习工程师(七种语
- Python函数式编程(fn)
- Go 每日一库之 negroni
- ebc是什么意思_ebc是什么意思?金蝶软件可靠吗?
- 解决西门子PLC模拟量输入值不稳定的问题
- 成为跨领域的「解决方案架构师」需要什么素养?
- UVa-10082-WERTYU
- android 蒙层动画,Android酷炫加载进度动画
- c语言程序设计数组实验报告,c语言程序设计实验报告(数组).doc
- 鸿蒙系统主题曲,新红楼梦的主题曲和片尾曲
热门文章
- python隐藏窗口_python怎么隐藏界面?
- 想学PLC编程,先弄清5种PLC专用语言
- 计算机软件需求说明编制指南gb/t 9385-2008,GBT 9385-2008 计算机软件需求说明编制指南.pdf...
- Dreamweaver CS4自学实例视频教程(高清)
- 屏幕录像专家 V6.0+注册机
- 计算机网络网线制作工具有,网线制作工具 网线水晶头制作过程详解(视频+图文教程)...
- 计算机网络网线制作与测试结果,《计算机网络》网线制作实验报告.doc
- 【色彩管理】HSI色彩模式详解
- 为什么说精益管理模式是适合中国企业的管理方法(zt)
- 向 Linux kernel 社区提交patch补丁步骤总结(已验证成功)