Frida05 - 高级API用法

参考文档

https://api-caller.com/2019/03/30/frida-note/

https://frida.re/docs/javascript-api/#frida

数组打印

测试代码:

private static class Bean {String a;int b;float c;
}private void test() {Bean[] beans = new Bean[3];beans[0] = new Bean();beans[0].a = "a";beans[0].b = 1;beans[0].c = 1f;beans[1] = new Bean();beans[1].a = "b";beans[1].b = 2;beans[1].c = 2f;beans[2] = new Bean();beans[2].a = "c";beans[2].b = 2;beans[2].c = 3f;Arrays.toString(beans);
}

想要 hook Arrays.toString() 方法很简单:

function main() {Java.perform(function () {Java.use("java.util.Arrays").toString.overload('[Ljava.lang.Object;').implementation = function (x) {var result = this.toString(x);console.log("params=", x);console.log("result=", result)return result}})
}setImmediate(main)

输出的结果很多:

可以看到,输出的数组里是一个对象,那有没有什么好办法将对象转成字符串显示出来呢?

答案就是Gson,所以使用开发的思想来做逆向是很重要的。

项目里面不一定引入了Gson,所以我们需要自己编译一个gons库,放到手机里面,然后使用frida加载一下就可以使用了。

加载外部DEX

var dexPath = "/data/local/tmp/r0gson.dex";
Java.openClassFile(dexPath).load();

已经有大佬编译好了的dex,我们可以直接用:

https://github.com/r0ysue/AndroidSecurityStudy/blob/master/FRIDA/r0gson.dex.zip

为了避免类重复,还特意换了包名,具体可看:

https://bbs.kanxue.com/thread-259186.htm

重新写脚本:

function main() {Java.perform(function () {Java.use("java.util.Arrays").toString.overload('[Ljava.lang.Object;').implementation = function (x) {var result = this.toString(x);if (x.length > 0 && x[0].getClass().getName() == "com.example.demo2.MainActivity$Bean") {Java.openClassFile("/data/local/tmp/r0gson.dex").load();const gsonClass = Java.use('com.r0ysue.gson.Gson');for (var i=0; i<x.length; i++) {console.log("entry=", gsonClass.$new().toJson(x[i]));}}return result;}})
}setImmediate(main)

看下输出结果:

Spawned `com.example.demo2`. Resuming main thread!                      
[Pixel::com.example.demo2]-> entry= {"a":"a","b":1,"c":1.0}
entry= {"a":"b","b":2,"c":2.0}
entry= {"a":"c","b":2,"c":3.0}

构造数组

有时候为了替换返回值,需要一个数组类型,可以使用如下方式,构造一个数组:

const values = Java.array('int', [ 1003, 1005, 1007 ]);const JString = Java.use('java.lang.String');
const str = JString.$new(Java.array('byte', [ 0x48, 0x65, 0x69 ]));

类型转换

测试代码:

Father father = new Father();
Son son = new Son();
Father father2 = new Son();

脚本:

Java.choose('com.example.demo2.Father', {onMatch: function (instance) {console.log('found instance', instance);var son = Java.cast(instance, Java.use('com.example.demo2.Son'))console.log('cast instance', son.test());}, onComplete: function () { }})Java.choose('com.example.demo2.Son', {onMatch: function (instance) {console.log('found instance', instance);var father = Java.cast(instance, Java.use('com.example.demo2.Father'))console.log('cast instance', father.test());}, onComplete: function () { }})

输出结果:

found instance com.example.demo2.Father@daf1aad
found instance com.example.demo2.Son@c7d41e2
cast instance Son
found instance com.example.demo2.Son@2341973
cast instance Son
Error: Cast from 'com.example.demo2.Father' to 'com.example.demo2.Son' isn't possibleat cast (frida/node_modules/frida-java-bridge/lib/class-factory.js:131)at cast (frida/node_modules/frida-java-bridge/index.js:270)at onMatch (/demo2.js:20)at _chooseObjectsArtPreA12 (frida/node_modules/frida-java-bridge/lib/class-factory.js:298)at <anonymous> (frida/node_modules/frida-java-bridge/lib/class-factory.js:250)at vt (frida/node_modules/frida-java-bridge/lib/android.js:573)

