【安卓逆向】从逆向登录协议开始到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"))
可以执行,看一下结果:
可以发现结果出来了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端