技术分享 | 专项测试技术初识Hook

news2024/12/25 12:18:33
本文节选自霍格沃兹测试学院内部教材

Hook 技术需要预先分析目标应用的源代码和逻辑,根据目标测试场景设置目标、逻辑和数据,然后运行时动态的对目标函数参数值、逻辑或者返回值做修改,达到修改现有函数逻辑、实现目标测试场景的目的。

Hook的价值

在测试中,虽然通过修改数据以实现测试场景的需求,大部分情况下都可以通过 Mock 技术实现,但是还有一小部分场景,例如需要修改应用内部函数的参数、返回值或运行逻辑等情况,这时就需要用到 Hook 技术。

单元测试之外,Mock 技术的主要作用是对服务、接口进行 Mock,通过代理等方式将被测服务发送到依赖服务的请求转发给 Mock 服务,再由 Mock 服务根据规则组装预期的返回数据响应给被测服务,达到预期的测试场景。

Hook 技术主要用于服务内部代码逻辑上的修改,当函数间传递的参数或者函数内的逻辑需要进行修改时,数据的传递并没有经过网络,Mock 服务无法对其进行操作,只能通过 Hook 技术通过在运行的代码中插入额外的代码或者在内存中进行操作。这种更精细更底层的修改,相比 Mock 技术能实现更多的修改范围,适用性更广,难度也更大。

JVM Sandbox简介

JVM-Sandbox 是 alibaba 开源的一个 JVM 沙箱容器,只能处理目标为 Java 应用的场景,主要的特点是支持热插拔(可以在目标应用运行中随时进行 Hook 的加载和解除)、可以同时操作挂载多个目标应用,相互之间独立设置互不干扰、支持的目标应用 JDK 版本较广(6-11)。工具本身功能很多,在这里仅介绍和使用它用作 Hook 的部分功能。

JVM Sandbox安装与启动

下载

  • 项目的 github 地址:https://github.com/alibaba/jvm-sandbox。
  • 下载所需版本的二进制压缩包,解压(演示所使用的版本为 1.3.3)。

环境准备

  • 官方声明支持的系统有:Linux/UNIX/MacOS,这几个系统只需要下载解压缩就可以直接运行。
  • 官方并未支持 Windows 系统,所以需要进行如下修改:
  • 安装 Git Bash。
  • 安装 JDK(版本 6-11,演示所用版本为 1.8.0_192),路径中不能带有空格。
  • 在 Shell 脚本中会有 Java 命令的调用,所以电脑中需要,并且因为 Git Bash 运行 Shell 脚本时的目录问题。
  • 修改启动脚本bin/sandbox.sh ,将脚本中 183-188 行内容注释。

启动脚本

  • 由于启动脚本中使用了相对路径,所以运行时需要切换到项目的 bin 目录下操作。
  • 在 bin 目录中执行语句./sandbox.sh -p 目标应用pid ,当出现如下提示信息,说明 JVM-Sandbox 已经成功启动了。
$ ./sandbox.sh -p 6204

                    NAMESPACE : default

                      VERSION : 1.3.3

                         MODE : ATTACH

                  SERVER_ADDR : 0.0.0.0

                  SERVER_PORT : 4543

               UNSAFE_SUPPORT : ENABLE

                 SANDBOX_HOME : e:/Download/sandbox/bin/..

            SYSTEM_MODULE_LIB : e:/Download/sandbox/bin/..\module

              USER_MODULE_LIB : E:\Download\sandbox\sandbox-module;~/.sandbox-module;

          SYSTEM_PROVIDER_LIB : e:/Download/sandbox/bin/..\provider

           EVENT_POOL_SUPPORT : DISABLE
  • JVM-Sandbox 同时还会对外提供接口,可以通过请求直接操作 JVM-Sandbox,这样就能方便的与自己的测试代码结合使用。

JVM Sandbox示例

  • 目标应用为一段简单的 Java 代码,代码中启动了一个死循环,每次循环会打印report 方法接收到的参数值,参数值已经在代码中固定传入,所以运行之后的结果是一串相同的输出内容。具体内容如下:
