技术分享 | Frida 实现 Hook 功能的强大能力

Frida 通过 C 语言将 QuickJS 注入到目标进程中,获取完整的内存操作权限,达到在程序运行时实时地插入额外代码和数据的目的。官方将调用代码封装为 python 库,当然你也可以直接通过其他的语言调用 Frida 中的 C 语言代码进行操作。

Frida安装和启动

电脑端 Frida 安装

  • Frida 支持 python2 和 python3 版本,演示所使用的版本为 python3.8
pip install frida-tools
  • 如果在安装中卡住,需要在 Frida 的 pypi 页面下载对应系统的 egg 文件,对应页面地址为:pypi.org/project/fri… ,并将该文件放置到个人文件夹路径下,例如 C:\Users\当前用户名 ,再重新使用命令安装。
  • 安装完毕后可以通过命令frida --version 来查看安装的版本,确认是否安装成功。

手机端 Frida-server 安装

  • 本次示例使用 Android App 作为目标程序,所以需要电脑端安装 SDK 环境,以便能够连接手机进行调试操作,还需在手机端准备一个 Frida-server,下载地址为:github.com/frida/frida… CPU 架构和本地 Frida 版本的包。
  • 下载之后解压文件,使用adb push 命令将文件推送到手机端,建议放置在/data/local/tmp 文件夹中,并修改该文件的权限为 755,以便之后进行启动。

确认环境运行正常

  • 通过 Frida 提供的一些小工具,对 Frida 的安装运行环境做简单的确认。
  • 首先准备一个 Android 模拟器或者真机,将上一步中提到的 Frida-server 推送到手机端中,在本示例中将放置在手机的/data/local/tmp 文件夹内,并将文件命名为frida-server
  • 通过adb shell 命令连接手机,运行/data/local/tmp/frida-server & ,将 Frida-server 放在系统后台自动运行。
  • 在本地电脑终端中运行frida-ps -U ,结果如下展示手机中的进程信息,说明环境已经准备完毕。
  PID  Name
-----  --------------------------------------------------

 1313  adbd

12621  android.process.acore

18037  android.process.media

14455  com.android.defcontainer

11656  com.android.deskclock

...

示例

目标应用介绍

  • 因为 Hook 需要通过分析源码中的逻辑来实现,所以先展示一下目标应用的源码部分,方便分析其中的逻辑,找到 Hook 时要修改的方法和变量。
  • 代码是简单的猜黑白游戏,通过按下黑或白按钮,与电脑结果进行对比,结果相同加 1 分,结果不同分数清零,当满 100 分时打出胜利提示语。具体代码如下:
package com.example.target_frida;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    TextView winCountView;

    TextView battleInfoTextView;

    int winCount = 0;

    @SuppressLint("SetTextI18n")

    @Override

    public void onClick(View view) {

        if (winCount > 100) {

            return;

        }

        if (view.getId() == R.id.tvButtonBlack) {

            if (!getCPUResult()) {

                winCount++;

                winCountView.setText(winCount + "");

                battleInfoTextView.setText("Right!");

            } else {

                winCount = 0;

                winCountView.setText(winCount + "");

                battleInfoTextView.setText("Wrong! Clean All!");

            }

        } else if (view.getId() == R.id.tvButtonWhite) {

            if (getCPUResult()) {

                winCount++;

                winCountView.setText(winCount + "");

                battleInfoTextView.setText("Right!");

            } else {

                winCount = 0;

                winCountView.setText(winCount + "");

                battleInfoTextView.setText("Wrong! Clean All!");

            }

        }

        if (winCount >= 100) {

            battleInfoTextView.setText("Win 100 times!!!");

        }

    }

    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        winCountView = findViewById(R.id.winCount);

        winCountView.setText(winCount + "");

        battleInfoTextView = findViewById(R.id.battleInfo);

        battleInfoTextView.setText("猜黑白!!!");

        Button buttonBlack = (Button) findViewById(R.id.tvButtonBlack);

        Button buttonWhite = (Button) findViewById(R.id.tvButtonWhite);

        buttonBlack.setOnClickListener(this);

        buttonWhite.setOnClickListener(this);

    }

    public boolean getCPUResult() {

        //true为白,false为黑

        return Math.random() > 0.5;

    }
}