符合直觉,子类可以转成父类类型,但是调用的方法还是子类的。

注册一个类

有时候,我们想做一个AOPhook的时候,就需要实现一个接口,我们可以使用 registerClass 方法来做到。

测试代码:

public interface IBook {String id();int size();boolean test(int input);}// -------------------------public class SimpleBook implements IBook {@Overridepublic String id() {return UUID.randomUUID().toString();}@Overridepublic int size() {return 100;}@Overridepublic boolean test(int input) {Log.e("SimpleBook", "input = " + input);return false;}}// -------------------------IBook book = new SimpleBook();

脚本代码:

Java.registerClass({name: 'com.example.demo2.SimpleBook2',implements: [Java.use('com.example.demo2.IBook')],fields: {proxy: 'com.example.demo2.IBook',},methods: {'<init>': [{returnType: 'void',argumentTypes: ['com.example.demo2.IBook'],implementation: function (proxy) {this.$super.$init();this.proxy.value = proxy;}}],id() {return this.proxy.value.id();},size() {return this.proxy.value.size();},test(input) {this.proxy.value.test(input);return true;},}
})Java.choose('com.example.demo2.MainActivity', {onMatch: function (instance) {console.log('found MainActivity instance', instance);var oldBook = instance.book.value;instance.book.value = Java.use('com.example.demo2.SimpleBook2').$new(oldBook);console.log('book test id = ', instance.book.value.id());console.log('book test size = ', instance.book.value.size());console.log('book test result = ', instance.book.value.test(1));}, onComplete: function () { }})

这里我们注册了一个类,com.example.demo2.SimpleBook2,并且实现了一个代理类,将 MainActivity 的字段替换之后,我们就可以让代理类来托管逻辑,做很多操作。

打印Map

与开发时的写法是一样的:

var result = "";
var keyset = map.keySet();
var it = keyset.iterator();
while(it.hasNext()){var keystr = it.next().toString();var valuestr = map.get(keystr).toString();result += valuestr;
}

Non-ASCII 方法名处理

比如说

int ֏(int x) {return x + 100;
}

甚至有一些不可视, 所以可以先编码打印出来, 再用编码后的字符串去 hook。

