本來是閒著無聊逆向一下喜馬拉雅的登入協議
日常抓包,分析資料包,有一個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"))
可以執行,看一下結果:
可以發現結果出來了