我一直以为江哥解放双手很多年.可是当我昨天看到江哥昨天的攻略,什么?江哥因为一个游戏而麒麟臂再次发作.我不知道为什么江哥为了MJ的游戏而使(基)用(情)双(深)手(厚),也不知道为什么江哥在使用双手后要对全体营销部的老(心)师(里)道(有)歉(鬼).咳咳(作正经状).好吧,那还是切入正题,相信大家在看过江哥小码哥营销部的老师们对不起!miao你们的《狂拍MJ》后会使用青花瓷修改数据请求了.经过一天的更新,首先我们看看程序猿哥哥修改了哪些内容
什么鬼,昨天还有个明显的score,今天完全看不懂,显然后台程序猿gg对提交的数据进行了加密处理.我不得不说关于加密解密这块也是得益于文顶顶老师教授的网络安全内容,据说这个课程也是新加入的.
废话不多说,于是我尝试对加密的方式进行破译,首先观察数据特点.在多次请求后发现.每一次在如下位置启动游戏后,提交的请求中的某些字段是不变的.
而且通过青花瓷发现,在进入游戏后一直重复玩游戏->结束->再来一次->玩游戏的循环,除了提交分数不会再有其他的请求.
接下来继续分析请求数据的特点,在多次请求后发现.如果不回到微信界面,只提留在游戏的相关界面.提交分数的请求有一部分始终是相同的.
下面提交了5次请求,前三次都是在1分结束的,后两次是在4分结束的.请求的数据分别为
1. pvKCJ=OvOPaQXRAYcA2FcFJUqgcA==&o8TE7=c4ca4238a0b923820dcc509a6f75849b&nxz2W=nZi5y&zm49s=bc59df515ce94c453e14763c55f34b38 2. pvKCJ=OvOPaQXRAYcA2FcFJUqgcA==&o8TE7=c4ca4238a0b923820dcc509a6f75849b&nxz2W=nZi5y&zm49s=bc59df515ce94c453e14763c55f34b38 3. pvKCJ=OvOPaQXRAYcA2FcFJUqgcA==&o8TE7=c4ca4238a0b923820dcc509a6f75849b&nxz2W=nZi5y&zm49s=bc59df515ce94c453e14763c55f34b38 4. pvKCJ=h2zKYFcX0GK0E/6OWEh9HA==&o8TE7=a87ff679a2f3e71d9181a67b7542122c&nxz2W=nZi5y&zm49s=54ae16bd09709ace3c89efd5ab3628aa 5. pvKCJ=h2zKYFcX0GK0E/6OWEh9HA==&o8TE7=a87ff679a2f3e71d9181a67b7542122c&nxz2W=nZi5y&zm49s=54ae16bd09709ace3c89efd5ab3628aa
通过观察不难发现
pvKCJ
,'o8TE7'等字段是不变的,而c4ca4238a0b923820dcc509a6f75849b``bc59df515ce94c453e14763c55f34b38
等字段在分数一致的情况下每次请求也是一致的.所以我推测,'='后面的字段与分数有关.
测试,连续提交两个3分的结果,查看请求与发现的规律是否一致.请求数据为:
pvKCJ=IzK3td5jq5gF6/YLBc5x4w==&o8TE7=eccbc87e4b5ce2fe28308fd9f2a7baf3&nxz2W=nZi5y&zm49s=e80543b6ce7aff8570ccffe6355f826f pvKCJ=IzK3td5jq5gF6/YLBc5x4w==&o8TE7=eccbc87e4b5ce2fe28308fd9f2a7baf3&nxz2W=nZi5y&zm49s=e80543b6ce7aff8570ccffe6355f826f
观察数据后,发现得出的规律是正确的.
接下来仔细观察数据,发现登号后面的一些数据十分符合MD5后的结果,于是把等号后面的数据拿去网上MD5破解.结果如下:
不难发现
就是对分数进行MD5后的结果.
原以为这样就算是大功告成了,我破解了一个其他的还是问题吗?图样图森破,有问题.因为其他的结果无法破解.而且,如果退出游戏界面到微信界面,再次进入游戏界面提交分数.会发现之前不变的字段也发生了改变.
同时这些字段的改变毫无规律可言.这样就™得尴尬了~~
无奈,黑盒破解失败,只能进行白盒破解.尝试找到生成请求数据的方法
但是通过上面的测试,发现从进入游戏界面到提交分数,一共有如下几个请求
其中第一个为微信的请求可以忽略.最后一个为分数提交,请求数据已经生成,也可以忽略.
中间几个请求后缀为.MP3的明显是加载资源的请求.
而且学过HTML5的同学都应该知道,js文件在这里是负责业务逻辑的.不好意思,这个HTML5小码哥的ios课程也有教.汗~
通过浏览器,可以尝试获得js文件的源码.结果如下
看到结果,我的内心是这样的
转念一想既然JSON可以格式化,那js代码行不行呢.去网上一搜,果然有.
把格式化好的代码拷贝出来,尝试着进行了阅读.哇擦,有没有swit的感觉,上了几天swift课也不是白上的好吗
在其中发现了这个两个方法
function gameOver() {
_gameOver = !0;
clearInterval(_gameTime);
setTimeout(function() {
GameLayerBG.className = "";
showGameScoreLayer()
},
1500);
var a = secdealpara(_gameScore);
jQuery.ajax({
type: "POST",
url: "game.php?mod=index&op=postscore",
data: a,
success: function() {},
dataType: "json",
error: function() {
alert("\u62b1\u6b49\uff0c\u6e38\u620f\u79ef\u5206\u63d0\u4ea4\u5931\u8d25")
}
})
}
function secdealpara(a) {
var b = CryptoJS.MD5(a.toString()),c = CryptoJS.enc.Utf8.parse(b),d = CryptoJS.enc.Utf8.parse(para[3]),d = CryptoJS.AES.encrypt(a.toString(), c, {
iv: d,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
a = "" + (para[0] + "=" + d);
c = "" + para[0];
a += "&" + para[4] + "=" + b;
c = c + d + para[4];
c += b;
b = para[2].split("=");
a += "&" + b[0] + "=" + b[1];
c += b[0];
c += b[1];
return a += "&" + para[1] + "=" + CryptoJS.MD5(c)
}这里我不得不提一下,网站后台程序猿gg写得非常规范,是一个好程序猿.连我都看懂了,额.可读性太好了.而且开始只是用的是明文,改过之后一言不合就aes加密,我还以为程序猿会简单弄个md5+salt,工作十分认真,可是道高一尺魔高一丈
其中gameOver()这个方法,大家通过名字也可以才出来是什么时候调用的.大体的流程就是游戏结束后,用secdealpara()方法对结果进行加密,然后把加密结果发给服务器.而secdealpara()方法就是加密结果的方法.
当我分析secdealpara()方法的时候,我发现其中para参数是缺省的,在整个文件中都没有发现,而且没有这个参数,该方法就无法运行,很有可能密钥就在其中而且通过该参数的使用方式来看,不难猜测该参数是一个数组.既然是一个数组,那里面就应该有值.那么实在哪里给数组赋值的呢?
我推测有两种可能性
1)客户端生成
2)服务器端生成发送给客户端
其中第一种可能性在简单的验证之后(我搜遍源文件没有找到后),我认为该参数应该是服务器返回的数据.
既然是服务器返回的,那么它就应该在之前提到的那些请求的返回数据中.而除了第二条请求
.其他请求都已经分析过了.因此该参数极有可能在该请求的返回值中,于是将返回值拷贝出来.command+f进行查找,果然发现了一个名为para的数组.
好了最后一个参数也找到了,呵呵呵,你以为我会去看程序猿gg的算法吗,我运行下得到结果不就完了.
保存好这个para数组
进行最后测试,简单成一个测试网页,调用加密算法的js文件,附件为写好的网页文件
归档.zip
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="crypto-js.js"></script>
<script type="text/javascript">
function secdealpara(a) {
var para = ['ClVf7','y8pvP','Wb1qH=leA2F','ctT9000erTNHppyy','mPAqt'];
var b = CryptoJS.MD5(a.toString()),
c = CryptoJS.enc.Utf8.parse(b),
d = CryptoJS.enc.Utf8.parse(para[3]),
d = CryptoJS.AES.encrypt(a.toString(), c, {
iv: d,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
a = "" + (para[0] + "=" + d);
c = "" + para[0];
a += "&" + para[4] + "=" + b;
c = c + d + para[4];
c += b;
b = para[2].split("=");
a += "&" + b[0] + "=" + b[1];
c += b[0];
c += b[1];
return a += "&" + para[1] + "=" + CryptoJS.MD5(c)
}
function test(){
var res;
res = secdealpara(1);
alert(res);
}
</script>
</head>
<body>
<button onclick="test()">小码哥一周年活动</button>
</body>
</html>用xcode把其中
secdealpara(a)中的
的para数组替换为替换为之前保存好的para数组(注意每次加载游戏这个数组都会变,重新玩不算,因为重新玩并没有退出游戏),然后在test()方法中res = secdealpara(1)
输入要获得的分数,先测试分数为1的时候结果是否正确.此网页我打包在附件了,浏览器运行html文件后,点小码哥活动就可以弹出输出结果
这个是正确的请求结果
这个是我自己计算的结果
不难发现这两个结果是一致的.到此所有的破解步骤都完成了.最后尝试着改一下分数最终验证.
将分数修改为300,获得结果:
yLzwW=5OVdVccVKz1RW3q/SaiEpA==&HZR18=94f6d7e04a4d452035300f18b984988c&uY5IG=a2iZZ&SWhUJ=71fc539409351256f210925891d670a4
编辑请求
再次发送
结果出来了


好吧我就问一句是不是江哥杰哥早就预谋好,规划好课程,怎么就被用来干这事的呢. 最后一个问题猜猜A了个K是谁?全小码哥这么有心机的boy.
最后我得为网站程序猿喊冤,人家写个游戏随便玩玩就行了,谁知道有一帮人抓包改数据.改数据那我加密算了,谁知道有一帮人会解密.后面我也不知道后台工程师怎么搞了,为了一个游戏上HTTPS,?然后还开发一个游戏应用,所有数据在应用内加密传送?然后是不是要深入到逆向工程了?我怎么觉得这些比游戏好玩呢