public class HookTarget {

    final void report(String stringParam, boolean boolParam, int intParam) {

        System.out.println("stringParam is " + stringParam);

        if (boolParam) {

            System.out.println("boolParam is true!");

        } else {

            System.out.println("boolParam is false");

        }

        System.out.println("intParam is " + intParam);

    }

    final void loopReport() throws InterruptedException {

        while (true) {

            report("a", false, 666);

            Thread.sleep(1000);

            System.out.println();

        }

    }

    public static void main(String... args) throws InterruptedException {

        new HookTarget().loopReport();

    }

}
  • 要编写符合 JVM-Sandbox 的 hook 脚本,需要引入sandbox-apisandbox-debug-module 两个依赖。
  • 通过实现 jvm.sandbox 中的 Module 接口,在 AdviceListener 方法中重写 before 方法,这样写入的语句就会在目标方法体执行之前进行执行,能够修改目标方法收到的参数数据。通过advice.changeParameter 方法,修改对应位置的参数数值,第一个参数为目标参数的位置,从 0 开始,第二个参数为替换的值。具体代码如下:
import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import org.kohsuke.MetaInfServices;
import javax.annotation.Resource;
import java.util.*;

@MetaInfServices(Module.class)
@Information(id = "ceshiren.com", author = "ceshiren.com")
public class hook_jvm implements Module {

    @Resource

    private ModuleEventWatcher moduleEventWatcher;

    @Command("ceshiren")

    public void ceshiren(final Map<String, String> param) {

        new EventWatchBuilder(moduleEventWatcher)

                .onClass("HookTarget")

                .onBehavior("report")

                .onWatch(new AdviceListener() {

                    @Override

                    protected void before(Advice advice) throws Throwable {

                        advice.changeParameter(0, "Change By Hook!");

                        advice.changeParameter(1, false);

                        advice.changeParameter(2, 965);

                    }

                });

    }

}
  • 项目通过 maven 管理依赖,对应的pom.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>

    <artifactId>ceshiren_book</artifactId>

    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <dependency>

            <groupId>com.alibaba.jvm.sandbox</groupId>

            <artifactId>sandbox-api</artifactId>

            <version>1.3.3</version>

        </dependency>

        <dependency>

            <groupId>com.alibaba.jvm.sandbox</groupId>

            <artifactId>sandbox-debug-module</artifactId>

            <version>1.3.3</version>

            <scope>compile</scope>

        </dependency>

    </dependencies>

    <build>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-assembly-plugin</artifactId>

                <executions>

                    <execution>

                        <goals>

                            <goal>attached</goal>

                        </goals>

                        <phase>package</phase>

                        <configuration>

                            <descriptorRefs>

                                <descriptorRef>jar-with-dependencies</descriptorRef>

                            </descriptorRefs>

                        </configuration>

                    </execution>

                </executions>

            </plugin>

        </plugins>

    </build>

</project>
  • 脚本编写完毕之后,将项目打成 Jar 包,放到下载的 JVM-Sandbox 项目下 sandbox-module 目录中。

  • 启动写好的 java 目标程序,运行之后命令行开始循环打印之前设置好的语句,内容如下:
stringParam is a

boolParam is false

intParam is 666

stringParam is a

boolParam is false

intParam is 666
  • 在 gitbash 命令行中打开sandbox/bin 目录,执行语句./sandbox.sh -p目标应用进程号-d 'ceshiren.com/ceshiren' ,启动 JVM-Sandbox 并对目标程序进行 Hook 操作,变更report 方法中传入的参数值,这时再回到目标程序运行的命令行中查看,可以看到命令行中输出的内容已经变更,如下:
stringParam is Change By Hook!

boolParam is false

intParam is 965

stringParam is Change By Hook!

boolParam is false

intParam is 965
  • 输出内容的变更,说明 Hook 已经生效。这样在目标程序运行中修改了方法传入的参数值,达到了 Hook 的目的。
  • 现在执行语句./sandbox.sh -p 目标应用进程号 -S 可以关闭修改,命令行中输出的内容变回了原始的输出内容。

