超星某习通firda检测及定位签到分析

查看 91|回复 9
作者:buluo533   
[color=]本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关.本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责
众所周知学习代码也是学习,研究研究超星某习通的firda检测和签到
一、环境信息
firda 16.5.6frIDA-tools 13.6.0样本版本信息: 6.6.2


image.png (139.85 KB, 下载次数: 0)
下载附件
样本
2025-9-22 18:31 上传

工具:jadx
小黄鸟
yang神脱壳脚本:https://github.com/lasting-yang/frida_dump
经纬度查询:https://map.yanue.net/
参考文章:
某当劳 Frida 检测
aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3Mva1pQWW1fSXItMzljZzdfWTdJc2UzQQ==

[color=]安卓壳学习记录
aHR0cHM6Ly9iYnMua2FueHVlLmNvbS90aHJlYWQtMjg1ODcwLmh0bQ==
安卓加壳脱壳原理-简单概要 https://www.52pojie.cn/thread-1865310-1-4.html
二、frida过检测   
将app简单的提取出来,通过文章的一些信息我们知道了这个企业壳的so文件是
libDexHelper.so,
我们可以简单hook一下dlopen加载过程,看看这一个样本的情况
[JavaScript] 纯文本查看 复制代码function hook_dlopen() {
  var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
  console.log("addr_android_dlopen_ext", android_dlopen_ext);
  Interceptor.attach(android_dlopen_ext, {
    onEnter: function (args) {
      var pathptr = args[0];
      if (pathptr != null && pathptr != undefined) {
        var path = ptr(pathptr).readCString();
        console.log("android_dlopen_ext:", path);
      }
    },
    onLeave: function (retvel) {
    }
  })
}
function main() {
   hook_dlopen()
}
setImmediate(main)
// frida -U -f com.chaoxing.mobile -l .\xxt_hook.js
  


image.png (789 KB, 下载次数: 1)
下载附件
so文件启动
2025-9-22 18:32 上传


  
可以看到一个手机处于一个打开界面卡死,frida进程也被杀死的一个状态,同时也加载出了我们壳特征的so文件,我们知道这个是通过线程检测的,我们去hook线程的加载,这里我们采取用的是clone。
[JavaScript] 纯文本查看 复制代码function hook_clone() {
  var clone = Module.findExportByName('libc.so', 'clone');
  Interceptor.attach(clone, {
    onEnter: function (args) {
      if (args[3] != 0) {
        // 真正的用户线程函数地址
        var addr = args[3].add(96).readPointer()  // 读取指针
        var so_name = Process.findModuleByAddress(addr).name;
        // 获取该 so 在进程里的基址
        var so_base = Module.getBaseAddress(so_name);
        // 获取相对于 so_base 的偏移
        var offset = (addr - so_base);
        console.log("===============>", so_name, addr, ptr(offset));
      }
    },
    onLeave: function (retval) {
    }
  });
}
[C] 纯文本查看 复制代码#include
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
这里有一个96的偏移,可以参考原函数,我们需要拿到的是线程的地址,也就是第四个参数,然后调用


