通过超级马里奥水上摩托对4399积分系统的分析

超级马里奥水上摩托游戏地址:

http://www.4399.com/flash/56259.htm

偶然看到这个游戏,挺难玩的,而且把马里奥画的有点丑,今天我们就来通过对这款游戏的反编译
来分析4399积分系统是什么样的

通过截包我们可以得到:
真实地址:

http://szhong.4399.com/4399swf/upload_swf/ftp5/haibo/20110511/1/mainload.swf

积分函数JS:

http://www.4399.com/jss/playerbg_jifen20140301.js

下载swf文件

载入FFDec中可以看出这个是Loader,载入的是二进制数据中的gamefile

 

导出二进制数据,重命名为swf文件,再载入FFDec,然后分析代码

 

可以看出这个swf也是个Loader,用于在游戏中显示排行榜、提交积分、即时获取游戏内的积分通过js传递到html页面显示等。

要想修改积分

我们只要在这个积分传递过程中做手脚就可以了 Specher原创转载请注明

或者我们可以直接模拟他的传递数据,直接提交我们自定义的积分到服务器

那我们来试试吧!

 

定位到提交分数的地方:

 

这里可以看出是和js相互通信,js中这个函数的地方:

其中提交积分的关键函数是

get_max_soure(gameid,user4399id);//更新当前分数

 

这个函数有两个参数,一个是游戏id,一个是自己的4399id

游戏ID在flash常量定义中可以找到:

4399id可以进入你的个人主页中看到:

知道这些后,我们直接在浏览器的地址栏输入

Javascript:get_max_soure(‘56259′,’1881037144’);

即可模拟提交分数操作

 

但好像有点不对劲,我们只是模拟提交了积分,而并没有修改积分。

那么我们继续寻找积分调用的地方

就在这里,调用了js中的rdscore,我们去js中看看这个函数:

显而易见,我们调用这个函数就能改变面板上的积分

Javascript:rdscore(‘50000’);

我们执行get_max_soure(gameid,user4399id);

看看发生了什么

结果是分数依然是之前游戏内的分数。

为什么呢?让我们分析下提交积分的函数

可以看出这个函数只是更新了面板的数据,然后更新成就

数据从下面取得

http://score.4399.com/get_topscore_forusercenter.php?callback=?&game_id=56259&user_id=1881037144

而并没有发现把分数上传到服务器的操作

看来是我们找错了,上传分数应该在这之前就已经完成

回到前面:

真正的提交积分原来在这里!

LoadBytes相当于一个post请求,第一个参数是url,是常量:

private var URL_SCORE:String = “http://score.4399.com/submitscore_forusercenter.php“;

第二个是个事件参数

他这里使用了匿名内部类来实现,用来和js进行一些交互

第三个参数就是post的参数了。就是这些:

我们截包后可以看到数据如下:

token=980a942d3fa726ec4b3d2e556c771aab&score=750&verify=bf621be32ad6654830c4e8d64e8393b1&autocommit=1&game%5Fid=56259&gs=1&time=1454063544314&game%5Fkey=a6231db93dfa5af2&starttime=1454062807192&uid=1881037144&username=hookd3d

其中有些数据是加密的,我们来一一解析,实现模拟这些数据,从而直接提交积分上排行榜

Token:

其中URL_TOKEN是常量http://score.4399.com/get_token.php

流程就是访问这个php得到&token=980a942d3fa726ec4b3d2e556c771aab

然后去掉前面7位

得到980a942d3fa726ec4b3d2e556c771aab就是token

Score:这个没有加密,直接写任意数字即可

Verify:

这里一些的代码被混淆了,经过混淆处理后

我们仍可分析得出

Verify是由

“SDALPlsldlnSLWPElsdslSE” + temKey + lGameScore + gameID + starttime + gs + _tokenData + “PKslsO”;

然后进行三次MD5得出的

我们再分别分析调用到的这些变量分别是什么

TemKey:

private function getIntegraKey() : String

{

var _loc1_:String = MD5.hash(MD5.hash(this.gameID + “LPislKLodlLKKOSNlSDOAADLKADJAOADALAklsd” + this.gameID)).substr(4,16);

return _loc1_;

}

这里算法很清晰,我们可以直接调用

lGameScore:

应该就是游戏的分数

gameID:

56259

Starttime:

var _loc2_:Date = new Date();

this.starttime = _loc2_.getTime();

取当前时间 可以直接用

Gs:

当前关卡 取值来自这里

_tokenData:

就是上面获取的token

 

继续分析下面的参数,

Autocommit:

为1提交后自动看排行为0不自动看排行。

game%5Fid:

也就是game_id:56259

Gs:当前关卡 和上面一样取值第一关就是1

Time:

var ts:String = md.getTime().toString();

应该是时间

game%5Fkey:

private function getIntegraKey() : String

{

var _loc1_:String = MD5.hash(MD5.hash(this.gameID + “LPislKLodlLKKOSNlSDOAADLKADJAOADALAklsd” + this.gameID)).substr(4,16);

return _loc1_;

}

 

也是个简单的算法,可以直接调用

Starttime:

var _loc2_:Date = new Date();

this.starttime = _loc2_.getTime();

游戏开始时的时间。

uid=1881037144&username=hookd3d

这个就不用说了吧。

好了全部分析完了,可以看出我们关键要得出的是

Verify,因为其中包含当前分数,我们修改了积分,这个值就也会变

而其他的参数根据游戏不同而不同,这里我们仅测试这一款游戏,其他参数通过封包中已经得出,就不一一生成了。

分析到这里,可知如果要模拟提交分数的话有点麻烦,我们还是直接修改分数吧。。

 

分数的变量是

lGameMidScore

与之相关的是

看到这里我们可以知道,上面我们修改的函数只是网页上显示的数据而已

并没有赋值到flash中提交分数中的变量Score,所以那些修改是无效的

this.lGameMidScore = this.lMain.score + this._totalscore;

从这行代码看出

这里面分数来自于lMain.score

lMain就是loader的游戏类的了。

这里有很多修改点,我们为了方便,就直接改他获取的地方吧

this.lGameMidScore = this.lMain.score + this._totalscore;

给他加五万

变成这样

然后改下当前关卡,防止被检测到我们是作弊

他是从游戏中获取的关卡数

估算了下应该是有10关,就改成10吧

OK,保存看下效果

结果是运行后闪退。

这是由于这个flash是混淆过的,而FFDec处理不完全,所以导致内存错误闪退

修改文件不行的话我们可以使用Loader来修改,但是介于篇幅,我们还是直接改游戏主文件吧

导出后再载入FFdex

找到启动类

找到分数初始化的地方:

 

直接改50000

关卡也要改

保存之后

依次替换回去

来看看效果怎么样

 

结果是分数变动了,但是一开始游戏又全部清零了。

这是因为4399的Loader初始化的时候会把分数清零

但是这里获取的还是我们修改的50000

只是提交按钮不可用

这时候我们上面得到的提交分数函数就有用了

执行Javascript:get_max_soure(‘56259′,’1881037144’);

我们的目的也就达到了

PS:

细心的朋友应该会发现,提交分数的参数中并没有对账号的验证

所以如果能模拟出提交分数的的参数,就可以伪造别人的账号来提交分数(前提是服务器没有cookies检测)

别人的uid可以在留言板发送留言的参数中获取

这么邪恶的事情我就不做了 留给大家玩吧!

作者: Specher

中文网名风生·水起,擅长安卓逆向与开发、Windows软件破解与补丁制作,喜欢IT与电子音乐,热爱运动,追求自由。

发表评论

电子邮件地址不会被公开。 必填项已用*标注