安卓逆向--使用jadx-ai-mcp辅助分析某校园pro校园跑"

admin 2026-10-24 11:49:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

安卓逆向 -- 使用jadx-ai-mcp辅助分析某校园pro校园跑

Tonyha7
Tonyha7

逆向有你

2026年10月19日 10:04
河南

去阅读

介绍

笔者的学校又开始了新一轮的校园跑 这次换了一个校园跑的app

本着科技强国的思想 自然少不了对这个app的一顿研究

易盾加固%20所以我们直接搞个Xposed模块来hook%20是比较省时省力的方法

分析与Hook

首先脱壳%20这里就不赘述了%20现有的工具很多

这里讲一下如何配置jadx-ai-mcp插件和服务器

首先打开jadx%20加载插件jadx-ai-mcp-6.3.0.jar

然后解压jadx-mcp-server-6.3.0.zip%20命令行进入jadx-mcp-server文件夹

执行

 复制代码 隐藏代码
pip%20install%20-r%20./requirements.txt

来安装依赖

然后进入各种支持mcp的编辑器%20我这里用的vscode

编辑mcp配置%20添加刚才的服务器

这里的端口要和jadx插件里的端口一致

这里有个坑%20有的时候打开了文件%20但是界面上没有Plugins的选项

解决方法是把jadx窗口最大化一下就好了

将这个服务器启用%20然后你就可以让agent来调用了

我这里用的是GitHub%20Copilot

模型推荐使用Gemini%203.1%20Pro Claude太贵%20GPT限制太多

确认需求

在详细分析之前%20先确定好我们的目标

  1. 使用大多数模拟位置的软件模拟位置后%20这个app仍然会获取到真实位置信息
  2. 在进行校园跑的过程中%20app会随机进行扫脸验证
  3. 校园跑有“电子围栏”机制%20在电子围栏外的操作全部不会记录
创建一个Xposed项目

创建模块这里不详细写了%20对于这种有加固的app%20我们需要获取到app真正加载的ClassLoader来进行hook操作

 复制代码 隐藏代码