Hook 需求分析

  • 由于正常情况下,连赢 100 次的概率几乎为零,如果想要达到胜利条件,Hook 就是一个比较好的方式。
  • 首先分析一下源码,想要达到连赢 100 次的情况,可以有两种解决办法:一种是通过修改用来记录连赢次数的变量winCount ,将连赢记录改成 99,这样只需要再赢一次就可以获得胜利;还有一种是通过修改getCPUResult 方法的返回值,让其固定返回一种可能性,这样只需要选择对应的颜色就可以连续获胜。接下来通过实现第一个方案,看看使用 Frida 如何达到想要的效果。

第一种实现:修改结果变量中保存的值

  • 首先展示修改代码,然后再进行逐步讲解:
import time

import frida, sys

date_str = time.strftime('%m-%d %H:%M:%S')

def on_message(message, data):

    if message['type'] == 'send':

        print(f"[{date_str}] {message['payload']}")

    else:

        print(f"[{date_str}] {message}")

def run_all():

  # Java.perform方法:当 js 附加到目标的进程中时被执行,运行其中定义的函数

  # Java.choose方法:通过完整类名,获取它的实例,从而对实例中的数据进行修改

  # 通过 key:value 结构定义了两个函数:

  # onMatch 对应的函数在命中一个实例的时候被调用,传入函数中的参数 instance 就是被命中的实例

  # onComplete 函数会在所有实例遍历完毕之后被调用,可以做一些后续处理操作

    jscode = """

    Java.perform(function () {

      Java.choose("com.example.target_frida.MainActivity",{

        onMatch:function(instance){

            console.log("winCount value is "+instance.winCount.value);

            instance.winCount.value=99;

            console.log("winCount value is "+instance.winCount.value);

        },

        onComplete:function(){

            console.log("Complete!!!")

        }

      });

    });

    """

    # attach目标App进程

    target_app = 'com.example.target_frida'

    process = frida.get_usb_device().attach(target_app)

    # 将JS代码注入进程,并附加监听方法,用来获取返回的日志信息

    script = process.create_script(jscode)

    script.on('message', on_message)

    # 打印起始日志

    print(f'[{date_str}] Start Frida on {target_app}')

    # 加载注入的JS代码逻辑

    script.load()

    # 使用系统输入语句阻止函数运行完毕自动退出

    sys.stdin.read()

if __name__ == '__main__':

    run_all()
  • 代码中的 python 语句已经添加了注释,Hook 的核心逻辑,JS 语句作为字符串保存在 jscode 变量中。
  • 梳理一下整个 JS 语句的流程:通过Java.choose 函数获取com.example.target_frida.MainActivity 类的实例。在获取到实例时,首先使用console.log 语句将当前实例中的 winCount 变量值(使用 winCount.value)打印到日志中,之后直接通过赋值语句把变量值改为 99,再次输出日志确认修改无误,修改逻辑就完成了。
  • 在手机端启动 Frida-server 和被测 App,电脑端运行脚本,可以看到在命令行中输出如下内容:
[04-15 18:19:57] Start Frida on com.example.target_frida

winCount value is 0

winCount value is 99

Complete!!!
  • 这时在 App 中选择一个颜色点击,只要选中正确的颜色,就可以成功达到预期的 100 次连胜目标,如果没能选中正确的颜色导致清零,可以再重复运行脚本修改一次数值,在这种情况下要达到预期的场景就很容易。

总结

第二个方案以及其他更多的可能性,就留给读者自行探索,在这里送上 Frida 官方 JavaScript API 链接:frida.re/docs/javasc… ,可以通过这个链接找到你所需要的 JS 函数。