image.png (830.27 KB, 下载次数: 1)
下载附件
线程
2025-9-22 18:32 上传

   
这里我们可以看到壳的线程创建,这里没有通过so去分析,根据文章直接去测试替换掉线程检测函数,frida也有提供api,举一个例子。
[JavaScript] 纯文本查看 复制代码function frida_Interceptor() {
    var add_method = new NativeFunction(Module.findExportByName('libhello.so', 'c_getSum'),
                                        'int',['int','int']);
    //输出结果 那结果肯定就是 3
    console.log("result:",add_method(1,2));
    //这里对原函数的功能进行替换实现
    Interceptor.replace(add_method, new NativeCallback(function (a, b) {
      //h不论是什么参数都返回123
      return 123;
    }, 'int', ['int', 'int']));
    //再次调用 则返回123
    console.log("result:",add_method(1,2));
  ;
}
这里的话呢,我们直接将返回值和入参都直接置空,就可以实现替换
[JavaScript] 纯文本查看 复制代码function hook_remove(so_name) {
  Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
    onEnter: function (args) {
      var pathptr = args[0];
      if (pathptr !== undefined && pathptr != null) {
        var path = ptr(pathptr).readCString();
        if (path.indexOf(so_name) !== -1) {
          this.match = true;
        }
        if (args[0].readCString() != null && args[0].readCString().indexOf("libmsaoaidsec.so") >= 0) {
          hook_pth()
        }
      }
    },
    onLeave: function (retval) {
      if (this.match) {
        console.log(so_name + " 加载成功");
        var base = Module.findBaseAddress(so_name);
        console.log("基址:", base)
        if (base === null) {
          console.error("!!加载成功,但未找到基址:", so_name);
          return;
        }
        patch_func_nop(base.add(0x4c574));
        patch_func_nop(base.add(0x56c10));
        patch_func_nop(base.add(0x54584));
        patch_func_nop(base.add(0x5c3c4));
        console.log("libDexHelper.so文件处理成功")
      }
    }
  });
}
function main() {
  hook_remove("libDexHelper.so");
}
setImmediate(main)
这样就实现了过掉frida的线程检测,脱壳部分可以直接参考yang神的项目文档,写的非常清楚,然后将脱壳后的代码放到jadx中进行分析
三、定位修改样例分析        
当我们实现脱壳,过掉frida检测时,在测试过程中有出现过root环境的一个检测(概率事件,没截到图,小伙伴遇到了),直接搜索一个文本内容
     


image.png (173.86 KB, 下载次数: 1)
下载附件
root文本
2025-9-22 18:33 上传

   
  


image.png (406.32 KB, 下载次数: 1)
下载附件
su检测
2025-9-22 18:33 上传


还是比较简单的一个root检测。直接firda一把梭
[JavaScript] 纯文本查看 复制代码function java_root() {
  Java.perform(function () {
    let m = Java.use("ge.m");
    m["g"].implementation = function (context, key, defaultValue) {
      console.log(`m.g is called: context=${context}, key=${key}, defaultValue=${defaultValue}`);
      let result = this["g"](context, key, defaultValue);
      if (!result) {
        result = true;
        return result;
      }
      return result
    };
  })
}
接下来就需要和小伙伴配合了,感谢我威哥的配合。


image.png (53.75 KB, 下载次数: 1)
下载附件
课程创建
2025-9-22 18:34 上传

   
创建两个课程,用来方便测试,发送签到信息。我们先发送普通签到用来测试一个接口的信息。


image.png (153.7 KB, 下载次数: 1)
下载附件
普通接口
2025-9-22 18:34 上传

     
这有一个seccess的返回值,可以合理猜测一下了,其他的好像都是js文件,内嵌的一个webview??重放处理一下。


image.png (159.09 KB, 下载次数: 1)
下载附件
重放
2025-9-22 18:34 上传



image.png (22.43 KB, 下载次数: 1)
下载附件
重放接口
2025-9-22 18:34 上传


这样我们就可以确定一个基本的接口信息,在后面的我们可以过滤非必要的信息。接下来就梭哈定位签到,我们需要用到一个经纬度的网站。直接发定位签到


image.png (300.88 KB, 下载次数: 0)
下载附件
西湖定位
2025-9-22 18:35 上传

可以看到我目前处于西湖的状态,定位要求在故宫博物馆,抓一下现在的接口信息
  


image.png (115.65 KB, 下载次数: 0)
下载附件
定位接口
2025-9-22 18:35 上传

  
可以看到,这个大概就是一个经纬度信息,我们需要把这个换成我们想要的,然后发送过去,搜一下latitude关键词


image.png (1.05 MB, 下载次数: 1)
下载附件
经纬度度检测
2025-9-22 18:35 上传


    可以看到搜出来的结果很多,因为这里是作为请求里面的数据,我们可以看到是使用了JSONObject来存储,大概是在这里进行的,然后来调用,这里我测试hook了几个,但是都没有出结果,我想到了去hook JSONObject的put方法,因为put在存储是涉及不同的数据类型,需要重载,这里我们可以看到,使用的是double类型,我们去实现一下。
