LR设置返回值检查点&打印输出执行日志

LR脚本:设置检查点与日志输出
这篇博客介绍了如何在LR(LoadRunner)脚本中使用web_reg_find函数进行内容查找,并设置检查点记录查找次数。通过示例展示了如何检查登录事务的成功与否,并根据查找次数判断登录状态,同时打印出相应的错误或成功消息。还提到了web_reg_find函数的使用位置和技巧,以及在日志中输出执行信息的方法。

LR脚本实例:

//登录事务开始

lr_start_transaction("trans_login");

//设置检查的内容,在savecount变量里面记录查找到的次数
web_reg_find("Text=欢迎您","SaveCount=loginss_count",LAST);

//登录(登录录制的自动生成代码)
web_submit_data("loginAction.do;jsessionid=16D156A310B3804B354123F7CDEE5211",
  "Action=http://****/loginAction.do;jsessionid={JSESSIONID2}",
  "Method=POST",
  ............
  LAST);

//检查登录是否成功。也可以使用:if(strcmp(lr_eval_string("{loginss_count}"),"0")==0)。strcmp、atoi都是C语言里面的函数。
if(atoi(lr_eval_string("{loginss_count}"))==0)

//打印出错误信息,同时把登录错误时的用户名、密码打印出来。也可以简单的:lr_output_message("login failed登录失败!");
   lr_error_message("login failed登录失败!username:%s,pwd:%s",lr_eval_string("{username}"),lr_eval_string("{pwd})"));
else
   lr_output_message("login successful登录成功!");

//登录事务结束

lr_end_transaction("trans_login", LR_AUTO);

网上摘录的web_reg_find用法:
web_reg_find
该函数的作用是“在缓存中查找相应的内容”,常用参数及含义如下:

web_reg_find("Search=Body", //定义查找范围

"SaveCount=ddd", //定义查找计数变量名称

"Text=aaaa", //定义查找内容

LAST);

使用该函数注意以下事项:

1、 位置

该函数写在要查找内容的请求之前,通常情况下写在如下六个函数之前:

Web_castom_request();web_image();web_link();web_submit_data();web_submit_form();web_url()

2、 使用技巧

在该函数的参数中有个“SaveCount”,该参数可以记录在缓存中查找内容出现的次数,我们可以使用该值,来判断要查找的内容是否被找到,下面举个例子来说明:(引用LR的帮助中的例子)

// Run the Web Tours sample

web_url("MercuryWebTours",

"URL=http://localhost/MercuryWebTours/",

"Resource=0",

"RecContentType=text/html",

"Referer=",

"Snapshot=t1.inf",

"Mode=HTML",

LAST);

// Set up check for successful login by looking for "Welcome"

web_reg_find("Text=Welcome",

"SaveCount=Welcome_Count",

LAST);

// Now log in

web_submit_form("login.pl",

"Snapshot=t2.inf",

..........

LAST);

// Check result

if (atoi(lr__string("{Welcome_Count}")) > 0){ //判断如果Welcome字符串出现次数大于0

lr_output_message("Log on successful."); }//在日志中输出Log on successful

else{ //如果出现次数小于等于

lr_error_message("Log on failed"); //在日志中输出Log on failed

return(0); }

