记一次FGO逆向过程 chapter5
本帖最后由 ss22219 于 2018-3-5 16:46 编辑上一章分析了b站登陆部分的逻辑,注册的请求也是一样的,有关代码可以在章节末尾链接中下载
登陆成功后会拿到一个access_key,可以在fiddler请求列表中找到:
{"requestId":"a4d431600fbf11e8acf4522233028424","timestamp":"1518417641334","code":0,"access_key":"cc7d0f9d40d06d010c0cc600c8d9f8be","uid":289451430}
点击游戏画面,让游戏登陆进去
查看Fiddler窗口,看见以下请求,最值得注意的就是developmentAuthCode
https://line3-s1-bili-fate.bilib ... ntomembercenter.php
access_token就是上面的access_key
现在我们要分析两个方向,一个是返回值的解码过程,一个是developmentAuthCode的生成过程
我们先来分析developmentAuthCode,直接在vs中搜索DevelopmentAuthCode
看到是一个常量,所以这个值是固定的,不需要解析
然后是返回内容的解析,返回内容是base64,直接以base64解码:
{"response":[{"resCode":"00","success":{"rguid":"30172359","rgusk":"498455f3582d89722601","rgtype":1,"dateVer":1518379200,"dataVer":163},"fail":{},"nid":"login_to_membercenter","usk":"498455f3582d89722601"}],"cache":{"updated":{},"replaced":{},"serverTime":1518417642}}
并没有加密内容
这里值得注意的就是"rguid","rgusk","usk"三个返回值
搜索logintomembercenter,因为链接就是这个,直接搜索这个名字效果最好
发现有一个类叫LoginToMemberCenterRequest,右击查看所有引用
发现有许多引用,因为我们是b站登陆后执行的,所以优先看BLGameSdk和BSCallbackListerner这两个类的引用
我这里看得是BSCallbackListerner,可以看到添入了很多请求参数,找找回调函数
LoginToMemberCenterRequest 类中有个requestCompleted方法
可以看到是直接把这三个值保存到全局PlayerPrefs中,相当于全局变量一样
PlayerPrefs.SetString("rguid", success["rguid"].ToString());
PlayerPrefs.SetString("usk", responseData.usk);
PlayerPrefs.SetString("rgusk", success["rgusk"].ToString());
既然有SetString,肯定就有GetString
F12 SetString进去看见这个类果然有GetString方法
右击查看引用
发现NetworkManager的RequestLogin有使用到这个函数,这里最可疑
request.addField("rguid", PlayerPrefs.GetString("rguid"));
request.addField("rgusk", PlayerPrefs.GetString("usk"));
NetworkManager的ReplaceBaseField也有用到
PlayerPrefs.GetString("usk");
再查查找SetString("usk" 有什么地方使用了
rguid,rgusk只有一处调用
usk有3个地方使用到,猜测这个usk会一直改变
继续查看请求,下一条地址是
https://line3-s1-bili-fate.bilib ... e/60_1001/login.php
这个请求返回的依然是一个base64内容
看一下他的请求rgsid是固定值
rguid rgusk是上面 LoginToMemberCenter 请求返回的内容,其他参数有个lastAccessTime,这个是当前时间,t是个固定值
看看他返回内容是什么
可以看到这个json对象
response{resCode: "00", success: {…}, fail: {…}, nid: "", usk: "754246b3a54e9009f8be"}
返回了一个usk数据,然后这个usk数据会 PlayerPrefs.SetString("usk", responseData.usk);
这个就很清晰了,再看看下一个请求
这个请求有个ac=action name=signuptop,意思是说请求名称叫signuptop?
有一个usk的请求参数,这个参数跟我们刚刚获取到的不一样,很明显,这个是服务器校验参数了
查看usk是如果生成的,猜测是根据服务器上一次返回的usk生成的,搜索所有的"usk"
找到这个代码
string @String = PlayerPrefs.GetString("usk");
string data = CryptData.EncryptMD5Usk(@string);
request.replaceField("usk", data);
public static string EncryptMD5Usk(string usk)
{
string decryptFunnyKey = CryptData.GetDecryptFunnyKey();
string str = decryptFunnyKey + usk;
return CryptData.EncryptMD5(str);
}
这个就是usk的生成函数了,根据服务器返回的usk,加上funnyKey,然后EncryptMD5
EncryptMD5就是一个md5函数,主要是这个FunnyKey
public static string GetDecryptFunnyKey()
{
string str = "+eTq/PgKHhpvmMWboN+Flb3okskn3SD325tVSqPf5nCjqAtdR6BN7Q==";
return CryptData.FunnyKeyDecrypt(str);
}
好家伙,还有一层
我尝试在C# Interactive窗口直接获取这个值
视图->其他窗口->C# Interactive
运行结果是 F02C093101C3E4F5813E46605842B74A
继续拿这个跟上面返回的usk运算:
MD5("F02C093101C3E4F5813E46605842B74A" + "754246b3a54e9009f8be")
0ad09c7453763ae3ee7f113110e84840
与上面的完全一致,那么之后的usk都是这么生成了
整个过程
1.b站登陆拿到access_key,填入到LoginToMemberCenter请求中的access_token
base64解码返回内容 获取到"rguid","rgusk","usk"三个返回值
2."rguid","rgusk"填入到rongame_beta/rgfate/60_1001/login.php请求中
base64解码返回内容 获取到usk
3.EncryptMD5Usk(usk) 填入usk 请求ac.php系列接口,这个接口都是ac=action&name=xxxx,每次都会返回一个usk
base64解码返回内容 获取到usk
利用上一次服务器返回的usk来生成下一个usk,即可完成服务器验证
========================================================
至此,关于FGO的游戏请求加密分析已经完成
往下我不知道讲什么内容好了,有两个想说的
一个是战斗数据的分析与修改
另外一个是fgo的解包
大家觉得哪个比较好,如果没什么疑问,这个系列就可能就此结束了
有关操作代码可以在我之前发表的FGO管理系统内找到
https://www.52pojie.cn/thread-686596-1-1.html
下一章:
https://www.52pojie.cn/thread-698928-1-1.html
上一章:
https://www.52pojie.cn/thread-698513-1-1.html lg560852 发表于 2018-2-12 16:20
能否分析一下BGO的反外挂对策?
是否有如下策略:
伤害过高;
答案是,没有反外挂,只有在服务器有频繁的请求有做验证 ss22219 发表于 2018-2-17 20:42
日服的root检测看看是不是在native层或者java层,这个按照之前的分析步骤走一遍就可以了,如果在il层的话 ...
检测在lib__6090__.so里 在java层是InAppPurchaseActivitya和InAppPurchaseActivityb调用的
java层一共是26个int常量 每个版本都不一样
b里有一个native调用6090的a函数的
主Activity里面有很多调用InAppPurchaseActivityb.a的东西
关于dump的话 按照一年前左右的文章来说
就算dump出来 也只能看见函数名 什么都看不到
libunity.so加载后IDA会segmentation fault
如果搞定了的话 加载libfgo.so之后 DLL的RVA会不正确
libfgo.so加载之后要么IDA不认 要么直接发mail(日服会把错误代码之类的东西用手机默认的邮箱软件把内容放进去,然后可以选择是否要发)
.unity3d的话 密钥是在CatAndMouseGame里面叫ThirdHouseBuilding和ForthHouseBuilding两个函数加载的 这两个函数也是链接libfgo.so
密钥是TopGameDataRequest获取的 返回结果经过libfgo.so解密 然后去调用这两个函数
1.29.0的时候因为密钥暴露了官方甚至把所有资源重新弄一遍,一天更新两个G
大概1.18.0以前还可以用Magisk+ANRC过root检测 现在检测Magisk就没办法了
模拟器的话 日服对模拟器的检测不是很严格 相反同样用6090的美服就比日服强多了。。
日服可以用关了root的Nox玩 美服在11月一次更新之后就不能了。。
检测模拟器和root应该不是用一些常规的方法 因为所有的root隐藏器之类的东西全部无效
基本上 我自己感觉是没什么办法了。。
现在唯一的日服挂就是AndroidRepublic做的 用了一个libandroidrepublic.so
和朋友分析一下应该是注入。。 而且那个版本过了root和usb检测
具体怎么做。。就想不明白了。。 感觉这东西有点丧心病狂 本帖最后由 lg560852 于 2018-2-12 16:22 编辑
能否分析一下BGO的反外挂对策?
是否有如下策略:
单次或累计伤害过高;
过章时间过短
技能使用次数过多
过章累计无伤害
等等
另外,如果后期官方考虑增加的话,从哪方面入手更为合适?
有矛才有盾 lg560852 发表于 2018-2-12 16:20
能否分析一下BGO的反外挂对策?
是否有如下策略:
单次或累计伤害过高;
过章时间过短服务器直接返回战斗失败 ss22219 发表于 2018-2-12 16:22
答案是,没有反外挂,只有在服务器有频繁的请求有做验证
感谢回复,看来封号只可能是分析后台数据了 lg560852 发表于 2018-2-12 16:23
感谢回复,看来封号只可能是分析后台数据了
事实上,当时我分析的时候整个战斗上传数据只有谁使用了什么卡,至于伤害还有时间都没有上传
[[ 人物1,卡1],[ 人物2,卡2]....] 战斗数据的分析,有助于编写外挂
解包解析,有助于掉率等等攻略的制作
这两个希望也能更新一下
另外,回传服务器的数据,又都包含哪些呢? 本帖最后由 boyulin 于 2018-2-12 16:34 编辑
頂一波對於脫機掛 很嚮往
想問樓主 是不是Assembly-CSharp.dll的手遊較好逆向
ss22219 发表于 2018-2-12 16:27
事实上,当时我分析的时候整个战斗上传数据只有谁使用了什么卡,至于伤害还有时间都没有上传
[[ 人物1 ...
是这样啊,那也难怪上次好多号被误封了 lg560852 发表于 2018-2-12 16:28
战斗数据的分析,有助于编写外挂
解包解析,有助于掉率等等攻略的制作
这两个希望也能更新一下
包含了玩家和怪物的等级和血量,还有掉落内容
也就是说,掉落是固定的,你只能放弃当前战斗才能获取新的物品
至于玩家数据这些,是通过服务器每次战斗开始的时候返回的数据为准,不是以本地为准