ss22219 发表于 2018-2-12 12:09

记一次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

jianghanxia 发表于 2018-2-23 12:42

测试的时候发现个问题:

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&timestamp=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

不知道那个地方有问题,希望大佬帮帮忙

艾莉希雅 发表于 2018-2-12 22:00

ss22219 发表于 2018-2-12 18:10
本来想分享以下乖离源码,看来没什么必要了

emmmmm这种东西有了啊
从登录到作死 国服
台服反而要砍掉一部分用
日服的话改一点点就是
本来是想写着教程一步步的……结果突然关服
期待大佬下篇继续bgo

艾莉希雅 发表于 2018-2-12 12:15

哔哩哔哩:ㄏㄨㄚQ

123-木头人 发表于 2018-2-12 13:26

膜拜,膜拜大佬

niconico128 发表于 2018-2-12 13:46

举报了有没有石头拿

ifivoid 发表于 2018-2-12 13:54

谢谢楼主分享经验

ss22219 发表于 2018-2-12 14:15

艾莉希雅 发表于 2018-2-12 12:15
哔哩哔哩:ㄏㄨㄚQ

混蛋什么,后面两个翻译不了啊

ss22219 发表于 2018-2-12 14:20

niconico128 发表于 2018-2-12 13:46
举报了有没有石头拿

举办啥?

nohack 发表于 2018-2-12 14:30

求下一章

ss22219 发表于 2018-2-12 14:39

nohack 发表于 2018-2-12 14:30
求下一章

现在暂时没时间编写,下一章涉及到游戏请求的分析,这个过程感觉会花点时间才能弄好

ss22219 发表于 2018-2-12 16:21

nohack 发表于 2018-2-12 14:30
求下一章

第五章已发
页: [1] 2 3
查看完整版本: 记一次FGO逆向过程 chapter4