通过示例可以看到 Frida 实现 Hook 功能的强大能力,它可以定位到类的实例,并且对实例中的数据进行直接的修改,达到场景构建的目的。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI生图王者之战!深度体验实测,谁是真正的艺术家?

10月11日凌晨,设计软件巨头Adobe宣布推出一系列图像生成模型,其中Firefly Image 2作为新一代图像生成器,通过改善皮肤、头发、眼睛、手和身体结构增强了人体渲染质量,提供更好的色彩和改进的动态范围,并为用户提供更大…

1100*C. Division by Two and Permutation(全排列数学)

Problem - 1624C - Codeforces 解析&#xff1a; 贪心&#xff0c;将每个数除到第一个没有出现的数字就停止。 #include<bits/stdc.h> using namespace std; #define int long long const int N2e55; int n,x,f[N]; void solve(){scanf("%lld",&n);memset…

服务器感染了.locked勒索病毒,如何确保数据文件完整恢复?

引言&#xff1a; 网络安全威胁的不断演变使得恶意软件如.locked勒索病毒成为当今数字时代的一大挑战。.locked勒索病毒能够加密您的文件&#xff0c;然后要求支付赎金以解锁它们。本文将深入探讨.locked勒索病毒的特点&#xff0c;以及如何应对感染&#xff0c;以及预防这种类…

【Java 进阶篇】Cookie 使用详解

欢迎阅读本篇博客&#xff0c;我们将深入研究 Java 中的 Cookie&#xff0c;从入门到精通&#xff0c;包括 Cookie 的基本概念、原理、使用方法以及一些高级技巧。无论你是新手还是有经验的开发者&#xff0c;希望这篇博客对你有所帮助。 第一部分&#xff1a;Cookie 是什么&a…

Docker安装教程

Docker安装教程 安装教程Centos7.6docker镜像源修改docker目录修改 Ubuntu20.04docker镜像源修改docker数据目录修改 安装教程 Centos7.6 &#x1f680;docker支持的Cetnos操作系统版本 CentOS 7 CentOS 8 (stream) CentOS 9 (stream) &#x1f680;支持的CPU ARM/X86_64 查看…

Gin学习笔记

Gin学习笔记 Gin文档&#xff1a;https://pkg.go.dev/github.com/gin-gonic/gin 1、快速入门 1.1、安装Gin go get -u github.com/gin-gonic/gin1.2、main.go package mainimport ("github.com/gin-gonic/gin""net/http" )func main() {// 创建路由引…

.NET Framework中自带的泛型委托Action

Action<>是.NET Framework中自带的泛型委托&#xff0c;可以接收一个或多个输入参数&#xff0c;但不返回任何参数&#xff0c;可传递至多16种不同类型的参数类型。在Linq的一些方法上使用的比较多。 1、Action泛型委托 .NET Framework为我们提供了多达16个参数的Action…

【网络安全 --- web服务器解析漏洞】IIS,Apache,Nginx中间件常见解析漏洞

一&#xff0c;工具及环境准备 以下都是超详细保姆级安装教程&#xff0c;缺什么安装什么即可&#xff08;提供镜像工具资源&#xff09; 1-1 VMware 16.0 安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读20…

【Linux】第十二站:进程

文章目录 1.windows和linux中的进程2.先描述3.在组织4.具体的Linux系统是如何做的&#xff1f;1.基本概念2.描述进程-PCB3.task_struct和PCB的关系4.task_struct内容分类5.linux具体如何做的&#xff1f;6.查看进程 1.windows和linux中的进程 一个已经加载到内存的程序&#xf…

洛谷P1102 A-B数对 详细解析及AC代码

P1102 A-B数对 前言题目题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题目分析注意事项 代码经典二分&#xff08;O(nlgn)&#xff09;酷炫哈希&#xff08;O(n)&#xff09; 后话额外测试用例样例输入 #2样例输出 #2 王婆卖瓜 题目来源 前言 酷&…