<think>好的,用户现在问的是关于在Unidbg中如何hook并修改返回值。首先,我需要回顾一下之前的对话历史。用户之前询问了openat系统调用的返回值,我详细解释了返回值的情况、错误码和使用示例。现在用户的问题转向了Unidbg,这是一个用于模拟执行Android Native代码的工具,常用于逆向工程和分析。 用户的问题具体是“unidbg hook 修改返回值”,需要解释如何在Unidbg中通过hook技术来修改某个函数的返回值。首先,我需要确认用户对Unidbg和hook的基本概念是否了解,可能需要先简要介绍Unidbg及其用途,然后解释hook的概念,再具体到如何修改返回值。 接下来,需要确定用户的使用场景。可能的用户身份是逆向工程师或安全研究人员,他们可能需要在模拟执行过程中动态修改函数的返回值,以绕过某些检查或测试不同情况下的程序行为。用户的真实需求可能是希望了解具体的实现步骤,或者遇到问题需要解决方案,比如如何定位目标函数、如何编写hook代码等。 然后,我需要组织回答的结构。首先介绍Unidbg和hook的基本概念,然后分步骤说明如何实现修改返回值,包括选择hook工具(如Dynarmic或Unicorn引擎)、定位目标函数、编写回调函数、替换返回值等。同时需要提供代码示例,帮助用户更直观地理解。此外,还要提到常见错误及调试方法,以及适用场景,确保回答全面。 还需要注意用户可能的深层需求。比如,用户可能在实际操作中遇到hook失败的情况,需要知道如何排查问题,或者如何确保hook后的稳定性。因此,回答中应包括调试技巧和注意事项,比如检查函数签名、内存地址有效性、堆栈平衡等。 在技术细节方面,需要解释Unidbg中不同引擎的hook方法,比如使用Dynarmic的addHook方法,或者Unicorn引擎的hook_add函数。同时,强调修改返回值时的参数传递约定,比如ARM架构下返回值存放在R0寄存器中,x86则在EAX中,确保用户理解不同架构的区别。 最后,总结适用场景和注意事项,帮助用户正确应用该技术,避免滥用导致的问题。提供示例代码时,要确保语法正确,并注释关键步骤,便于用户理解。</think>以下是关于在 **Unidbg** 中通过 Hook 修改函数返回值的分步解析: --- ### **1. 核心原理** **Unidbg** 是一个动态二进制分析框架,用于模拟执行 Android/iOS 的 Native 代码。通过 Hook 目标函数,可以拦截其执行流程,并修改寄存器或返回值。关键点: - **Hook 时机**:在函数执行前或执行后注入自定义逻辑 - **返回值修改**:覆盖寄存器中存储的返回值(如 ARM 的 R0/x86 的 EAX) - **场景**:绕过校验、模拟特定条件、动态调试等 --- ### **2. 实现步骤** #### **步骤 1:选择 Hook 工具** 在 Unidbg 中常用两种 Hook 方式: - **Dynarmic 引擎**:通过 `addHook` 方法直接 Hook 指令地址 - **Unicorn 引擎**:使用 `hook_add` 结合回调函数 #### **步骤 2:定位目标函数** 找到需修改返回值的函数地址: - 静态分析:通过 IDA/Ghidra 反编译获取函数偏移 - 动态追踪:结合 Unidbg 的日志输出或 `console.debugger()` #### **步骤 3:编写 Hook 回调函数** 以修改返回值(ARM 32 位为例): ```java // 使用 Dynarmic 引擎示例 emulator.getBackend().addHook(new Hook() { @Override public void hook(Backend backend, long address, int size, Object user) { // 判断是否为函数返回前的指令(如 BX LR) if (isFunctionExit(backend, address)) { // 修改 R0 寄存器的值(即返回值) backend.reg_write(ArmConst.UC_ARM_REG_R0, 0x1); // 强制返回 1 } } }, startAddress, endAddress, null); // 指定 Hook 的地址范围 ``` #### **步骤 4:替换返回值** 根据架构修改对应的寄存器: | 架构 | 返回值寄存器 | 示例代码 | |-----------|--------------|-----------------------------------| | ARM 32 | R0 | `reg_write(ArmConst.UC_ARM_REG_R0, value)` | | ARM 64 | X0 | `reg_write(Arm64Const.UC_ARM64_REG_X0, value)` | | x86 | EAX | `reg_write(X86Const.UC_X86_REG_EAX, value)` | --- ### **3. 完整代码示例** ```java public class ModifyReturnValue { public static void main(String[] args) { AndroidEmulator emulator = new AndroidARMEmulator(); Memory memory = emulator.getMemory(); // 加载目标 SO 文件 Module module = memory.load(new File("target.so")); // 获取目标函数地址(假设函数偏移为 0x1234) long targetFuncAddr = module.base + 0x1234; // 添加 Hook emulator.getBackend().addHook(new Hook() { @Override public void hook(Backend backend, long address, int size, Object user) { // 判断是否在目标函数范围内 if (address >= targetFuncAddr && address < targetFuncAddr + 0x10) { // 修改返回值(例如强制返回 0xABCD) backend.reg_write(ArmConst.UC_ARM_REG_R0, 0xABCD); } } }, targetFuncAddr, targetFuncAddr + 0x10, null); // 调用目标函数 emulator.eFunc(targetFuncAddr); } } ``` --- ### **4. 常见错误与调试** | 问题现象 | 解决方法 | |---------------------------|--------------------------------------------------------------------------| | Hook 未触发 | 检查地址范围是否正确,确认引擎是否支持 Hook(如 Unicorn 需手动启用) | | 程序崩溃 | 确保修改寄存器时未破坏其他上下文(如 LR/SP),检查堆栈平衡 | | 返回值未生效 | 确认 Hook 时机是否在函数返回前,检查寄存器与架构是否匹配 | --- ### **5. 适用场景** - **绕过许可证校验**:强制让 `check_license()` 返回成功 - **模拟硬件特性**:让 `get_device_id()` 返回指定字符串 - **动态测试**:测试不同返回值对程序流程的影响 --- ### **总结** 通过 Unidbg 的 Hook 机制修改返回值,需明确目标函数地址、架构寄存器规则及 Hook 范围。实际应用中需结合动态调试确保准确性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值