星火出海是您的WhatsApp业务解决方案提供商
埃及、利比亚、突尼斯、阿尔及利亚、摩洛哥、亚速尔群岛(葡)、马德拉群岛(葡)、加那利群岛(西)、苏丹、南苏丹、埃塞俄比亚、厄立特里亚、索马里、吉布提、肯尼亚、坦桑尼亚、乌干达、卢旺达、布隆迪、塞舌尔,乍得、中非、喀麦隆、赤道几内亚、加蓬、刚果共和国、刚果民主共和国、圣多美和普林西比,毛里塔尼亚、塞内加尔、冈比亚、马里、布基纳法索、几内亚、几内亚比绍、佛得角、塞拉利昂、利比里亚、科特迪瓦、加纳、多哥、贝宁、尼日尔、尼日利亚 、西撒哈拉(摩洛哥实际控制),赞比亚、安哥拉、津巴布韦、马拉维、莫桑比克、博茨瓦纳、纳米比亚、南非、斯威士兰、莱索托、马达加斯加、科摩罗、毛里求斯、留尼汪岛(法)、圣赫勒拿岛(英)、马约特(法)
com.facebook.katana.apk
jadx(反编译)
burp suite(抓包工具)
root手机(Google pixel Anroid 9)
frida环境
提取Facebook账号登录后的access_token与cookie
Facebook有SSL Pinning Bypass证书校验,并且采用的sslv1.3加密通信,所以我们必须先破解Facebook证书校验后,再采用burpsuite进行抓包
Facebook登录包,通过请求协议头可以看出提交参数采用了gzip压缩,解压后可以看到完整数据
解压后数据,发现有一个sig签名校验,由于此篇文章主要讲提取登录环境,所以此加密暂不分析
可以看到登录成功后返回了access_token与cookies
查看其它请求接口都有带上access_token,m.facebook.com接口API则会带上cookie请求
至此,Facebook抓包分析完毕
jadx打开facebook.apk,然后搜索字符串Authorization
发现httpPost.addHeader("Authorization", "OAuth " + str4);
这段代码非常可疑,添加http请求的协议头,跟进去看一下
发现Authorization的值是通过str4变量传递进来的,往上查看发现str4是通过str4 = viewerContext.mAuthToken;
获取赋值来的,那么我们分析一下ViewerContext这个类
标注红框的这几个变量都异常可疑,通过名称来看是账号的授权验证信息,接下来我们验证下这个ViewerContext类存储的是不是账号授权验证信息
JavaScript脚本,保存为test.js
Java.perform(function () {
/**
* 寻找类型为ViewerContext的对象
*/
Java.choose("com.facebook.auth.viewercontext.ViewerContext", {
onMatch: function (instance) {
console.log("start");
if (instance.mAuthToken.value !== '') {
Java.openClassFile("/data/local/tmp/r0gson.dex").load();
const gson = Java.use('com.r0ysue.gson.Gson');
console.log("facebook info:" + gson.$new().toJson(instance));
}
},
onComplete: function () {
console.log("stop");
}
});
});
JavaScript脚本有用到r0gson.dex实现java对象转json,具体使用安装与使用教程请查看Frida打印[object]解决gson
包重名的问题
python脚本
import frida, sys
import threading
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
def get_device():
mgr = frida.get_device_manager()
changed = threading.Event()
def on_changed():
changed.set()
mgr.on('changed', on_changed)
device = None
while device is None:
devices = [dev for dev in mgr.enumerate_devices() if dev.type == 'usb']
if len(devices) == 0:
print('Waiting for usb device...')
changed.wait()
else:
device = devices[0]
mgr.off('changed', on_changed)
return device
if __name__ == '__main__':
# 查找USB设备
device = get_device()
print(device)
# 附加到目标进程
process = device.attach('com.facebook.katana')
# 读入js脚本
js_code = open(file='test.js', mode='r', encoding='UTF-8').read()
# 在目标进程里创建脚本
script = process.create_script(js_code)
# 注册消息回调
script.on('message', on_message)
print('[*] Running Start')
# 加载创建好的javascript脚本
script.load()
# 读取系统输入
sys.stdin.read()
通过usb连接设备后,先运行frida服务端./frida-server
,然后执行python脚本,执行后如下
寻找到ViewerContext并成功打印,打印后的json内容如下
{
"mAuthToken": "EAAAAUaZA8jlABAFBWyyWh1a9RRkXuC0on6ifoiQCqZCsNmDaq3B2GwpAtCbsswTJ6ZA9lnPyGNKeMiSPLoPPjSXOW2r5Pz1Etgk9jQbDeZBotdxqwXXXX4olkRZBUXsgDWRjwvPevwXa7ErTekG0sj0ZBWrVohyDI4VsjCmLI6jTUxHuR28ZAgddM58vZCdMJLP1ZCbEZD",
"mIsDittoContext": false,
"mIsFoxContext": false,
"mIsPageContext": false,
"mIsTimelineViewAsContext": false,
"mSessionCookiesString": "[{\"name\":\"c_user\",\"value\":\"xxxx\",\"expires\":\"Sun, 24 Oct 2021 07:00:45 GMT\",\"expires_timestamp\":1635058845,\"domain\":\".facebook.com\",\"path\":\"/\",\"secure\":true},{\"name\":\"xs\",\"value\":\"29:G0TgeekBOaI8RQ:2xx:1603522845:-1:-1\",\"expires\":\"Sun, 24 Oct 2021 07:00:45 GMT\",\"expires_timestamp\":1635058845,\"domain\":\".facebook.com\",\"path\":\"/\",\"secure\":true,\"httponly\":true},{\"name\":\"fr\",\"value\":\"xxx.AWXnfnu6Fd9v-1rLuoUTC2p_Y34.Bfk9Ed..AAA.0.0.Bfk9Ed.AWXJJAtgjLc\",\"expires\":\"Fri, 22 Jan 2021 07:00:43 GMT\",\"expires_timestamp\":1611298843,\"domain\":\".facebook.com\",\"path\":\"/\",\"secure\":true,\"httponly\":true},{\"name\":\"datr\",\"value\":\"HdGTX84Fu6qF__wmOj6CG14q\",\"expires\":\"Mon, 24 Oct 2022 07:00:45 GMT\",\"expires_timestamp\":1666594845,\"domain\":\".facebook.com\",\"path\":\"/\",\"secure\":true,\"httponly\":true}]",
"mSessionKey": "5.G0TgeekBOaI8RQ.1603522845.29-100055144183397",
"mSessionSecret": "40ec00c740b2dfa33562ca9bc13e9b4c",
"mUserId": "xxxx",
"mUsername": "xxxxx"
}
发现通过调用ViewerContext即可获取到Facebook账号登录后的授权验证信息,拿到这两个值就可以愉快的调用Facebook的接口了