var methods = Java.use('com.example.demo2.MainActivity').class.getDeclaredMethods();
for (var i in methods) {console.log('origin method name -> ' + methods[i].toString());console.log('encode method name ->' + encodeURIComponent(methods[i].toString().replace(/^.*?\.([^\s\.\(\)]+)\(.*?$/, "$1")));
}Java.use('com.example.demo2.MainActivity')[decodeURIComponent("%D6%8F")].implementation = function() {console.log('method invoke');return 200;
}

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

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

相关文章

深度学习笔记_6经典预训练网络LeNet-18解决FashionMNIST数据集

1、 调用模型库&#xff0c;定义参数&#xff0c;做数据预处理 import numpy as np import torch from torchvision.datasets import FashionMNIST import torchvision.transforms as transforms from torch.utils.data import DataLoader import torch.nn.functional as F im…

二十九、获取文件属性及相关信息

二十九、获取文件属性及相关信息QFileInfo QFileInfo 提供有关文件在文件系统中的名称 位置 &#xff08;路径&#xff09;、访问权限及它是目录还是符号链接、等信息。文件的大小、最后修改/读取时间也是可用的。QFileInfo 也可以被用于获取信息有关 Qt resource . QFileInf…

算法模板之双链表图文详解

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;算法模板、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️使用数组模拟双链表讲解1.1 &#x1f514;为什么我们要使用数组去模拟双链表…

使用java调用python批处理将pdf转为图片

你可以使用Java中的ProcessBuilder来调用Python脚本&#xff0c;并将PDF转换为图片。以下是一个简单的Java代码示例&#xff0c;假设你的Python脚本名为pdf2img.py&#xff1a; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader…

Java数组(2)

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

Kotlin 笔记 -- Kotlin 语言特性的理解(二)

都是编译成字节码&#xff0c;为什么 Kotlin 能支持 Java 中没有的特性&#xff1f; kotlin 有哪些 Java 中没有的特性&#xff1a; 类型推断、可变性、可空性自动拆装箱、泛型数组高阶函数、DSL顶层函数、扩展函数、内联函数伴生对象、数据类、密封类、单例类接口代理、inter…

西蒙子S7协议介绍

西门子的S7 协议&#xff0c;没有仍何关于S7协议的官方文档&#xff0c;是一个不透明的协议。关于S7的协议介绍&#xff0c;大都是非官方的一些七零八落的文档。 1. S7的通信模型 西蒙子S7 通讯遵从着基于TCP 的 Master&#xff08;client&#xff09; & Slave&#xff0…

读取小数部分

1.题目描述 2.题目分析 //假设字符串为 char arr[] "123.4500"; 1. 找到小数点位置和末尾位置 代码如下&#xff1a; char* start strchr(arr, .);//找到小数点位置char* end start strlen(start) - 1;//找到末尾位置 如果有不知道strchr()用法的同学&#xf…

Linux 基本语句_16_Udp网络聊天室

代码&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdlib.h> #include <unistd.h> #include <string…

中小型企业网络综合实战案例分享

实验背景 某公司总部在厦门&#xff0c;北京、上海都有分部&#xff0c;网络结构如图所示&#xff1a; 一、网络连接描述&#xff1a; 厦门总部&#xff1a;内部网络使用SW1、SW2、SW3三台交换机&#xff0c;SW1为作为核心交换机&#xff0c;SW2、SW3作为接入层交换机&#x…

PDF控件Spire.PDF for .NET【转换】演示:将多个图像转换为单个 PDF

如果您想要将多个图像合并为一个文件以便于分发或存储&#xff0c;将它们转换为单个 PDF 文档是一个很好的解决方案。这一过程不仅节省空间&#xff0c;还确保所有图像都保存在一个文件中&#xff0c;方便共享或传输。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET …

-bash: docker-compose: 未找到命令

-bash: docker-compose: 未找到命令 我在使用Docker搭建Nacos容器时遇到了这个问题&#xff1a;是没有安装 docker-compose工具 。 docker-compose的用处主要体现在以下几个方面&#xff1a; 快速搭建开发环境&#xff1a;使用docker-compose可以快速搭建起开发环境&#xff0…

一分钟轻松制作AI数字人播报视频

随着人工智能的快速发展&#xff0c;AI数字人播报成为了媒体和信息传播领域的一项创新技术。AI数字人播报是利用人工智能技术创建的一系列短视频&#xff0c;以新闻主播为中心&#xff0c;展示各种场景和情境能够以短视频的形式进行新闻的报道。这种创新的内容形式在社交媒体和…

Java刷题篇——单链表练习题上

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 1. 题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例1 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例2 输入&#xff1a;head [1,2] 输出&…

Spring Boot 3 + Vue 3 整合 WebSocket (STOMP协议) 实现广播和点对点实时消息

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

高可用接入层技术演化及集群概述

集群概述 集群的介绍及优势 集群&#xff1a;将多台服务器通过硬件或软件的方式组合起来&#xff0c;完成特定的任务&#xff0c;而这些服务器对外表现为一个整体。集群的优势 高可靠性&#xff1a;利用集群管理软件&#xff0c;当主服务器故障时&#xff0c;备份服务器能够自…

2023年国赛高教杯数学建模D题圈养湖羊的空间利用率解题全过程文档及程序

2023年国赛高教杯数学建模 D题 圈养湖羊的空间利用率 原题再现 规模化的圈养养殖场通常根据牲畜的性别和生长阶段分群饲养&#xff0c;适应不同种类、不同阶段的牲畜对空间的不同要求&#xff0c;以保障牲畜安全和健康&#xff1b;与此同时&#xff0c;也要尽量减少空间闲置所…

代码随想录算法训练营第五十五天 _ 动态规划_392. 判断子序列、115.不同的子序列。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 392. 判断子序列 这个题目就是 …

消息队列kafka详解:Kafka原理分析总结

一、概述 Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统&#xff0c;后成为Apache的一部分&#xff0c;它使用Scala编写&#xff0c;以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Apache Storm、Spark等都支持与Kafka集成。 Kaf…

SGPIO介紹

什么是SGPIO&#xff1f; Serial General Purpose Input Output (SGPIO) is a method to serialize general purpose IO signals. SGPIO defines the communication between an initiator (e.g. a host bus adapter) and a target (e.g. a backplaneholding disk drives). The …