生成式人工智能的“经济学”,The Economic Case for Generative AI#a16z

a16z召集了行业精英&#xff0c;为我们带来了有关生成式AI的洞察。在创造力方面&#xff0c;生成式AI带来了3-4倍量级的成本优势&#xff0c;更多新的需求将诞生。 AI REVOLUTION The Economic Case for Generative AI Martin Casado MixCopilot 大家好&#xff0c;欢迎来到本期…

遇到python程序是通过sh文件启动的,如何调试

说明 下载的源码总会遇到这样启动的&#xff1a; 并且发现shell文件内容很多&#xff0c;比较复杂&#xff0c;比如&#xff1a; 解决方案 这时候想要调试&#xff0c;可以通过端口连接的方式调试&#xff0c;具体方法如下&#xff1a; 在vscode调试按钮中添加远程附加调试…

【kubernetes】pod的生命周期

文章目录 1、概述2、pod的生命期3、pod阶段4、容器状态5、容器重启策略6、pod状况6.1 Pod就绪态6.2 Pod就绪态的状态6.3 Pod网络就绪 7、容器探针7.1 检查机制7.2 探测结果7.3 探测类型 8、Pod的终止8.1 强制终止Pod8.2 Pod的垃圾收集 1、概述 pod遵循预定义的生命周期&#x…

【MogDB/openGauss误删未归档的xlog日志如何解决】

在使用MogDB/openGauss数据库的过程中&#xff0c;有时候大量业务&#xff0c;或者导数据会导致pg_xlog下的日志数量持续增长&#xff0c;此时如果xlog的产生频率太快&#xff0c;而来不及自动清理&#xff0c;极有可能造成pg_xlog目录的打满。如果对数据库的xlog不太了解的时候…

解决Java中https请求接口报错问题

1. 解决SSLException: Certificate for &#xff1c;域名&#xff1e; doesn‘t match any of the subject alternative报错问题 1.1 问题描述 最近在做一个智能问答客服项目&#xff0c;对接的是云问接口&#xff0c;然后云问接口对接使用的是https方式&#xff0c;之前一直…

git push超过100MB大文件失败(remote: fatal: pack exceeds maximum allowed size)

push代码的时候&#xff0c;有时会出现如下问题 remote: fatal: pack exceeds maximum allowed size error: failed to push some refs to ‘git.n.xiaomi.com:fuzheng1/nl2sql.git’ 解决方案&#xff1a; 将本地 http.postBuffer 数值调整到GitHub服务对应的单次上传大小配置…

凭什么不让使用外键!?

△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 434 篇原创分享 作者 l Hollis 来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09; MySQL 外键&#xff08;Foreign Key&#xff09;是用于建立表之间关系的&#xff0c;它定义了一个表中的一列或一组…

IDEA JAVA项目 导入JAR包,打JAR包 和 JAVA运行JAR命令提示没有主清单属性

一、导入JAR包 1、java项目在没有导入该jar包之前&#xff0c;如图&#xff1a;2、点击 File -> Project Structure&#xff08;快捷键 Ctrl Alt Shift s&#xff09;&#xff0c;点击Project Structure界面左侧的“Modules”如图&#xff1a;3.在 “Dependencies” 标签…

Javaweb之javascript的详细解析

JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;我们需要给他注入灵魂&#xff0c;所以接下来我们需要学习JavaScript&#xff0c;这门语言会让我们的页面能够和用户进行交互。 1.1 介绍 通过代码/js效果演示提供资料进行效果演示&…

使用Kotlin与Unirest库抓取音频文件的技术实践

目录 摘要 一、Kotlin与Unirest库概述 二、使用Kotlin和Unirest抓取音频文件 1、添加Unirest依赖 2、发送HTTP请求获取音频文件 3、保存音频文件 三、完整代码示例 四、注意事项 结论 摘要 本文详细阐述了如何使用Kotlin编程语言与Unirest库抓取网络上的音频文件。首…