示例简单展示了 JVM-Sandbox 用作 Hook 工具的功能,通过 Hook 功能就可以对 Java 项目的内部运行逻辑和参数、返回值进行修改。测试场景的构建、测试用例的执行都变得更加方便哦~

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汇编语言指令

文章目录算术运算指令ADDADDISUB伪指令LUILIAUIPCLA逻辑运算指令内存读写指令条件分支指令无条件跳转指令算术运算指令 ADD 语法ADD RD&#xff0c;RS1,RS2例子add x5,x6,x7x5x6x7编码格式&#xff1a;R-type opcode(7):0110011(OP) 从RS里面取出数据&#xff0c;把里面的数据…

【MyBatis框架】关联映射

关系映射1. 关联映射概述2. 环境搭建3.处理字段名和属性名不一致的情况4. 处理一对一映射5. 处理多对一映射5.1 级联方式处理5.2 使用association处理映射关系5.3 分步查询6. 处理一对多查询7. 小结1. 关联映射概述 在关系型数据库中&#xff0c;多表之间存在着三种关联关系&a…

Linux文件打包及压缩、解包及解压

目录 前言 什么是压缩&#xff1f; tar的介绍与使用 简介 打包压缩文件 打包文件&#xff08;不压缩&#xff09; gzip压缩类型压缩文件 bzip压缩类型压缩文件 xzip压缩类型压缩文件 解包解压文件 简介 解压缩&#xff08;解压到当前目录&#xff09; 解压缩&#x…

线代 | 【提神醒脑】自用笔记串联

一、初等变换 1、初等行变换与方程组的同解变换 2、初等行变换关系网 ※ 3、关联结论 —— 同解方程 4、行、列变换适用场景

Java 线程池之ThreadPoolExecutor学习总结

前提 java version "1.8.0_25" 池简述 软件开发活动中&#xff0c;我们经常会听到数据库连接池、内存池、线程池等各种“池”概念&#xff0c;这些“池”到底是什么东西呢&#xff1f;程序的世界里&#xff0c;我们可以将池简单的理解为一种容器类数据结构&#x…

哪本计算机书籍,让你有了醍醐灌顶突然开悟的感觉?

计算机书籍每年都会出版很多&#xff0c;但是能影响几代程序员的有这几本书&#xff0c;推荐一下&#xff0c;肯定让你有醍醐灌顶的开悟的感觉。 1、重构 改善既有代码的设计&#xff08;第2版 平装版&#xff09; 豆瓣评分&#xff1a;9.2 本书是一本为专业程序员编写的重构指…

30岁本科男,在测试行业干了五年还只会功能测试,难道真的要去送外卖吗?

在网上看到一个帖子 从发帖内容可以看出&#xff0c;题主是一位拥有五年功能测试经验的IT从业者&#xff0c;他也深知功能测试现在的处境艰难&#xff0c;想改变&#xff0c;却又因为年龄和经济压力的原因迟迟不敢迈出第一步&#xff0c;其实这是很多年近30岁的人事业危机的缩影…

【Java】之File类

个人主页&#xff1a;天寒雨落的博客_CSDN博客-C,CSDN竞赛,python领域博主 特别标注&#xff1a;仅为自己的学习记录笔记&#xff0c;方便复习和加深记忆&#xff0c;仅供借鉴参考&#xff01; 前篇回顾&#xff1a;【java】之File类_天寒雨落的博客-CSDN博客 目录 目录的遍历…

五 系统安全分析与设计

目录 一、安全基础技术 1.1 对称与非对称加密 1.2 数字签名&#xff08;防抵赖&#xff09; 1.3 信息摘要&#xff08;防篡改&#xff09; 1.4 加密、数字签名、信息摘要结合使用 1.5 数字证书&#xff08;防止公钥被截取篡改&#xff09; 二、网络安全 2.1 安全协议 …

Android LayerDrawable 使用

1. 前言 Android LayerDrawble 包含一个Drawable数组&#xff0c;系统将会按照这些Drawable对象的数组顺序来绘制他们&#xff0c;索引最大的 Drawable 对象将会被绘制在最上面。 LayerDrawable对象的xml文件的根元素是<layer-list>&#xff0c; 该元素内部包含多个<i…

