记一次FGO逆向过程 chapter4
本帖最后由 ss22219 于 2018-3-5 16:45 编辑上一章我们成功还原了Assembly-CSharp.dll文件,这一章主要分析FGO的登陆逻辑
用dnSpy导出项目,在visual studio中打开,解决方案管理器中搜索login
发现在BSGameSdk中有一个login方法,看上去是调用java层登陆
跟踪进去,确实是java调用
分析android java代码,一般以 反编译 + smail + 动态调试 来组成农夫三拳
下载jd-gui(Java decompliler), dex2jar
首先用d2j-dex2jar.bat xxx.apk 生成jar包,然后用jd-gui打开
看起来有不少的参数,这时候可以用Fiddler来分析
关于mumu模拟器如何设置代{过}{滤}理服务器,这是个很有意思的问题
adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO system (name,value)VALUES('http_proxy','192.168.0.102:8888')"
用adb来给模拟器设置代{过}{滤}理看起来很cool,但其实很不方便,有时候要关掉怎么办?要换ip怎么办?
所以这里给出了另外一个办法,下载
https://github.com/DerekZiemba/RootActivityLauncher/releases
打开后找到设置,点击可以看到WLAN,点击进去就可以设置代{过}{滤}理了
关于Fiddler如何监听https链接,这篇文章有介绍
http://blog.csdn.net/idlear/article/details/50999490
证书安装需要添加锁屏密码,直接添加,关闭浏览器重新打开百度,打开了就没问题了
登陆有游客跟b站账号两种方式,这里针对b站账号分析
可以看到4个请求
1.http://p.biligame.com/api/client/rsa
2.http://p.biligame.com/api/client/login
3.https://gameinfoc.biligame.net/....
4.https://gameinfoc.biligame.net/....
可以看到第二条是登陆,后面两条是错误提交
分析第一条请求,名字叫rsa,难道跟加密有关?
查看返回内容,果然是一个rsa公钥(PUBLIC KEY)
猜测应该是拿来给密码加密的
看第二条请求,密码果然是加密处理过的,密码上还有个sign,这个应该是对整个请求的一个校验值
分析java代码,jd-gui中查找password,看到有一个比较令人在意的log
打开Android Studio,之前第一章介绍过如何无源码调试java代码
找到对应的smail文件,打断点
看到这里密码还没加密,但是有个hash出来了,这个hash猜想是其他字段的一个md5
跟踪到log后那个new y,分析Java代码
看到有个client/login字符串,后面有一大堆参数设置,这里应该就是登陆请求了,打断点继续
到这里pwd已经加密完成了,继续回到第一次log那段代码,发现有个调用
com.bsgamesdk.android.utils.r.a(hash + password明文, rsa)
跟踪就去发现是个RSA/ECB/PKCS1Padding加密,然后转成字符串
那么这个hash从哪里来的呢?是不是每次固定的?重新调试一次
果然是一直变,猜想是由我的输入生成的(判断错了)
查看堆栈,直接找到com.bsgamesdk.android.task -> a
这里是获取用户名密码然后处理的开始,q.c.a是个接口,在这里下断点
invoke-interface/range {v0 .. v5}, Lcom/bsgamesdk/android/api/bi;->a(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/bsgamesdk/android/api/BSGameSdkAuth;
单步跟踪进去
来到 com/bsgamesdk/android/api/e -> a 跟踪jd-gui里面对应反编译
一路查看调用
发现了一个函数,这里有个md5调用,hash应该是这里生成了
Lcom/bsgamesdk/android/utils/n; -> a
回到android studio,找到对应文件下断点,可以看到两个参数的值,p0如下
{"ad_f":"36938c908e0c11e6bf0552223301d6e6","ad_location_id":"305","ad_channel_id":"47"}11201p.biligame.com01024*57611211MuMu454.4.43111.6.7.1248x86,armeabi-v7a1518403790013Pwc3BzUCOgJgU2oPcw9z1.17.11
前面是个json,后面是一些服务器和系统名字,感觉这些数据些熟悉
可以看到这个参数就是所有的请求参数的值拼接在一起,然后作为参数传递进来,我们在登陆一次看看第二个参数会不会变
p1 : a4e39619a09d49e9aead9b820980013a
还是没变,改变一下密码用户名呢?
额,这时候程序崩溃了,好在我写有一个脚本,直接点卡重新调试
在程序重新运行时,我在考虑,这个hash应该就是p0 + p1(固定字符串) md5生成的,我们验证一下我的想法
果然还是一样的结果
那么值得注意的就是p0了,p0里面进过对照,肯定是请求里面各个参数的值
不过不是全部,对比发现有这些参数放进去了
"c", "channel_id", "domain", "dp", "game_id", "idfa", "merchant_id", "model", "net", "operators", "pf_build", "pf_ver", "platform_type", "pwd", "sdk_log_type", "sdk_type", "sdk_ver", "server_id", "timestamp", "udid", "uid", "user_id", "ver", "version"
好吧,就差这个sign没放进去了
看样子是排序过的,循序是参数名称a-z排序
得到固定p1参数
a4e39619a09d49e9aead9b820980013a
那么我们看下其他参数是怎么来的吧
首先是这个ad_f,通过查找,发现是读取apk里assets/ext.txt文件获取的一个固定值(过程我偷懒了)
appid应用id?应该是固定
我直接那上面那个p1字符串在导出的c#项目中搜索,发现了一行代码
BSGameSdk.init(true, "1", "112", "248", "a4e39619a09d49e9aead9b820980013a");
1 = merchant_id
112 = app_id
248 = server_id
a4e39619a09d49e9aead9b820980013a = app_key
原来你叫app_key啊,那么剩下的就好办了
pwd是加密后的密码,channel_id是固定,dp是屏幕分辨率,timestamp是当前时间,platform_type是平台(ios/android),model是系统名称,game_id固定,net固定。。。。。。
看起来很多其实却没什么难获取
ok,然后尝试拿这个p0 + app_key md5然后转换成字符串 Lcom/bsgamesdk/android/utils/n; -> b 就是转换函数
得到的值就是login提交的sign参数
看来里真正破解登陆过程不远了呢
pwd加密应该是使用rsa来加密,刚才说过
com.bsgamesdk.android.utils.r.a(hash + password明文, rsa)
处是密码的加密,我看了一下,这个hash其实在/client/rsa请求中有返回
。。。。。。。。早知道不应该少看这个rsa请求的
pwd这一个参数也找到了,整个登陆的流程就解析了出来了
1.请求 /client/rsa 获取公钥 和 token
2.使用公钥执行rsa加密,加密内容是 token+密码,得到byte[] 转换成base64字符串
3.构造一个hashtable,这个表包含一下内容
"c", "channel_id", "domain", "dp", "game_id", "idfa", "merchant_id", "model", "net", "operators", "pf_build", "pf_ver", "platform_type", "pwd", "sdk_log_type", "sdk_type", "sdk_ver", "server_id", "timestamp", "udid", "uid", "user_id", "ver", "version"
对该hashtable的key排序,然后拼接他们的值
拼接值 + app_key 进行md5
将md5以sign为key填入hashtable
4.将hashtable转换成url请求参数,请求/client/login
========================================================
至此,关于FGO的登陆分析已经完成,有关操作代码可以在我之前发表的FGO管理系统内找到
https://www.52pojie.cn/thread-686596-1-1.html
至于这一章为什么来得那么快,因为这是已经代码实现了的,再发出来只是重温一下过程...
我们下一章再见
下一章:
https://www.52pojie.cn/thread-698587-1-1.html
上一章:
https://www.52pojie.cn/thread-698450-1-1.html 测试的时候发现个问题:
Fiddler捕获的原始URL为:
/api/client/rsa?sdk_type=1&isRoot=0&sign=64463094b615bc223a4819bbbc970836&merchant_id=1&dp=2030*1080&uid=&support_abis=arm64-v8a%2Carmeabi-v7a%2Carmeabi&platform_type=3&operators=2&model=MIX%202&udid=agltXWQCYANmAjIBfQF9&net=4&app_id=113&game_id=113×tamp=1518626511339&ver=2.4&c=0&server_id=249&version=1&domain_switch_count=0&pf_ver=8.0.0&domain=p.biligame.com&original_domain=&sdk_log_type=1&sdk_ver=1.6.7.1&channel_id=1
按文章中说明,去除多余字段,排序生成应该是这样:
01p.biligame.com2030*10801131MIX%202428.0.03111.6.7.12491518626511339agltXWQCYANmAjIBfQF92.41
加上a4e39619a09d49e9aead9b820980013a后计算MD5是:de0f688ef62ae832a6092f16c6bc8f4a
对比sign不正确,然后尝试全部字段是这样:
11301p.biligame.com02030*108011301MIX 2428.0.03111.6.7.1249arm64-v8a,armeabi-v7a,armeabi1518626511339agltXWQCYANmAjIBfQF92.41
MD5计算是0ca3cbe57c1c34644dfb4c4f5e98e5ed
不知道那个地方有问题,希望大佬帮帮忙 ss22219 发表于 2018-2-12 18:10
本来想分享以下乖离源码,看来没什么必要了
emmmmm这种东西有了啊
从登录到作死 国服
台服反而要砍掉一部分用
日服的话改一点点就是
本来是想写着教程一步步的……结果突然关服
期待大佬下篇继续bgo 哔哩哔哩:ㄏㄨㄚQ 膜拜,膜拜大佬 举报了有没有石头拿 谢谢楼主分享经验 艾莉希雅 发表于 2018-2-12 12:15
哔哩哔哩:ㄏㄨㄚQ
混蛋什么,后面两个翻译不了啊 niconico128 发表于 2018-2-12 13:46
举报了有没有石头拿
举办啥? 求下一章 nohack 发表于 2018-2-12 14:30
求下一章
现在暂时没时间编写,下一章涉及到游戏请求的分析,这个过程感觉会花点时间才能弄好 nohack 发表于 2018-2-12 14:30
求下一章
第五章已发