frida 入门

一直想学 frida 一直鸽,终于有 ctf 用到了,我测东西这么多

官方文档感觉写的依托,这 python rpc 直接拿来入门真的太有生活了

frida 是一个动态插桩 (dynamic instrumentation) 工具,提供了交互式 cli 界面来追踪函数行为。用人话说就是允许用户从任意位置跳转执行自定义代码,用 js 代码片段 hook 原始程序的任意位置。具体而言,类似断点的实现方法,frida 会将 hook 入口处的汇编指令替换为跳转到 js 引擎的 jmp 指令,在 js 运行完毕时复原汇编代码。

典型的应用场景:从任意行号开始执行、替换任意函数的实现

文章目录

  • 安装
    • 安装类型补全
    • frida-gum 介绍
  • frida 使用:插桩 apk
    • 注入 frida-core 并启动 cli
    • 插桩安卓 Java 程序
      • frida hook Java 中动态加载的 dex
      • frida 调用额外 .dex 文件的函数
      • 在 activity 启动前附加 frida
      • 在 frida 中定义类,实现一个接口
      • 打印 stacktrace
    • 插桩安卓 so 原生代码
      • 按名字查找 export 函数
      • 按名字查找 module
      • 枚举 module 的符号
      • hook RegisterNative
      • 识别 jclass
      • 按地址 hook 函数
  • 使用 frida stalker 进行 assembly tracing
  • frida-python
  • MISC
    • 便捷命令 - frida-ps, frida-trace
    • 在 jailed iOS/Android 使用 frida
    • frida 辅助分析 OLLVM
      • 常见特征
      • 技巧
    • ref

安装

直接 pip install 即可。安装后会创建 frida, frida-ps 等命令。miniconda 会在切换时将 Scripts 添加到 PATH,在 windows 也可以直接用。

安装类型补全

利用 vscode 自动导入 ts 类型的机制,在 pwd 下 npm install @types/frida-gum 可以安装类型补全。这样之后写 js 的回调就有 type hint 了

frida-gum 介绍

上面依赖中出现的 gum 是 frida 的动态插桩核心库 Gum 的意思。Gum 用 C 开发,支持访问整个内存空间。考虑到 hook 的代码变化会很频繁,frida 又提供了一套脚本语言的 api GumJS ,为用户省去构建流程,缩短逆向开发时的反馈周期。

在运行时,GumGumJs 被打包成共享库注入到目标进程内。自定义脚本在用户进程中,通过 ipc 跨进程代理变量访问。这一打包、注入、双向通信的工作由 frida-core 完成。frida-core 包含了 frida 在目标机的主要功能,除了支持 gum 注入外,还包含 ps,枚举安装程序等功能。

frida 使用:插桩 apk

Frida 提供了简洁的语法,支持用户利用 js 的 api 通过字符串名称筛选符号,找到目标模块、目标类、目标对象或目标函数后,最后在 js 中检查传入参数和返回值、并支持用回调函数覆盖目标的实现。

Frida 依赖操作系统的调试 syscall 实现 hook (JVM, webasm 运行在 custom 解释器),因此天生依赖 OS,所以也会在用户体验上对 os 做很多优化。Frida 支持 Windows/Linux, Android, iOS, macos 等多种系统。被主要用于 Android/iOS, webasm 等环境。PC 系统上,Frida 只支持 Ring3 的部分特性因此不如其他平台好用,在这些平台常常需要其他工具来配合。

注入 frida-core 并启动 cli

注入 js 脚本的基础语法形如:

frida -U -f com.example.someapp -l hook.js

这个命令会在当前 shell 创建一个 REPL cli 交互环境,类似浏览器的 console,用户在里面敲命令回显结果。

  • -l 参数加载 js 脚本文件。和浏览器一样,加载 js 文件后,可以在 cli 敲符号名运行自定义的函数,也可以直接在 js 写 setImmediate(main) 加载后立即运行 main。frida 支持 js 脚本的热更新,在 js 文件 onSave 的时候会触发重新加载
  • -f 参数会 spawn 一个新的目标程序
  • -U 表示通过 USB 在目标设备上运行程序(而非当前客户机),调试移动端通常都会有 -U。理论上需要在手机上安装并启动 frida-server,但实测下来雷电模拟器似乎并不需要,不知道为啥

frida-server 在目标机运行 frida-core,并对外暴露一个 tcp 服务通信

插桩安卓 Java 程序