publicclassStartHookimplementsIXposedHookLoadPackage {
 %20  @Override
 %20  publicvoidhandleLoadPackage(XC_LoadPackage.LoadPackageParam%20loadPackageParam)throws Throwable%20{
 %20 %20 %20  StringpackageName= loadPackageParam.packageName;
 %20 %20 %20  ClassLoaderclassLoader= loadPackageParam.classLoader;
 %20 %20 %20  if (packageName.equals(\"com.huachenjie.shandong_school_pro\"))%20{
 %20 %20 %20 %20 %20 %20XposedHelpers.findAndHookMethod(\"com.netease.nis.wrapper.MyApplication\",%20loadPackageParam.classLoader,
 %20 %20 %20 %20 %20 %20 %20 %20 %20  \"attachBaseContext\",%20Context.class, newXC_MethodHook()%20{
 %20 %20 %20 %20 %20 %20 %20  @Override
 %20 %20 %20 %20 %20 %20 %20  protectedvoidafterHookedMethod(MethodHookParam%20param)throws Throwable%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20  super.afterHookedMethod(param);
 %20 %20 %20 %20 %20 %20 %20 %20 %20  Contextcontext= (Context)%20param.args[0];
 %20 %20 %20 %20 %20 %20 %20 %20 %20  ClassLoaderclassLoader= context.getClassLoader(); //使用这个ClassLoader来进行Hook
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20Toast.makeText(context, \"Hook成功\",%20Toast.LENGTH_SHORT).show();
 %20 %20 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20 %20 %20});
 %20 %20 %20 %20}
 %20 %20}
}
信息获取

我们需要获取一次真实的上传数据%20用于分析校园跑在跑步的过程中需要记录什么信息

获取到校园跑Activity之后%20直接扔给ai分析

ai写出了以下的代码

 复制代码 隐藏代码
publicclassRunDataLoggerHook {
 %20  publicstaticvoidHook(ClassLoader%20classLoader) {
 %20 %20 %20  try {
 %20 %20 %20 %20 %20  //%20定位到最终负责上传各个成绩请求的入口类
 %20 %20 %20 %20 %20 %20Class<?>%20runModelClass%20=%20XposedHelpers.findClassIfExists(\"com.huachenjie.running.model.b\",%20classLoader);

 %20 %20 %20 %20 %20  if (runModelClass%20!= null)%20{
 %20 %20 %20 %20 %20 %20 %20  //%20Hook%20跑步结束上传成绩的方法%20c(Map<String,%20Object>%20params)
 %20 %20 %20 %20 %20 %20 %20 %20XposedBridge.hookAllMethods(runModelClass, \"c\", newXC_MethodHook()%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20  @Override
 %20 %20 %20 %20 %20 %20 %20 %20 %20  protectedvoidbeforeHookedMethod(MethodHookParam%20param)throws Throwable%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  super.beforeHookedMethod(param);

 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  if (param.args%20!= null &&%20param.args.length%20> 0 &&%20param.args[0] instanceof Map)%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20Map<?,%20?>%20paramsMap%20=%20(Map<?,%20?>)%20param.args[0];

 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20XposedBridge.log(\"======%20拦截到准备上传的真实跑步数据%20======\");

 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  //%20尝试使用%20Fastjson(应用内自带)将%20Map%20转为%20JSON,方便阅读和复制
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  try {
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20Class<?>%20jsonClass%20=%20XposedHelpers.findClassIfExists(\"com.alibaba.fastjson.JSON\",%20classLoader);
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  if (jsonClass%20!= null)%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  StringjsonString= (String)%20XposedHelpers.callStaticMethod(jsonClass, \"toJSONString\",%20paramsMap);
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  //%20分段打印,防止%20logcat%20截断
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20logLongString(jsonString);
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20} else {
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20  //%20退级:直接%20toString()
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20logLongString(paramsMap.toString());
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20} catch (Exception%20e)%20{
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20XposedBridge.log(\"转%20JSON%20出错:%20\" +%20e.getMessage());
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20logLongString(paramsMap.toString());
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20}

 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20XposedBridge.log(\"======%20真跑数据拦截结束%20======\");
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20 %20 %20 %20 %20});
 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20} catch (Exception%20e)%20{
 %20 %20 %20 %20 %20 %20XposedBridge.log(\"RunDataLoggerHook%20异常:%20\" +%20e.getMessage());
 %20 %20 %20 %20}
 %20 %20}

 %20  //%20处理超长字符串的打印(Xposed%20log%20最大长度有硬性限制,通常4k)
 %20  privatestaticvoidlogLongString(String%20str) {
 %20 %20 %20  if (str%20== null) return;
 %20 %20 %20  intsegmentSize=3000;
 %20 %20 %20  longlength= str.length();
 %20 %20 %20  if (length%20<=%20segmentSize)%20{
 %20 %20 %20 %20 %20 %20XposedBridge.log(str);
 %20 %20 %20 %20} else {
 %20 %20 %20 %20 %20 %20XposedBridge.log(\"数据过长,分段打印开始:\");
 %20 %20 %20 %20 %20  for (inti=0;%20i%20<%20length;%20i%20+=%20segmentSize)%20{
 %20 %20 %20 %20 %20 %20 %20  intend= (i%20+%20segmentSize)%20<%20length%20?%20(i%20+%20segmentSize)%20:%20(int)%20length;
 %20 %20 %20 %20 %20 %20 %20 %20XposedBridge.log(str.substring(i,%20end));
 %20 %20 %20 %20 %20 %20}
 %20 %20 %20 %20 %20 %20XposedBridge.log(\"分段打印结束。\");
 %20 %20 %20 %20}
 %20 %20}
}