Frida-Hook-Native层操作大全

前期准备

  • 使用 jadx 进行逆向工程的基础知识。
  • 能够理解 Java 代码。
  • 能够编写简短的 JavaScript 代码片段。
  • 熟悉 adb。
  • 已 root 的设备。
  • 对 x86/ARM64 汇编和逆向工程有基础了解。

1、Hook Native层中调用的函数并且读取传入的参数

对于Native层的函数Hook,我们使用如下模板

Interceptor.attach(targetAddress, {onEnter: function (args) {console.log('Entering ' + functionName);// Modify or log arguments if needed},onLeave: function (retval) {console.log('Leaving ' + functionName);// Modify or log return value if needed}
});
  • Interceptor.attach:将回调函数附加到指定的函数地址。targetAddress 应该是我们想要挂钩的本地函数的地址。
  • onEnter:当挂钩的函数被调用时,调用此回调。它提供对函数参数 (args) 的访问。
  • onLeave:当挂钩的函数即将退出时,调用此回调。它提供对返回值 (retval) 的访问。
    需要获取targetAddress我们可以方便的使用如下API
  1. Module.enumerateExports()
    通过调用 Module.enumerateExports(),我们可以获取到导出函数的名称、地址以及其他相关信息。这些信息对于进行函数挂钩、函数跟踪或者调用其他函数都非常有用。
  2. Module.getExportByName()
    当我们知道要查找的导出项的名称但不知道其地址时,可以使用 Module.getExportByName()。通过提供导出项的名称作为参数,这个函数会返回与该名称对应的导出项的地址。
  3. Module.findExportByName()
    这与 Module.getExportByName() 是一样的。唯一的区别在于,如果未找到导出项,Module.getExportByName() 会引发异常,而 Module.findExportByName() 如果未找到导出项则返回 null。让我们看一个示例。
  4. Module.getBaseAddress()
    通过调用 Module.getBaseAddress() 函数,我们可以获取指定模块的基址地址,然后可以基于这个基址地址进行偏移计算,以定位模块内部的特定函数、变量或者数据结构
  5. Module.enumerateImports()
    通过调用 Module.enumerateImports() 函数,我们可以获取到指定模块导入的外部函数或变量的名称、地址以及其他相关信息。

例题 Frida-Labs 0x8

MainActivity

file
可以发现,程序从EditText控件中获取到了用户的输入,然后调用了native层中的cmpstr函数进行比较。

Navtive层逻辑

file
程序在cmpstr中使用了strcmp函数,那么我们只需要拿到strcmp函数的传入参数就可以知道程序的正确输入了

Hook begin

首先我们使用Module.enumerateImports(“libfrida0x8.so”)查看导入表
file
可以发现strcmp来自于libc.so,那么我们就可以使用Module.findExportByName(“libc.so”,“strcmp”);来获取strcmp的地址了
file

获取了strcmp的地址就可以使用之前给的模板进行Hook了

function hook(){var targetAddress = Module.findExportByName("libc.so","strcmp");console.log("Strcmp Address: ",targetAddress.toString(16));Interceptor.attach(targetAddress,{onEnter:function (args){},onLeave:function(retval){}})console.log("success!");
}function main(){Java.perform(function (){hook();})
}
setImmediate(main);

但是我们需要注意的是strcmp可能不止调用一次,因此我们需要判断strcmp的第一个参数是否为0我们才进行操作,不然hook可能会一直循环输出
file
因此我们可以使用Memory.readUtf8String(args[0]);来获取我们的输入字符串,平且使用 if (input.includes(“111”))来判断

hook代码

function hook(){var targetAddress = Module.findExportByName("libc.so","strcmp");console.log("Strcmp Address: ",targetAddress.toString(16));Interceptor.attach(targetAddress,{onEnter:function (args){var input = Memory.readUtf8String(args[0]);if (input.includes("111")){console.log(Memory.readUtf8String(args[1]));}},onLeave:function(retval){}})console.log("success!");
}function main(){Java.perform(function (){hook();})
}
setImmediate(main);

file

2、Hook修改native层程序返回值

首先还是给出hook的模板如下:

Interceptor.attach(functionaddr, {onEnter: function (args) {},onLeave: function (retval) {}
});

可以看到在onLeave中有一个参数retval,这个retval,就是我们hook上的程序的返回值,我们可以使用retval.replace(val)来修改返回值。

例题 Frida-labs 0x9

MainActivity

file
可以发现程序根据native层的check_flag 方法的返回值

check_flag

file
只是简简单单的返回了一个1

hookbegin

首先使用Module.enumerateExports(“liba0x9.so”),查看导出表,看看check_flag方法的偏移地址
file
然后就可以使用模板一把梭了

hook代码
function hook(){var check_flag = Module.enumerateExports("liba0x9.so")[0]["address"];console.log("Func address = ",check_flag);Interceptor.attach(check_flag,{onEnter:function (args){},onLeave:function (retval){console.log("Origin retval : ",retval);retval.replace(1337);}})
}
function main(){Java.perform(function (){hook();})
}
setImmediate(hook);

file

3、调用native层中未被调用的方法

让我提供一个模板。

var native_adr = new NativePointer(<address_of_the_native_function>);
const native_function = new NativeFunction(native_adr, '<return type>', ['argument_data_type']);
native_function(<arguments>);

让我逐行解释。

var native_adr = new NativePointer(<address_of_the_native_function>);

要在 Frida 中调用一个本地函数,我们需要一个 NativePointer 对象。我们应该将要调用的本地函数的地址传递给 NativePointer 构造函数。接下来,我们将创建 NativeFunction 对象,它表示我们想要调用的实际本地函数。它在本地函数周围创建一个 JavaScript 包装器,允许我们从 Frida 调用该本地函数。

const native_function = new NativeFunction(native_adr, '<return type>', ['argument_data_type']);

第一个参数应该是 NativePointer 对象,第二个参数是本地函数的返回类型,第三个参数是要传递给本地函数的参数的数据类型列表。现在我们可以像在 Java 空间中那样调用该方法了。

native_function(<arguments>);

好的,我们明白了。让我们来看看例题。

例题Frida-labs 0xA

MainActivity

file
发现就是在主函数中加载了stringFromJNI

native

file
没有关于flag的信息,但是有未被调用的flag函数,我们直接使用hook调用它输出log
file

hook代码
function hook(){var a = Module.findBaseAddress("libfrida0xa.so");var b = Module.enumerateExports("libfrida0xa.so");var get_flagaddress = null;var mvaddress = null;for(var i = 0 ; b[i]!= null ; i ++ ){// console.log(b[i]["name"])if(b[i]["name"] == "_Z8get_flagii"){console.log("function get_flag : ",b[i]["address"]);console.log((b[i]["address"] - a).toString(16));//       mvaddress = b[i]["address"] - a;get_flagaddress = b[i]["address"];}}console.log(ptr.toString(16));var get_flag_ptr = new NativePointer(get_flagaddress);const get_flag = new NativeFunction(get_flag_ptr,'char',['int','int']);var flag = get_flag(1,2);console.log(flag)//console.log(b);
}function main(){Java.perform(function (){hook();})
}
setImmediate(main)

file

4、更改Native层方法的汇编指令

首先我们先看来自x86指令集的frida使用模板

var writer = new X86Writer(opcodeaddr);
Memory.protect(opcodeaddr, 0x1000, "rwx");
try {writer.flush();} finally {writer.dispose();
}

X86Writer的实例化:

  • var writer = new X86Writer(<指令的地址>);
  • 这将创建一个X86Writer类的实例,并指定我们要修改的指令的地址。这设置了写入器以操作指定的内存位置。

**插入指令 **

  • try { /* 在此处插入指令 */ }
  • try块内,我们可以插入要修改/添加的x86指令。X86Writer实例提供了各种方法来插入各种x86指令。我们可以查阅文档以了解详情。

刷新更改:

  • writer.flush();
  • 插入指令后,调用flush方法将更改应用到内存中。这确保修改后的指令被写入内存位置。

清理:

  • finally { /* 释放X86Writer以释放资源 */ writer.dispose(); }
  • finally块用于确保X86Writer资源得到适当清理。调用dispose方法释放与X86Writer实例关联的资源。

解除段只读权限
Memory.protect 。我们可以使用这个函数来修改内存区域的保护属性。Memory.protect 函数的语法如下:

Memory.protect(地址, 大小, 保护属性);
  • 地址:要更改保护的内存区域的起始地址。
  • 大小:内存区域的大小,以字节为单位。
  • 保护属性:内存区域的保护属性。

那么如何使用进行覆写呢
对于x86系统而言我们首先需要查看官方文档中的使用方法
https://frida.re/docs/javascript-api/#x86writer

file
对与arm64系统而言,我们使用如下api
https://frida.re/docs/javascript-api/#arm64writer

file
接下来让我用一个用例程序来讲一下这个指令的用法,我们示范的内容为arm64架构

例题Frida-labs 0xB

MainActivity

首先我们看到MainActivity函数内容
file
发现MainActivity就是在用户点击按钮后调用了getflag方法,但是正常点击getflag方法并不会返回flag值。

Native层内容

file
惊讶的发现MainActivity中什么都没有,显然这是不存在的。接下来我们到控制流窗口中查看。
file
查看控制流发现程序出现了永假条件跳转。导致导致ida识别不到输出flag的功能。那么我们可以把这个B.NE给Nop掉即可
首先我们需要计算B.NE的偏移地址
file
可以发现就是基地址增加15248,然后我们覆写为Nop就可以了

Hook代码
function hook(){var Base =  Module.getBaseAddress("libfrida0xb.so");console.log("Base address : ",Base);var BNE = Base.add(0x15248);Memory.protect(Base,0x1000,"rwx");var writer = new Arm64Writer(BNE);try{writer.putNop();writer.flush();console.log("Success!!");}finally {writer.dispose();}
}function main(){Java.perform(function (){hook();})
}setTimeout(main,1000);

file

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

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

相关文章

计算阶梯数 Python

题目描述 爱因斯坦曾出过这样一道有趣的数学题&#xff1a; 有一个长阶梯&#xff0c; 若每步上2阶&#xff0c;最后剩1阶&#xff1b; 若每步上3阶&#xff0c;最后剩2阶&#xff1b; 若每步上5阶&#xff0c;最后剩4阶&#xff1b; 若每步上6阶&#xff0c;最后剩5阶&#xf…

MES+APS难度地狱级,搞定它就是劫后余生呀。

一、什么是MES和APS MES&#xff08;Manufacturing Execution System&#xff09;和APS&#xff08;Advanced Planning and Scheduling&#xff09;是两种在制造业中常用的软件系统&#xff0c;用于优化生产过程和提高生产效率。 MES是一种用于管理和监控制造过程的系统。它与…

九:多播和广播

1 多播 &emsp 多播(Multicast )方式的数据传输是基于UDP完成的。 因此&#xff0c;与UDP服务器端/客户端的实现方式非常接近。 区别在于&#xff0c; UDP数据传输以单一目标进行&#xff0c;而多播数据同时传递到加入(注册)特定组的大量主机。 换言之&#xff0c;采用多播…

嵌入式驱动学习第二周——Linux休眠唤醒

前言 这篇博客来聊一聊Linux系统的休眠与唤醒。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前言1. …

Truenas入门级教程

Truenas入门教程 前言&#xff1a;系统相关配置 采用I3 4160&#xff0c;采用了2块500G的硬盘&#xff0c;内存为8G&#xff0c;两个网卡只用了其中一个&#xff0c;系统安装的是core版本 硬件采用DELL3020MT机箱&#xff0c;自带3个SATA网口&#xff0c;后期网口不够&#…

-bash: unzip: 未找到命令的解决方案

遇到 -bash: unzip: 未找到命令 这样的错误信息&#xff0c;表示你的系统中没有安装 unzip 工具。unzip 是一个常用的解压工具&#xff0c;用于解压缩 .zip 文件。你可以通过系统的包管理器安装它。 根据你使用的 Linux 发行版&#xff0c;安装 unzip 的命令会有所不同。下面是…

C# SwinV2 Stable Diffusion 提示词反推 Onnx Demo

目录 介绍 效果 模型信息 项目 代码 下载 C# SwinV2 Stable Diffusion 提示词反推 Onnx Demo 介绍 模型出处github地址&#xff1a;https://github.com/SmilingWolf/SW-CV-ModelZoo 模型下载地址&#xff1a;https://huggingface.co/SmilingWolf/wd-v1-4-swinv2-tagg…

自动化测试之web自动化(Selenium)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

飞桨AI框架安装和使用示例

飞桨AI框架安装和使用示例 飞桨PaddlePaddle是非常流行的国产AI框架&#xff0c;让我们一起来动手实践吧&#xff01; 安装 飞桨安装参考页面&#xff1a;https://www.paddlepaddle.org.cn/install/quick?docurl/documentation/docs/zh/install/pip/linux-pip.html 在这个安…

网络工程师笔记10 ( RIP / OSPF协议 )

RIP 学习路由信息的时候需要配认证 RIP规定超过15跳认定网络不可达 链路状态路由协议-OSPF 1. 产生lsa 2. 生成LSDB数据库 3. 进行spf算法&#xff0c;生成最有最短路径 4. 得出路由表

【uni-app小程序开发】实现一个背景色渐变的滑动条slider

最近做的一个用uni-app+vue2开发的微信小程序项目中要实现一个滑动进度控制条,如下图所示: 1. 滑动条需要渐变背景色 2. 滑块的背景色需要与当前位置滑动条的背景色一致(动态改变) 碰到这样的需求,我当然先是看看官方提供的slider组件和uView里的u-slider组件能不能满足…

HarmonyOS云端一体化组件之AGC应用管理

&#xff08;可选&#xff09;在AGC控制台创建同包名应用 如创建工程时&#xff0c;发现尚未在AGC控制台创建与工程包名相同的应用&#xff0c;可进行补充创建。 1.点击界面提示内的“AppGallery Connect”&#xff0c;浏览器打开AGC控制台“我的项目”页面。 2.点击选择您希…