前言
在前面我们已经写好了账号的登录,现在开始正式的进入烧脑的环节。
使用工具
工具名称 | 用途 |
---|---|
ffdec | 反编译swf文件 |
Fiddler/F12开发者工具 | 抓包 |
开发IDE(随意) | 存档加解密复现 |
分析开始
我们开始尝试抓包,抓到了获取存档列表的数据,但是发现有个 verify
参数,不过看着就是拼凑的md5。
提取SWF
因为这个游戏是swf的,所以,我们需要先提取swf,最开始的时候,我提取了游戏的swf,搜索 https://save.api.4399.com/?ac=get_list
发现,根本没有,然后分析了很久,最后发现,并不在游戏的swf里,而是在依赖包里。
这些就是游戏的依赖包,但是,我们需要的只有一个。下面我们开始分析。
分析swf
我们先把依赖包丢进 ffdec
里,直接查找 https://save.api.4399.com/?ac=get_list
最后,我们知道了 ctrl_mo_v5.swf
是我们需要的文件,接着,我们看看那里引用了 URL_SAVE_LIST
变量,我们直接跳过去。
我们直接查看,这不就是找到了吗
_loc2_ = new URLVariables();
_loc2_.gameid = mainProxy.gameID;
_loc2_.uid = mainProxy.userID;
_loc3_ = param1.target.data;
_loc2_.token = _loc3_;
_loc4_ = saveKey();
_loc2_.gamekey = _loc4_;
_loc5_ = MD5.hash(MD5.hash(MD5.hash("SDALPlsldlnSLWPElsdslSE" + _loc4_ + mainProxy.userID + mainProxy.gameID + _loc3_ + "PKslsO")));
_loc2_.verify = _loc5_;
logList = new LogData(LogData.API_SAVE,"list");
new LoaderUrl(AllConst.URL_SAVE_LIST,returnList,_loc2_);
这很明显了呀,verify
就是经过了3次 md5
计算出来的,我们接着看看它还有个 saveKey
函数
private function saveKey() : String
{
return MD5.hash(MD5.hash(this.mainProxy.gameID + "LPislKLodlLKKOSNlSDOAADLKADJAOADALAklsd" + this.mainProxy.gameID)).substr(4,16);
}
发现也是很简单,这个 gameID
在这里是找不到的,需要在游戏的swf里找,但是,我们前面抓包里就有呀,直接拿来用就好了。然后,我们尝试把这个获取存档列表写出来
我们直接运行测试,看看能不能获取成功,下面就是成功的,所以我们的没有问题
这里,我们列表是有了,但是数据呢,我们继续抓包看看。获取是啥样的。
随便点进一个存档,我们就发现,它会提交一个 https://save.api.4399.com/?ac=get
的请求,我们在 ffdec
直接搜索,向刚刚那样定位
这里的 verify
也是一样的算法,直接用上面的即可。我们需要注意的是 returnGet
函数,我们跳过去分析
data = com.adobe.serialization.json.JSON.decode(e.target.data) as Object;
tmpObj = this.copyObj(data);
try
{
byte = Base64.decodeToByteArray(data.data);
byte.uncompress();
data.data = byte.readObject() as String;
byte = null;
}
我们最后分析看到,我们需要的只有这段代码,从中我们可以知道,它是先 Base64
解码后,再进行 zlib压缩
,这里的 byte
是 ByteArray
类型,默认压缩和解压都是 zlib
的。解压之后用了 readObject
,这函数呢,是有个序列化的过程的,我们先不管,一会在研究,我们直接写代码进行测试解压后的数据。
这里我用了我封装好的 ByteArray
模块,我们直接运行看到解密是解密出来了,但是为什么前面会多几个乱码呢,别急,还记得前面我说的 readObject
函数吗,它是有自己专门的一套序列化,前面那乱码,就是它自己的解构。我们输出字节集看看。
这里,我们发现,数据长度是 12312
正确的字符长度应该是 12308
才对,这前面多了 4
字节的长度,由于我也是第一次接触到 AS
这块,后面通过网上查资料了解到了结构
最后放上解析的代码,其中借鉴了 GitHub 上的 XPilot 的 ByteArray.js ,感谢大佬们的贡献。
这里为什么我用 变体型
是因为后面我封装的时候,其他类型好读取,最后我们按照反编译出来的代码还原,运行测试。
运行成功,完美的还原出了数据,至于保存存档,也是差不多的,也就是和读取差不多的,只是提交链接不一样而已
它的存档数据,无非就是 writeObject
写入数据后,对 ByteArray
的数据进行 base64编码
即可。这里大家可以自己尝试下,我会把封装好的 ByteArray
模块放到最后,有需要的可以下载直接使用即可
最后
因为我也是第一次接触这块,如果有错误的地方,请各位告知,我也会感谢大家。
9 条评论
真棒!
加密怎么搞啊。搞了半天也没写出来
加密也是一样的呀。按他的逻辑搞就行了
加密怎么搞啊。搞了半天也没写出来
bytearray源码可以发吗
你可以自己反编译出来看看
bytearray源码可以发吗
棒棒的
模块可能还没不完善,有问题可以提