编写 hook.js 如下:

function main() {// Java perform 指进入 jvm 执行回调Java.perform(function() {var _class = Java.use('java.lang.String') // 从全限定名拿到 class// 根据名称直接访问成员,用类型 spec 重载函数。(变量和函数同名会将变量添加 _ 前缀)// .impl hook 函数实现_class.someMethod.overload("int", "int").implementation = function(arg0, arg1) {             var ret = this.someMethod(arg0, arg1) // this 访问原始函数console.log(arg0, arg1, ret) // 通过 log 打印return ret}let string = _class.$new("helloworld").getBytes()this.m.value = 0; // 直接设置变量值Java.choose // 从 cls 枚举所有 obj})
}setImmediate(main) // 异步执行 main 避免阻塞

常见开发模式:在 aosp java 的源码里搜索内部调用链,找一个合适的 hook 掉

frida hook Java 中动态加载的 dex

有些时候,Java 会在运行时动态加载 dex,frida 可能找不到。这是因为 frida 默认的 classloader 不一致,需要在 js 里通过 Java.enumerateClassLoaders 切换 classLoader.

frida 调用额外 .dex 文件的函数

逆向工程师可以自己写一个 Java 程序,用 d8 编译成 dex 文件后,通过 frida 的 openClassFile 加载到 frida 的 VM 里。之后,可以在 frida 中同样地用 Java.use 调用自己写的 Java 函数。

在 activity 启动前附加 frida

在启动 frida 时,指定 --no-pause -f 参数,并在 js 里 hook ActivityThread.getApplicationContext

在 frida 中定义类,实现一个接口

参看 api 文档的 Java.registerClass 节。可以实现一个新的类,用 js 编写类的成员函数,并实现接口条件。

打印 stacktrace

两种实现,既可以 hook Java 的 java.lang.Exception 类,查看文档选择 element。似乎也可以用 backtrace 的 api

插桩安卓 so 原生代码