[JavaScript] 纯文本查看 复制代码function java_root() {
  Java.perform(function () {
    let m = Java.use("ge.m");
    m["g"].implementation = function (context, key, defaultValue) {
      console.log(`m.g is called: context=${context}, key=${key}, defaultValue=${defaultValue}`);
      let result = this["g"](context, key, defaultValue);
      if (!result) {
        result = true;
        return result;
      }
      return result
    };
  })
}
这里不写入主函数,在需要的时候直接调用。


image.png (267.76 KB, 下载次数: 1)
下载附件
定位接口触发
2025-9-22 18:36 上传

  
当我们点击获取地址时,就会触发这个接口,我们提前将这个函数注入,就可以看到latitude和longitude的写入


image.png (811.41 KB, 下载次数: 1)
下载附件
经纬度写入
2025-9-22 18:36 上传


获取一下经纬度信息,我们加一个判断,把入参给改一下
[JavaScript] 纯文本查看 复制代码function hook_location() {
  Java.perform(function () {
    let JSONObject = Java.use("org.json.JSONObject");
    JSONObject["put"].overload('java.lang.String', 'double').implementation = function (str, obj) {
      console.log('double类型入参===>', str, obj)
      let result = this["put"](str, obj);
      return result;
    };
  })
}
这样发现我们好像改成功了
  


image.png (332.48 KB, 下载次数: 0)
下载附件
修改测试
2025-9-22 18:36 上传



image.png (84.68 KB, 下载次数: 1)
下载附件
后台
2025-9-22 18:37 上传

因为我们在抓包的时候发现还有一个地址的名字的传入,这个发现是后台的可以查看的信息,这个需要改一下了,严谨一点,但是这个在put写入的时候就又涉及到数据类型
[JavaScript] 纯文本查看 复制代码function hook_location() {
  Java.perform(function () {
    let JSONObject = Java.use("org.json.JSONObject");
    JSONObject["put"].overload('java.lang.String', 'double').implementation = function (str, obj) {
      console.log('double类型入参===>', str, obj)
      if (str == "latitude") {
        obj = 39.924091367210636
      }
      if (str == 'longitude') {
        obj = 116.4034138534206
      }
      let result = this["put"](str, obj);
      return result;
    };
    JSONObject["put"].overload('java.lang.String', 'java.lang.Object').implementation = function (str, obj) {
      console.log('Object类型入参===>', str, obj)
      if (str == "address") {
        obj = "故宫博物馆"
      }
      let obj_result = this["put"](str, obj);
      return obj_result;
    };
  })
}
这样修改一下,我们就成功实现了一个定位签到的修改,以及后台信息的匹配


image.png (158.56 KB, 下载次数: 1)
下载附件
结果1
2025-9-22 18:37 上传



image.png (43.04 KB, 下载次数: 1)
下载附件
结果2
2025-9-22 18:37 上传

四、总结        
目前这个属于测试过程,后续也会做成一个xposed模块,继续对拍照,二维码等方面进行处理。毕竟学习学习通代码也是学习。好好学习,天天向上。{:1_932:}读大佬文章觉得自己太菜了,继续学习{:1_923:}[md]```

下载次数, 下载附件

jiang01258   

伟大无需多言
Benincasamatch   

给大佬点赞!可惜现在手机root权限太难获取了,能这样学习的地方越来越少了,我个人是用不了这种方法了
kikyo293   

太实用了,感谢
buluo533
OP
  

改了一次,不知道有没有漏掉和错误的地方,大佬见谅
阿灰   

我也是过来学习的,虽然偶尔看不懂,但是不影响我学习的,哈哈。
xixicoco   

图片加载不出来啊
xixicoco   

你图里面老是这个加载:[i]  应该没有搞对
helian147   

外链图片全挂了
J3ggedPeak   

学习了!!!
您需要登录后才可以回帖 登录 | 立即注册