当前位置: 首页 > news >正文

frida安装配置及其使用方法

Frida安装

 pip install frida-tools -i https://pypi.tuna.tsinghua.edu.cn/simplefrida --version

ADB(Android Debug Bridge) 环境搭建

https://googledownloads.cn/android/repository/platform-tools-latest-windows.zip

解压缩后配置环境变量

 adb --version

逍遥模拟器虚拟设备设置

检测root权限是否开启

开启开发者模式并开启USB调试

  • 打开设置

  • 找到关于平板电脑

  • 连续点击版本号

  • 返回一下点击开发者选项

  • 打开USB选项

开始搭建Frida环境

1. push fs(Frida-server) 文件至虚拟设备

逍遥模拟器的虚拟设备默认端口为 21503 每增加一个虚拟设备,其端口号“加10”,如第一个虚拟设备的端口是21503,那么第二个虚拟设备的端口就是21513

  1. 先终止一下ADB服务

     adb kill-server
  2. 通过指令链接到逍遥模拟器

     adb connect 127.0.0.1:21503
  3. 列出已知设备

     adb devices
  4. 链接设备(注意!请确保已按照上文方法开启【USB调试】如果显示已知设备不唯一,则可以通过 -s <设备> 参数指定设备,如:adb -s 127.0.0.1:21503 shell

     adb shell​获取设备架构信息(用于确认Frida-server版本)指令在 adb shell 成功后,在shell对话中输入 getprop ro.product.cpu.abi 即可获取设备架构信息获取架构信息后,再与安装的Frida版本结合,便可前去Github下载其Frida-server文件命名格式如下:frida-server-<Frida版本>-android-<设备架构版本>.xz
  5. push fs(Frida-server)文件至 /data/local/tmp

    • exit 退出shell会话

    • 再输入 adb push <Frida-server 文件绝对路径> /data/local/tmp

2. 给予 Frida-server 最高权限

实际操作
 adb shellcd /data/local/tmpchmod 777 fs

3. 运行 Frida-server

验证Frida-server工作

  1. 新开启一个CMD

  2. 输入进行端口转发(一般不转发也没事)

     adb forward tcp:27042 tcp:27042adb forward tcp:27043 tcp:27043adb shell am start -D -n  com.example.app/.MainActivityadb jdwp 查看可以转发的端口
  3. 再输入 frida-ps -U ,令其列出所有进程

配置证书

按网上步骤即可,遇到不能上传执行下述命令

 adb rootadb remount

常用Frida tools命令

 frida-ls-devices 查看连接设备frida-ps -U 通过USB或者WIFI列出正在运行的进程frida-ps -Ua 列出正在运行的应用frida-ps -Uai 列出安装的应用frida-kill -D device-id pid

注入的两种方法

python脚本交互

 import frida# 定义要注入的 JavaScript 脚本js_code = """console.log("[*] Script loaded successfully.");"""# 定义目标进程名称target_process = "medical"# 获取 USB 设备device = frida.get_usb_device()# 附加到目标进程session = device.attach(target_process)# 创建脚本并加载script = session.create_script(js_code)script.load()

js代码

 // Hook 模板Java.perform(function () {// 查找目标类var TargetClass = Java.use("com.example.target.ClassName");// Hook 目标方法TargetClass.targetMethod.implementation = function (arg1, arg2) {console.log("[*] Hooked targetMethod called!");console.log("    arg1: " + arg1);console.log("    arg2: " + arg2);// 调用原始方法var result = this.targetMethod(arg1, arg2);console.log("    Original result: " + result);// 修改返回值var modifiedResult = "Modified Result";console.log("    Modified result: " + modifiedResult);return modifiedResult;};});
  1. 将此代码保存为 hook.js。

  2. 使用 Frida 命令行工具加载脚本:

     frida -U -n <目标进程名> -s hook.jsfrida -l hook.js -U 目标名称
  3. 替换 com.example.target.ClassNametargetMethod 为实际的目标类和方法名称。

 // Hook Native 函数Interceptor.attach(Module.findExportByName("libtarget.so", "target_function"), {onEnter: function (args) {console.log("[*] Hooked target_function called!");console.log("    arg0: " + args[0].toInt32());console.log("    arg1: " + args[1].readUtf8String());},onLeave: function (retval) {console.log("    Original return value: " + retval.toInt32());// 修改返回值retval.replace(12345);console.log("    Modified return value: " + retval.toInt32());}});
  • onEnter在函数执行第一条指令前执行,可以读取或修改参数数据

  • onLeave在函数返回时执行,可以读取或修改函数的返回值

  • Module.findExportByName查找符号对应的函数地址

HOOK重载方法

1. 使用 .overload()指定方法签名

 Java.perform(function() {var targetClass = Java.use("com.example.ClassName");// Hook test(String)targetClass.test.overload('java.lang.String').implementation = function(s) {console.log("Called test(String): " + s);return this.test(s); // 调用原方法};// Hook test(int)targetClass.test.overload('int').implementation = function(i) {console.log("Called test(int): " + i);return this.test(i);};// Hook test(String, int)targetClass.test.overload('java.lang.String', 'int').implementation = function(s, i) {console.log("Called test(String, int): " + s + ", " + i);return this.test(s, i);};});

2. 获取所有重载方法

 Java.perform(function() {var targetClass = Java.use("com.example.ClassName");// 获取方法的所有重载版本var overloads = targetClass.test.overloads;for (var i = 0; i < overloads.length; i++) {overloads[i].implementation = function() {console.log("test called with args: " + Array.prototype.slice.call(arguments));return this.test.apply(this, arguments); // 调用原方法};}});

HOOK对象参数

 Java.perform(function() {// Hook一个方法并构造参数const TargetClass = Java.use('com.example.TargetClass');TargetClass.targetMethod.implementation = function(arg1, arg2) {// 构造新参数const newArg1 = Java.use('java.lang.String').$new('Hooked!');const newArg2 = Java.use('java.util.ArrayList').$new();newArg2.add(Java.use('java.lang.Integer').$new(123));// 调用原方法return this.targetMethod(newArg1, newArg2);};});

枚举所有类和类方法

Java.perform(function() {// 获取所有已加载的类var classes = Java.enumerateLoadedClassesSync();// 遍历所有类classes.forEach(function(className) {try {// 获取类引用var targetClass = Java.use(className);// 获取类所有方法var methods = targetClass.class.getDeclaredMethods();console.log("\n[+] Class: " + className);// 遍历类方法for (var i = 0; i < methods.length; i++) {var method = methods[i];var methodName = method.getName();var returnType = method.getReturnType().getName();var parameterTypes = method.getParameterTypes();// 构建参数类型字符串var params = [];for (var j = 0; j < parameterTypes.length; j++) {params.push(parameterTypes[j].getName());}console.log("  |- Method: " + returnType + " " + methodName + "(" + params.join(", ") + ")");// Hook 方法并修改对象属性hookMethod(targetClass, methodName, params);}} catch (e) {// 忽略无法访问的类// console.log("Error with class: " + className + " - " + e);}});
});function hookMethod(targetClass, methodName, paramTypes) {// 根据参数类型数量生成实现函数var overloads = targetClass[methodName].overloads;for (var i = 0; i < overloads.length; i++) {overloads[i].implementation = function() {// 打印调用信息console.log("\n*** Called: " + targetClass.$className + "." + methodName);// 打印参数for (var j = 0; j < arguments.length; j++) {var arg = arguments[j];console.log("  |- arg[" + j + "]: " + arg);// 如果是对象,尝试修改其属性//if (arg && arg.getClass) {//try {modifyObjectProperties(arg);//} catch (e) {console.log("  |- Failed to modify object properties: " + e);//}//}}// 调用原始方法return this[methodName].apply(this, arguments);};}
}function modifyObjectProperties(obj) {// 获取对象类var objClass = obj.getClass();// 获取所有字段var fields = objClass.getDeclaredFields();for (var i = 0; i < fields.length; i++) {var field = fields[i];field.setAccessible(true);var fieldName = field.getName();var fieldType = field.getType().getName();var originalValue = field.get(obj);console.log("    |- Field: " + fieldType + " " + fieldName + " = " + originalValue);// 修改字符串字段if (fieldType === "java.lang.String" && originalValue !== null) {var newValue = originalValue + "_modified";field.set(obj, newValue);console.log("    |  Changed to: " + newValue);}// 修改int字段if (fieldType === "int") {var newValue = originalValue + 1000;field.set(obj, newValue);console.log("    |  Changed to: " + newValue);}// 修改boolean字段if (fieldType === "boolean") {var newValue = !originalValue;field.set(obj, newValue);console.log("    |  Changed to: " + newValue);}}
}

主动调用方法

Java.perform(function() {// 导入需要的Java类var RSA = Java.use("com.null.fridaapp.RSA"); // RSA加密类var String = Java.use("java.lang.String");   // Java字符串类var Base64 = Java.use("android.util.Base64"); // Base64编码类// 准备要加密的明文var plaintext = "syj";// 将字符串转换为字节数组var plaintextBytes = String.$new(plaintext).getBytes();console.log("原始字符串字节表示: " + JSON.stringify(plaintextBytes));try {// 调用RSA类的静态encrypt方法进行加密var encryptedBytes = RSA.encrypt(plaintextBytes);console.log("加密后的字节长度: " + encryptedBytes.length);// 将加密结果进行Base64编码以便查看var base64Result = Base64.encodeToString(encryptedBytes, 0);console.log("Base64编码后的加密结果: " + base64Result);} catch (e) {console.log("加密过程中出现错误: " + e);}
});
public static byte[] encrypt(byte[] plaintext) throws Exception {PublicKey publicKey = getPublicKey(PublicKey);Cipher cipher = Cipher.getInstance("RSA/None/NoPadding", "BC");cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 1对应Cipher.ENCRYPT_MODEreturn cipher.doFinal(plaintext);
}
http://www.dtcms.com/a/348027.html

相关文章:

  • 一个奇怪的问题-Python会替代Java吗?技术语言之争的真相-优雅草卓伊凡
  • Java 大视界 -- Java 大数据在智能交通智能公交系统中的乘客流量预测与车辆调度优化
  • 程序里的依赖和中间件的依赖冲突,怎么解决
  • Docling:一个基于AI驱动的免费文档解析工具
  • Python性能优化实战(二):让循环跑得比博尔特还快
  • [身份验证脚手架] 应用布局如何构建
  • 初学python的我开始Leetcode题-16
  • CTFshow系列——命令执行web49-52
  • assert使用方法
  • Redis 高可用开发指南
  • 力扣594:最和谐子序列
  • 客流特征识别误报率↓76%!陌讯多模态时序融合算法在智慧零售的实战解析
  • Tesla智能座舱域控制器(MCU)的系统化梳理
  • 【网络运维】Shell 脚本编程:if 条件语句
  • 【40页PPT】数字工厂一体化运营管控平台解决方案(附下载方式)
  • Spark04-MLib library01-机器学习的介绍
  • SNMP 协议的总结
  • 每日算法题【链表】:相交链表、环形链表、环形链表II
  • 鸿蒙分布式计算实战:用 ArkTS+Worker 池落地可运行任务管理 Demo,从单设备到跨设备全方案
  • [二维前缀和]1277. 统计全为 1 的正方形子矩阵
  • HarmonyOS实战(DevEco AI篇)—深度体验DevEco CodeGenie智能编程助手
  • Function + 枚举 + Map:轻量路由器的最佳实践
  • ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘192.168.24.96‘ (10060)
  • 基于Java、GeoTools与PostGIS的对跖点求解研究
  • 大数据毕业设计选题推荐:基于Spark+Django的学生创业数据分析可视化系统详解 毕业设计/选题推荐/深度学习/数据分析/数据挖掘/机器学习/随机森林
  • 网络编程socket-Udp
  • Linux网络启程
  • Java基础(十四)分布式
  • 《Distilling the Knowledge in a Neural Network》论文PDF分享, 2015 年,谷歌提出了 “知识蒸馏” 的概念
  • 深入解析Apache Kafka的核心概念:构建高吞吐分布式流处理平台