动态库的导出其实和 js 有点像,会指明 import 和 export。在 IDA 可以看到有一个 exports 面板展示了所有导出的函数。对于 export 的函数,frida 可以直接通过函数名定位并 hook。对于其他函数,不管函数有没有导出,frida 都支持直接索引地址 hook,也可以 hook 到函数内部的任意汇编位置。(似乎非 export 函数也能按名字hook

由于安卓程序的入口是 Java,在 System.loadLibrary 之前 so 还没有加载。所以通常需要将 Interceptor 放到 loadLibrary 的 hook 回调里。也看到过放到 linker 的 Android dlopen 函数后面的,或者也可以手动在 cli 执行函数。

按名字查找 export 函数

借助 InterceptorModule.getExportByName 可以实现通过字符串符号名 hook 动态库 module 的函数。这里 Module 是专门用来处理动态库的组件,甚至可以写一个新 c 函数。回到 hook,文档里给的例子是 hook socket, inet 库的 send 函数,修改入参的 ip 地址以实现向别处发包。

const st = Memory.alloc(16);
// Now we need to fill it - this is a bit blunt, but works...
st.writeByteArray([0x02, 0x00, 0x13, 0x89, 0x7F, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]);
// Module.getExportByName() can find functions without knowing the source
// module, but it's slower, especially over large binaries! YMMV...
Interceptor.attach(Module.getExportByName(null, 'connect'), {onEnter(args) {send('Injecting malicious byte array:');args[1] = st;}//, onLeave(retval) {//   retval.replace(0); // Use this to manipulate the return value//}
});// Use Interceptor.replace to replace impl.

按名字查找 module

Process.findModuleByName, 见下节

枚举 module 的符号

如果是通过 JNIOnload 或其他方法动态注册的 Native 函数。被注册的 Native 函数本身并不是 export 的。此时可以 hook libart 的 RegisterNative 函数,劫持注册过程。

let libart_module = Process.findModuleByName("libart.so")
let symbols = libart_module.enumerateSymbols()for (var i = 0; i < symbols.length; i++) {var name = symbols[i].nameif (name.indexOf("RegisterNative")) {}
}

hook RegisterNative

识别 jclass

jclass 在底层只是一个序号,可以通过 frida-java-bridge 的 Env.getClassName 转换得到类名等信息

frida-java-bridge 提供了 jclass 的解析库,可以在直接使用。

Java.vm.tryGetEnv().getClassName(jclass)

按地址 hook 函数

通过地址 hook 有多种实现方法:

// 用 `Interceptor.attach` hook 特定地址。ptr 是 frida 的指针类
let base = Module.findBaseAddress("my.so")
Interceptor.attach(ptr("0x1234"), { // Or base.addonEnter(args) {console.log(args[0].toInt32());args[0] = ...}
});// 用 NativeFunction 封装二进制函数在 js invoke
// 用 Memory 在目标进程 malloc 内存,并在 invoke 传参新指针
const st = Memory.allocUtf8String("TESTMEPLZ!"); // See also: Memory.alloc(), Memory.protect()
const f = new NativeFunction(ptr("0x1234"), 'int', ['pointer']);// In NativeFunction param 2 is the return value type,// and param 3 is an array of input types
f(st);

按地址 hook 具有很强的灵活性。可以 hook 到函数内部的某一条汇编指令然后修改寄存器。这种被称作内联 hook

Imyang 说,内联 hook(hook到函数内部的 asm)不如 hook 函数入口稳定。能用倒是

使用 frida stalker 进行 assembly tracing

由于 ida 反编译现在已经相对比较成熟,所以市面上也会有对 c 程序进行混淆的工具链。逆向混淆后的程序很折磨,特别是引入虚假控制流程和控制流平坦化后,难以识别到底哪些代码被执行了。在这种时候,可以追踪每条实际执行的汇编指令,得到实际执行的汇编指令串。IDA 和 frida 都提供了 tracer 模块。

frida stalker 可以跟随线程的执行,跟踪每个函数、基本块和指令。具体使用不想写了。

frida-python

官方文档乱的要死

rpc,姑且可以先看看官网的例子

MISC

便捷命令 - frida-ps, frida-trace

官方文档从这里入门,但对 cli 参数基本没有解释。我每次都很难对上脑电波,一定是 doc 写的依托答辩 :\

frida 除了 frida 命令外,还提供 frida-ps, frida-trace 等 cli 命令,帮助用户快速跟踪函数。

frida-ps 可以直接敲,类似 ps 可以打印进程的名字。

frida-trace 需要附加额外参数,例如 frida-trace -i "recv*" "Clash for Windows.exe" 会按照进程名称字符串或 pid 把 frida 附加到进程,然后 trace 所有以 recv 开头的受支持函数。frida-trace 会给每个监听函数生成 js 模板,用户可以修改回调脚本,热更新刷新 trace 的行为。

frida-trace 自动生成的模板包含 OnEnterOnLeave 两个关键函数,分别在目标函数进入和退出时同步调用。用户可以自定义回调函数的行为,支持覆盖参数和返回值。

{/*** Called synchronously when about to call recvfrom.** @this {object} - Object allowing you to store state for* use in onLeave.* @param {function} log - Call this function with a string* to be presented to the user.* @param {array} args - Function arguments represented as* an array of NativePointer objects.* For example use args[0].readUtf8String() if the first* argument is a pointer to a C string encoded as UTF-8.* It is also possible to modify arguments by assigning a* NativePointer object to an element of this array.* @param {object} state - Object allowing you to keep* state across function calls.* Only one JavaScript function will execute at a time, so* do not worry about race-conditions. However, do not use* this to store function arguments across onEnter/onLeave,* but instead use "this" which is an object for keeping* state local to an invocation.*/onEnter(log, args, state) {log("recvfrom()");log("recvfrom(socket=" + args[0].toInt32()+ ", buffer=" + args[1]+ ", length=" + args[2].toInt32()+ ", flags=" + args[3]+ ", address=" + args[4]+ ", address_len=" + args[5].readPointer().toInt32()+ ")");},/*** Called synchronously when about to return from recvfrom.** See onEnter for details.** @this {object} - Object allowing you to access state* stored in onEnter.* @param {function} log - Call this function with a string* to be presented to the user.* @param {NativePointer} retval - Return value represented* as a NativePointer object.* @param {object} state - Object allowing you to keep* state across function calls.*/onLeave(log, retval, state) {}
}

在 jailed iOS/Android 使用 frida

在 root 的 Android 下可以直接将 frida attach 到一个进程上,这被称为 inject mode

但在 jailed OS 上该功能可能受限。在这些设备上,Frida 提供 frida-gadget 动态共享库,开发者需要在编译应用时把 frida-gadget 加入到 lib 中,从而在应用启动时自带 frida 功能。这被称为 embed 模式。(我感觉主要用于调试而非逆向)

除了编译 so,官网也给了 其他途径 把 frida-gadget 嵌入到程序中,包括 LD_PRELOAD( DYLD_INSERT_LIBRARIES), patch binary

frida 辅助分析 OLLVM

OLLVM(obfuscated LLVM) 是对 C 代码的混淆工具,额外增加了逆向的难度。混淆器可以把简单的混淆策略迭代多轮,提高复杂度。

常见特征

  1. 程序所有常量加密,在 .init_array 存在解密函数。(官方默认解密函数名是 datadiv_decode 但可以换)
  2. 控制流平坦化:while 1 …
  3. 指令替换:c = a+b => { r = rand(); c = a - (-b) = a - r - (-b) - (-r)。

技巧

hook 随机数发生器固定结果。然后多次调用函数根据输入输出猜函数功能

Google 搜索反编译结果里的特征查找算法的公开实现,包括 hex 常量,字节数组

识别混淆策略。如指令替换的 r,识别之后只看输入输出猜结果不管过程。

停止其他线程以防反调试。

ref

http://littleshark.space/2024/08/25/Frida%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Frida%E4%BD%BF%E7%94%A8%E5%A4%A7%E5%85%A8/

阿 b 直接搜 frida 看别人操作会直观很多:
https://www.bilibili.com/video/BV1wt4y1n7cq
https://www.bilibili.com/video/BV1G4sxemEuA

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/12484.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据技术】教程03:本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …

Notepad++消除生成bak文件

设置(T) ⇒ 首选项... ⇒ 备份 ⇒ 勾选 "禁用" 勾选禁用 就不会再生成bak文件了 notepad怎么修改字符集编码格式为gbk 如图所示

CSS布局(一)flex一篇搞定

目录 一、flex布局 1.1. 认识flex布局 1.2. flex布局重要的概念 二、flex container中的属性 2.1.flex-direction 2.2.flex-wrap、flex-flow 2.3.justify-content 2.4.align-items 2.5.align-content 三、 flex item中的属性 3.1.order 3.2.align-self 3.3.flex-gr…

e2studio开发RA2E1(5)----GPIO输入检测

e2studio开发RA2E1.5--GPIO输入检测 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置GPIO口配置按键口配置按键口&Led配置R_IOPORT_PortRead()函数原型R_IOPORT_PinRead()函数原型代码 概述 本篇文章主要介绍如何…

[吾爱出品]CursorWorkshop V6.33 专业鼠标光标制作工具-简体中文汉化绿色版

CursorWorkshop V6.33 专业鼠标光标制作工具 链接&#xff1a;https://pan.xunlei.com/s/VOIFeq5DFB9FS56Al_mT2EfdA1?pwd7ij4# 产品概述 Axialis CursorWorkshop 是一个专业光标创作工具它在 Windows 下运行&#xff0c;让您轻松创建高质量的静态和动态光标适用于 Windows …

STM32单片机学习记录(2.2)

一、STM32 13.1 - PWR简介 1. PWR&#xff08;Power Control&#xff09;电源控制 &#xff08;1&#xff09;PWR负责管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压监测器和低功耗模式的功能&#xff1b; &#xff08;2&#xff09;可编程电压监测器&#xff08;…

【物联网】ARM核常用指令(详解):数据传送、计算、位运算、比较、跳转、内存访问、CPSR/SPSR

文章目录 指令格式&#xff08;重点&#xff09;1. 立即数2. 寄存器位移 一、数据传送指令1. MOV指令2. MVN指令3. LDR指令 二、数据计算指令1. ADD指令1. SUB指令1. MUL指令 三、位运算指令1. AND指令2. ORR指令3. EOR指令4. BIC指令 四、比较指令五、跳转指令1. B/BL指令2. l…

Nacos 的介绍和使用

1. Nacos 的介绍和安装 与 Eureka 一样&#xff0c;Nacos 也提供服务注册和服务发现的功能&#xff0c;Nacos 还支持更多元数据的管理&#xff0c; 同时具备配置管理功能&#xff0c;功能更丰富。 1.1. windows 下的安装和启动方式 下载地址&#xff1a;Release 2.2.3 (May …

【零基础到精通】小白如何自学网络安全

小白人群想学网安但是不知道从哪入手&#xff1f;一篇文章告诉你如何在4个月内吃透网安课程&#xff0c;掌握网安技术 一、基础阶段 1.了解网安相关基础知识 了解中华人民共和国网络安全法、熟知网络安全的相关概念&#xff1a;包括信息安全、风险管理、网络攻防原理、认证与…

架构规划之任务边界划分过程中承接分配

架构师在边界划分的过程中需要做什么事情呢&#xff1f;接下来&#xff0c;我们会讨论一些关于任务分配的 基础假设&#xff0c;以及由这些基础假设而带来的决策路径。 所谓任务边界划分&#xff0c;就是判定某个任务在多个承接方中&#xff0c;应该归属到哪个承接方的过程。…

如可安装部署haproxy+keeyalived高可用集群

第一步&#xff0c;环境准备 服务 IP 描述 Keepalived vip Haproxy 负载均衡 主服务器 Rip&#xff1a;192..168.244.101 Vip&#xff1a;192.168.244.100 Keepalive主节点 Keepalive作为高可用 Haproxy作为4 或7层负载均衡 Keepalived vip Haproxy 负载均衡 备用服务…

MySQL常用数据类型和表的操作

文章目录 (一)常用数据类型1.数值类2.字符串类型3.二进制类型4.日期类型 (二)表的操作1查看指定库中所有表2.创建表3.查看表结构和查看表的创建语句4.修改表5.删除表 (三)总代码 (一)常用数据类型 1.数值类 BIT([M]) 大小:bit M表示每个数的位数&#xff0c;取值范围为1~64,若…

DeepSeekMoE:迈向混合专家语言模型的终极专业化

一、结论写在前面 论文提出了MoE语言模型的DeepSeekMoE架构&#xff0c;目的是实现终极的专家专业化(expert specialization)。通过细粒度的专家分割和共享专家隔离&#xff0c;DeepSeekMoE相比主流的MoE架构实现了显著更高的专家专业化和性能。从较小的2B参数规模开始&#x…

寻迹传感器模块使用说明

产品用途&#xff1a; 1、电度表脉冲数据采样 2、传真机碎纸机纸张检测 3、障碍检测 4、黑白线检测 产品介绍: 1、采用 TCRT5000 红外反射传感器 2、检测反射距离&#xff1a;1mm~25mm 适用 3、比较器输出&#xff0c;信号干净&#xff0c;波形好&#xff0c;驱…

java项目验证码登录

1.依赖 导入hutool工具包用于创建验证码 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.2</version></dependency> 2.测试 生成一个验证码图片&#xff08;生成的图片浏览器可…

Baklib探讨如何通过内容中台提升组织敏捷性与市场竞争力

内容概要 在数字化转型的浪潮中&#xff0c;内容中台已经成为企业提升市场响应速度和竞争力的关键所在。内容中台不仅是信息处理的集结地&#xff0c;更是促进资源高效整合和灵活应用的重要平台。通过构建一个高效的内容中台架构&#xff0c;企业能够更好地应对不断变化的市场…

Java基础——分层解耦——IOC和DI入门

目录 三层架构 Controller Service Dao ​编辑 调用过程 面向接口编程 分层解耦 耦合 内聚 软件设计原则 控制反转 依赖注入 Bean对象 如何将类产生的对象交给IOC容器管理&#xff1f; 容器怎样才能提供依赖的bean对象呢&#xff1f; 三层架构 Controller 控制…

Spring中@Conditional注解详解:条件装配的终极指南

一、为什么要用条件装配&#xff1f; 在实际开发中&#xff0c;我们经常需要根据不同的运行环境、配置参数或依赖情况动态决定是否注册某个Bean。例如&#xff1a; 开发环境使用内存数据库&#xff0c;生产环境连接真实数据库 当存在某个类时才启用特定功能 根据配置文件开关…

Redis代金卷(优惠卷)秒杀案例-多应用版

Redis代金卷(优惠卷)秒杀案例-单应用版-CSDN博客 上面这种方案,在多应用时候会出现问题,原因是你通过用户ID加锁 但是在多应用情况下,会出现两个应用的用户都有机会进去 让多个JVM使用同一把锁 这样就需要使用分布式锁 每个JVM都会有一个锁监视器,多个JVM就会有多个锁监视器…

ros 发布Topic

1、确定话题名称和消息类型 自定义话题名称&#xff0c;消息类型根据发送消息需要从std_msgs中查找确定 2、在main函数中通过NodeHander发布话题 // 创建一个NodeHandle对象&#xff0c;用于与ROS系统进行交互ros::NodeHandle nh;// 创建一个Publisher对象&#xff0c;用于发…