【Linux】开发工具之gdb调试器

目录&#x1f308;前言&#x1f337;1、debug与release&#x1f338;2、gdb选项&#x1f308;前言 本篇文章进行调试器gdb的学习&#xff01;&#xff01;&#xff01; &#x1f337;1、debug与release debug会生成需要调试的信息&#xff0c;release不会生成 程序的发布方式有…

【Node.js】模块的加载机制

✍️ 作者简介: 前端新手学习中。 &#x1f482; 作者主页: 作者主页查看更多前端教学 &#x1f393; 专栏分享&#xff1a;css重难点教学 Node.js教学 从头开始学习 目录 模块的加载机制 优先从缓存中加载 内置模块的加载机制 自定义模块的加载机制 第三方模块的加载机…

2022年浙江省中职组“网络空间安全”赛项模块B--Linux系统渗透提权

2022年中职组浙江省“网络空间安全”赛项 B-3:Linux系统渗透提权一、竞赛时间 420分钟 共计7小时 吃饭一小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第①阶段: 单兵模式系统渗透测试 任务一: Windows操作系统渗透测试 任务二: Linux操作系统渗透测试 任务…

经典算法|水仙花数|自幂数

算法题目 水仙花数&#xff08;Narcissistic number&#xff09;也被称为超完全数字不变数&#xff08;pluperfect digital invariant, PPDI&#xff09;、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数&#xff08;Armstrong number&#xff09;&#xff0c;水仙花数是指一个 3 位…

高精度RC振荡器的设计

1. 一些技术指标 应用于数字模拟混合信号芯片的高频率精度&#xff0c;高频率稳定度&#xff0c;全集成RC振荡器设计 由于数字电路指标仅与复杂度有关&#xff0c;此仅考虑模拟电路的设计指标。 项目Value电源电压2.5V~5.5V工作温度-40~125目标频率Ftyp 2MHZ频率精度&#x…

常用流媒体服务器

1、Mediasoup mediasoup是相对比较新的一个WebRTC服务器端的开源项目。它更多是通过集成包方式和其他应用服务器来集成。它支持SFU模式&#xff0c;主要支持视频聊天&#xff0c;媒体流广播等。 其特点是&#xff1a; 通过底层API实现和第三方集成&#xff0c;安装简单&#…

java自学第一天

1.1.体系&#xff1a; JavaSE&#xff08;J2SE&#xff09;&#xff08;Java2 Platform Standard Edition&#xff0c;java平台标准版&#xff09; JavaEE(J2EE)(Java 2 Platform,Enterprise Edition&#xff0c;java平台企业版) JavaME(J2ME)(Java 2 Platform Micro Edition&a…

如何提高代码交付效率,完成代码交付应用自动化?

为了提高代码交付效率&#xff0c;完成代码交付应用自动化&#xff0c;CoCode旗下Co-Project V2.5.0智能项目管理平台全新发布&#xff0c;新增CI/CD功能&#xff1a;Co-DevOps。 Co-DevOps是 CoCode 全新开发出的一项CI/CD功能&#xff0c;提供持续集成、持续交付&#xff08;…

六轴工业机器人

连杆原理 符号中文名含义aaa连杆长度两个相邻关节轴之间的公垂线的长度α\alphaα连杆转角两个相邻关节间轴之间形成的角度&#xff0c;右手定则前一个轴到后一个轴ddd连杆偏距两个相邻连杆之间的距离&#xff0c;高度差θ\thetaθ关节角两个相邻杆绕公共关节轴旋转的角度 机…

TypeScript-01基础知识

目录 一、ts与es、js之间的关系 二、TypeScript与JavaScript之间的区别 三、安装TypeScript编译器 四、执行typescript的步骤 五、ts的数据类型 1、类型别名 2、接口 接口 与 类型别名 的区别 3、类型断言 4、文字类型 不常用枚举、bigint、symbol 六、类型缩小 1、…