whatsapp登陆协议分析记录

本次研究的平台为安卓,版本号为2.23.24.74
用到了以下工具和技术

  • JADX
  • JEB
  • IDA PRO
  • Frida
  • HttpCanary

抓包

首先安装好HttpCanary后,对其进行抓包,发现主要是这两个请求在这里插入图片描述

其中reg_onboard_abprop接口根据其返回内容以及接口名称大致可以推测应该是拉取服务器的一些abtest数据的,可以先暂时忽略。接下来重点分析exist接口
在这里插入图片描述
可以看到这是一个Get请求,主要的参数为ENC字段,但是该字段是加密的,要想得到加密前的参数以及加密算法,还需要对其apk文件进行逆向分析

jadx分析

首先要找到其按钮点击事件,通过开发助手app的布局查看功能,可以很快定位到其按钮ID为0x7f0b15cd在这里插入图片描述
通过在jadx里搜索该资源内容,可以很快定位到其事件点击函数在X.50h#A04方法的case33逻辑里
在这里插入图片描述
可以发现里面都是在进行一些手机状态检测以及参数的校验逻辑,如果输入的内容校验通过的话,内层的switch会走到case1的逻辑。在case1的里面依然是在进行一些逻辑校验,最终会走到X.52O#A06逻辑里面,结合该类里面的注释,我们可以推测该类混淆前的类名为RegistrationHttpManager
继续分析A06方法,可以看到其首先会拉取abprop数据,拉取数据的方法在JniBridge的public static native long jvidispatchIOOOO(int i, Object obj, Object obj2, Object obj3, Object obj4);方法里,由于这个接口不是重点,先不分析该接口,我们继续往下看。
拉取到abprops数据后,其会把它存到sharedPrefences里,然后会走到 C5T5 A01 = registrationHttpManager2.A01(jsonObjWithAttemp, str8, str7, A00, str9, jSONObject, acquireClientCapabilities);
这个方法里最终会通过一个jni调用 JniBridge.jvidispatchIOOOOOOOOOO(0, phoneCcc, str8, A03, domainList, wamsysRegistrationWrapper, bArr3, bArr4, bArr5, bArr6, A0u);来完成参数的组装
在这里插入图片描述
由于该方法是一个jni方法,需要借助IDA来进行分析,我们先用frida对该方法进行Hook,查看一下该方法的参数

Java.perform(() => {
    let C8Z6 = Java.use("X.8Z6");
    let JniBridge = Java.use("com.whatsapp.wamsys.JniBridge");
    JniBridge["jvidispatchIOOOOOOOOOO"].implementation = function (i, obj, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10) {
        console.log(`JniBridge.jvidispatchIOOOOOOOOOO is called: i=${i}, obj=${obj}, obj2=${obj2}, obj3=${obj3}, obj4=${obj4}, obj5=${obj5}, obj6=${obj6}, obj7=${obj7}, obj8=${obj8}, obj9=${obj9}, obj10=${obj10}`);
        let result = this["jvidispatchIOOOOOOOOOO"](i, obj, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10);
        console.log(`JniBridge.jvidispatchIOOOOOOOOOO result=${result}`);
        return result;
    };
})

得到以下结果

JniBridge.jvidispatchIOOOOOOOOOO is called: i=0, obj=86, obj2=13511111111, obj3=2b8e0b5b-e155-440d-b812-bb753cbde5f3, obj4=[amazon https://y9yrsygcg6.execute-api.us-east-1.amazonaws.com/s/s?={PATH}&{QS} y9yrsygcg6.execute-api.us-east-1.amazonaws.com, google https://google.com/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.com.sa/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.com.br/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.com.my/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.com.et/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.com.om/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.co.in/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.co.zw/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.ru/s?={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net, google https://google.ae/s?_={PATH}&{QS} us-central1-propane-fusion-170222.cloudfunctions.net], obj5=X.6Ex@a41a814, obj6=[B@2a2d8bd, obj7=[B@c8e0eb2, obj8=null, obj9=null, obj10={airplane_mode_type=[B@a2ae03, sim_operator_name=[B@f9b3180, pid=[B@72943b9, cellular_strength=[B@94a63fe, device_name=[B@398275f, mistyped=[B@641e5ac, read_phone_permission_granted=[B@d116275, roaming_type=[B@7e4c20a, network_operator_name=[B@d41da7b, feo2_query_status=[B@bbdb098, push_token=[B@922b0f1, device_ram=[B@114f4d6, offline_ab=[B@c09a357, network_radio_type=[B@c293e44, hasinrc=[B@b206b2d, sim_type=[B@f438862, language_selector_time_spent=[B@11b1df3, backup_token_error=[B@89dfab0, sim_state=[B@1c58d29, token=[B@8d5c8ae, language_selector_clicked_count=[B@abfa64f, gpia=[B@86011dc, rc=[B@280d2e5, client_metrics=[B@339c1ba, gpia_token=[B@87a586b, simnum=[B@ca6fc8}
JniBridge.jvidispatchIOOOOOOOOOO result=0

可以看到传递的参数与exist接口的参数内容非常接近,进一步确认了该函数就是接口参数生产的函数。

JNI函数分析

  1. 首先要找到该函数对应的so文件,对apk进行解包后发现其里面只有三个so文件
    在这里插入图片描述
    这里面的文件很明显跟加解秘没太大的关系,猜测该app应该是第一次打开时从网络上下载so文件,最终在其data目录下找到了libwhatsapp.so文件,通过对其动态加载过程进行分析,发现其绑定的函数在0x323fd4地址上
    在这里插入图片描述
  2. 找到对应so文件函数后,开始对该函数进行分析。前面的操作都是去对参数进行一些简单的处理,最终这些处理的参数会走到sub_439A34里面
    在这里插入图片描述

分析可得该函数最终会调用sub_43B900函数在这里插入图片描述
该函数首先会生产url里的参数,然后对该参数进行加密,这里面有个v11变量,如果是exist接口,该变量为true,如果是code接口,该变量为false。由于本次分析exist接口,我们进入first_req_43B800函数,经过层层分析,我们发现了会在里面调用cal_aggrement_39E110函数进行curve25519密钥对的生成,到这里已经快到突破口了,接下来对其进行Hook


//  sub_43B9EC
Java.perform(function () {
    let hook_lib = "libwhatsapp.so"
    hook_cal_agrement()
});


function hook_cal_agrement(){
     let nativePointer = Module.findBaseAddress("libwhatsapp.so");
    console.log(nativePointer)
    var jniEntryAddress = 0x337F24
    nativePointer = nativePointer.add(jniEntryAddress)

    Interceptor.attach(nativePointer, {
        onEnter: function (args) {
            try {
                console.log("私钥",hexdump(args[1]))
            } catch (e) {
                console.log(e)
            }

        },
        onLeave: function (retval) {
            try {
                console.log("-------------------------\n\n\n")
            }catch (e) {
                console.log(e)
            }
        }
    })
}

解密参数

通过上一步frida hook的私钥与whatsapp的公钥可以计算出用于请求加密的AESKey,对请求参数进行解码可得原始请求参数
在这里插入图片描述
有了这些参数,通过查看java代码可以逐一确定其生成方式

总结

这次分析还是挺耗费时间的,里面的调用链路还是很复杂的,有些参数的具体含义还是没有太搞懂,欢迎大家一起交流

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值