【安卓逆向】从逆向登录协议开始到frida rpc的初探

本来是闲着无聊逆向一下喜马拉雅的登录协议

日常抓包,分析数据包,有一个password字段

想分析一下这个password这个字段,jadx搜索一下啊

 

经过frida多次的hook定位,发现这个方法便是加密过程,点进去

可以hook一下这个方法查看一下

function hook() {
    let LoginRequest = Java.use("com.ximalaya.ting.android.loginservice.LoginRequest");

    LoginRequest["a"].overload('androidx.fragment.app.FragmentActivity', 'com.ximalaya.ting.android.loginservice.base.d', 'java.util.Map', 'com.ximalaya.ting.android.loginservice.base.a').implementation = function (fragmentActivity, iRequestData, map, iDataCallBackUseLogin) {
        console.log(`LoginRequest.m65178a is called:`);

        if (map !== null) {
            if (map.containsKey("account")) {
                console.log(` - account: ${map.get("account")}`);
            }

            if (map.containsKey("password")) {
                console.log(` - password: ${map.get("password")}`);
            }
        }

        // 保留原始方法调用
        this["a"].call(this, fragmentActivity, iRequestData, map, iDataCallBackUseLogin);
    };
}

然后重新登录,输入账号密码,发现确实hook到了

最后锁定加密代码

这里调用 

LoginEncryptUtil.m65187a().m65184a(str);

进行加密,点进去看一下m65184a函数

package com.ximalaya.ting.android.loginservice;

import android.content.Context;
import com.huawei.hms.framework.common.ContainerUtils;
import java.util.Map;
import java.util.TreeMap;

/* loaded from: classes3.dex */
public class LoginEncryptUtil {
    private native String BEfHgGMDiX(Context context, Map<String, String> map);

    private native String SudCmgZCdt(String str);

    private native String jwpAFNrLmt(Context context, boolean z, String str);

    static {
        System.loadLibrary("login_encrypt");
    }

    /* renamed from: com.ximalaya.ting.android.loginservice.LoginEncryptUtil$a */
    /* loaded from: classes3.dex */
    private static class C24706a {

        /* renamed from: a */
        private static final LoginEncryptUtil f85016a = new LoginEncryptUtil();
    }

    /* renamed from: a */
    public static LoginEncryptUtil m65187a() {
        return C24706a.f85016a;
    }

    /* renamed from: a */
    public String m65185a(Context context, boolean z, Map<String, String> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        TreeMap treeMap = new TreeMap(map);
        StringBuilder sb = new StringBuilder();
        for (Map.Entry entry : treeMap.entrySet()) {
            sb.append((String) entry.getKey());
            sb.append(ContainerUtils.KEY_VALUE_DELIMITER);
            sb.append((String) entry.getValue());
            sb.append("&");
        }
        return jwpAFNrLmt(context, z, sb.toString());
    }

    /* renamed from: a */
    public String m65184a(String str) {
        return SudCmgZCdt(str);
    }

    /* renamed from: a */
    public String m65186a(Context context, Map<String, String> map) {
        return BEfHgGMDiX(context, map);
    }
}

最后调用so层函数进行加密,ida分析一下这个,找到这个加密函数

追进去,我滴乖乖!

ollvm混淆又来了,逆向是不可能逆了,这里可以使用unidbg模拟so库把password的加密结果计算出来,毕竟如果要做登录协议,也不一定非得把算法逆向出来,只需要得到加密值就行,因为unidbg需要补环境,这里使用frida rpc

调用实现在python代码中获取加密值

首先发现

这个方法是静态的,返回值就是加密结果,可以直接frida直接调用改方法,改成rpc调用形式

function hook_encryt(phone){
    var string;
    Java.perform(function(){
    let C24795g = Java.use("com.ximalaya.ting.android.loginservice.g");
    var javaString = Java.use("java.lang.String");
    string = C24795g.c(javaString.$new(phone));
    console.log(string)

    })
    return string  //返回值需要放到Java.perform外面
   
}

rpc.exports={
    method:hook_encryt
}

然后在python中进行调用

import frida
import time

device = frida.get_usb_device()
print(device)

pid=device.spawn(["com.ximalaya.ting.android"]) #启动目标app
device.resume(pid)
time.sleep(1)

session=device.attach(pid) 

with open("hook3.js") as f:
    script=session.create_script(f.read())    #加载脚本

script.load()
api=script.exports #获取导出函数列表

print("method==>>"+api.method("GGbomb"))

可以执行,看一下结果:

可以发现结果出来了

posted @ 2024-04-17 23:14  GGBomb  阅读(22)  评论(0编辑  收藏  举报