hook某银行加固app

分析

要在未修复dex并打包情况下对其app内在类进行hook,单纯的hook会由于加固的问题而导致加载不到内在想hook的类。因此需要进行加载加固的classloader。
在此之前需要先了解Context

在Android中,只有Application、Activity以及Service有自己的Context。
Application的Context
我们知道Application的Context是伴随着Application的创建而创建的,AMS在需要启动应用进程的时候,通过本地socket通知Zygote来fork应用进程,应用进程在启动完成之后,会通过Binder机制向AMS报告“我已经启动好了”,AMS在接收到该Binder调用之后,会立即通过Binder调用通知应用进程创建Application。
应用在创建Application的时候,首先通过ClassLoader加载对应的class文件,并通过newInstance创建一个应用的Application对象,这样就经过了Application的构造函数,同时应用进程还会实例化一个Context对象,通过Application对象的attachBaseContext方法赋值给Application,这些都做完之后,应用进程才会调用Application对象的onCreate方法。这里需要注意,Application中的context其实只是一个空壳,真正起作用的是应用进程通过attachBaseContext赋值的mBase,Application的context其实是mBase的静态代理。
Application的总结
● 继承关系:Application <- ContextWrap <- Context
● 调用顺序:构造函数 -> attachBaseContext -> onCreate
ContextWrap中包含了一个Context(mBase变量,是应用进程通过attachBaseContext赋值的),Application中关于Context的调用都是委托给它

在android的android.app.Application的源码中可以发现

Application继承ContextWrapper

attachBaseContext方法被attach调用,而大部分的壳都是在attachBaseContext这个方法里面去完成代码的解密,使用加固之后的应用的classloader会被换成其加固应用本身的。
编写
因此可以利用java.use编写脚本加载样本app的classloader

if(Java.available) {Java.perform(function(){var application = Java.use("android.app.Application");application.attach.overload('android.content.Context').implementation = function(context) {var result = this.attach(context); // 先执行原来的attach方法var classloader = context.getClassLoader();return result;}});
}

利用加载到的classloader再次对样本app的类进行hook

//框架为
if(Java.available) {Java.perform(function(){var application = Java.use("android.app.Application");application.attach.overload('android.content.Context').implementation = function(context) {var result = this.attach(context); // 先执行原来的attach方法var classloader = context.getClassLoader(); // 获取classloaderJava.classFactory.loader = classloader;var Hook_class = Java.classFactory.use("com.xxx.xxx");  // app的类console.log("Hook_class: " + Hook_class);// 下面代码和写正常的hook一样Hook_class.函数.implementation = function()  // 有参数填参数{}return result;}});
}

有一处root检测,只需要将其返回的值为false就可以了。

public class RootCheckUtil {private static final String TAG = RootCheckUtil.class.getSimpleName();public static boolean isRooted() {if (Build.MODEL.equals("Redmi Note 4")) {return false;}if (isExecuted("/system/xbin/su")) {return true;}if (isExecuted("/system/bin/su")) {return true;}if (isExecuted("/su/bin/su")) {return true;}if (isExecuted("/system/sbin/su")) {return true;}if (isExecuted("/sbin/su")) {return true;}if (isExecuted("/vendor/bin/su")) {return true;}return checkRootMethod2();}private static boolean isExecuted(String path) {boolean ret = false;try {if (new File(path).exists()) {Process exec = Runtime.getRuntime().exec("ls -l " + path + "\n");BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));while (true) {String str = br.readLine();if (str == null) {break;} else if (str.length() > 10) {String key = (String) str.subSequence(9, 10);if (key.equals("x") || key.equals(d.ap)) {ret = true;}}}exec.waitFor();br.close();}} catch (Exception e) {LoggerFactory.getTraceLogger().debug(TAG, "Exception rootcheck e");}return ret;}private static boolean checkRootMethod2() {try {return new File("/system/app/Superuser.apk").exists();} catch (Exception e) {LoggerFactory.getTraceLogger().debug(TAG, "Exception checkRootMethod e");return false;}}
}

在hook signature的过程中发现存在Context字段内存在一个Request-Data,对其产生了兴趣,代码如下

private RpcSignUtil.SignData a(String operationType, byte[] body, String ts, InnerRpcInvokeContext invokeContext, int[] signCostPtr) {StringBuffer signPlain = new StringBuffer();signPlain.append("Operation-Type=").append(operationType).append("&");signPlain.append("Request-Data=").append(Base64.encodeToString(body, 2)).append("&");signPlain.append("Ts=").append(ts);String content = signPlain.toString();if (MiscUtils.isDebugger(getRpcFactory().getContext())) {LogCatUtil.debug("RpcInvoker", "[getSignData] sign content: " + content);}boolean useSignAtlas = MiscUtils.isAlipayGW(invokeContext.gwUrl);long startTime = SystemClock.elapsedRealtime();MonitorInfoUtil.startLinkRecordPhase(operationType, WbCloudFaceContant.SIGN, null);try {return RpcSignUtil.signature(this.d.getContext(), invokeContext.appKey, isReq2Online(invokeContext), content, useSignAtlas);} finally {long signCost = SystemClock.elapsedRealtime() - startTime;signCostPtr[0] = (int) signCost;LogCatUtil.debug("RpcInvoker", "[getSignData] sign time = " + signCost + "ms. ");MonitorInfoUtil.endLinkRecordPhase(operationType, WbCloudFaceContant.SIGN, null);}}

在写hook的过程,发现其加密的发现是调用了android的原生包中的类android.util.Base64。而真正想要hook的类为

public static SignData signature(Context context, String externalAppKey, boolean isReq2Online, String content, boolean pUseSignAtlas) {try {SignRequest signRequest = new SignRequest();signRequest.appkey = MpaasPropertiesUtil.getAppkey(externalAppKey, isReq2Online, context);signRequest.content = content;if (a(context, pUseSignAtlas)) {signRequest.signType = SignRequest.SIGN_TYPE_ATLAS;}return SignData.createSignDataBySignResult(SecurityUtil.signature(signRequest));} catch (Throwable e) {LoggerFactory.getTraceLogger().warn("RpcSignUtil", e);return SignData.newEmptySignData();}}

综合上述,最终的hook脚本为

if(Java.available) {Java.perform(function(){var application = Java.use("android.app.Application");var dedata1 = Java.use("android.util.Base64");application.attach.overload('android.content.Context').implementation = function(context) {var result = this.attach(context);var classloader = context.getClassLoader();Java.classFactory.loader = classloader;var Hook_class = Java.classFactory.use("com.alipay.mobile.common.transport.utils.RpcSignUtil");var passroot = Java.classFactory.use("com.1111.common.api.util.RootCheckUtil");var requestdata = Java.classFactory.use("com.alipay.mobile.common.rpc.RpcInvoker");console.log("Hook_class: " + Hook_class);Hook_class.signature.implementation = function(context,externalAppKey,isReq2Online,dcontent,pUseSignAtlas){console.log("context:"+ context);console.log("externalAppKey:"+ externalAppKey);console.log("isReq2Online:"+ isReq2Online);console.log("content:"+ dcontent);console.log("pUseSignAtlas:"+ pUseSignAtlas);}requestdata.a.overload('java.lang.String', '[B', 'java.lang.String', 'com.alipay.mobile.common.rpc.transport.InnerRpcInvokeContext', '[I').implementation = function (operationType,body,ts,invokeContext,signCostPtr) {console.log("-------------------");console.log("-------------------");var ret = dedata1.encodeToString(body, 10);console.log("Request-Data"+ret);console.log("=========decode========");console.log(base64decode(ret));}passroot.isRooted.implementation = function (){return false;}passroot.isExecuted.implementation = function (path){return false;}passroot.checkRootMethod2.implementation = function (){return false;}return result;}function base64decode(str){var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);var c1, c2, c3, c4;var i, len, out;len = str.length;i = 0;out = "";while(i < len) {do {c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];} while(i < len && c1 == -1);if(c1 == -1)break;do {c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];} while(i < len && c2 == -1);if(c2 == -1)break;out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));do {c3 = str.charCodeAt(i++) & 0xff;if(c3 == 61)return out;c3 = base64DecodeChars[c3];} while(i < len && c3 == -1);if(c3 == -1)break;out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));do {c4 = str.charCodeAt(i++) & 0xff;if(c4 == 61)return out;c4 = base64DecodeChars[c4];} while(i < len && c4 == -1);if(c4 == -1)break;out += String.fromCharCode(((c3 & 0x03) << 6) | c4);}return out;}});}

最后进行hook的效果

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

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

相关文章

Gradle系列(3)——Gradle extension(gradle扩展),如何自定义gradle扩展,AppPlugin,AppExtension原理

文章目录 1.什么是Extensions2.如何自定义Extension3.问题来了——如何通过自定义Extension给Plugin传递数据4.BaseAppModuleExtension和AppPlugin部分原理BuildTypes是如何创建并传递数据给AppPlugin的&#xff1f;AppPlugin是如何接收数据的&#xff1f;buildTypeContainer流…

HDLbits 刷题 -- Mux256to1

Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel0 should select in[0], sel1 selects bits in[1], sel2 selects bits in[2], etc. Expected solution length: Around 1 line. 译&#xff1a; 创建一个…

CESS 受邀出席香港Web3.0标准化协会第一次理事会议,共商行业未来

2024 年 4 月 5 日&#xff0c;CESS&#xff08;Cumulus Encrypted Storage System&#xff09;作为香港 Web3.0 标准化协会的副理事会成员&#xff0c;于香港出席了 2024 年度第一次理事会会议。此次会议汇聚了来自不同领域的知名企业和专家&#xff08;参会代表名单见文末&am…

Linux——守护进程

在这篇文章中我介绍了关于tcp网络套接字&#xff0c;关于网络套接字编程的问题我会再次讲述一点东西&#xff0c;然后介绍关于守护进程的知识。 1. 关于网络套接字编程的一些问题 在进行套接字编程时我们一定是得先有套接字&#xff0c;并且我们在使用socket的一些接口时&…

MyBatis 源码分析 - 映射文件解析过程

1.简介 在上一篇文章中&#xff0c;我详细分析了 MyBatis 配置文件的解析过程。由于上一篇文章的篇幅比较大&#xff0c;加之映射文件解析过程也比较复杂的原因。所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来&#xff0c;独立成文&#xff0c;于是就有了本篇文章…

新标准日本语 课后练习

自学错误可能较多&#xff0c;听力题不需要听力的就没听录音 第二十課 スミスさんはピアノを弾くことができます 練習&#xff11;&#xff0d;&#xff11; &#xff11;張さんは日本の歌を歌うことができます 张先生会唱日本歌 &#xff12;小野さんは自転車に乗ることがで…

设计模式代码实战-模版方法模式

1、问题描述 小明喜欢品尝不同类型的咖啡&#xff0c;她发现每种咖啡的制作过程有一些相同的步骤&#xff0c;他决定设计一个简单的咖啡制作系统&#xff0c;使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型&#xff1a;美式咖啡&#xff08;American Coffee&#…

RAID 5实训

Raid 5 配置实训 实验结构&#xff1a; 实验步骤 环境准备&#xff0c;Linux操作虚拟机下添加3个及以上的磁盘用于raid 10阵列构建所用&#xff08;本次实验4个&#xff0c;一个用于备用&#xff09;创建raid 5 磁盘阵列格式化并挂载磁盘阵列存储速度检查是否提升安全性能检查…

DevExpress WinForms中文教程 - 如何通过UI测试自动化增强应用可靠性?(二)

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

C++进阶——继承

前言&#xff1a;从这篇文章开始&#xff0c;我们进入C进阶知识的分享&#xff0c;在此之前&#xff0c;我们需要先来回顾一个知识&#xff1a; C语言有三大特性&#xff0c;分别是封装、继承和多态&#xff0c;而我们前边所分享的各种容器类&#xff0c;迭代器等&#xff0c;…

数据结构----链表算法题目

1.移除链表的元素 这个题目我们有多种解决方案 &#xff08;1&#xff09;思路A&#xff1a;遍历整串数据&#xff0c;如果是我们想要删除的数据&#xff0c;就让这个数字后面的数字全部向前移动直到整传数字全部遍历完成&#xff1b;这个方法的时间复杂度是N的平方&#xff…

ARM作业day8

温湿度数据采集应用&#xff1a; 由上图可知&#xff1a; 控制温湿度采集模块的引脚是PF14&#xff08;串行时钟线&#xff09;和PF15&#xff08;串行数据线&#xff09;&#xff1a;控制温湿度采集模块的总线是AHB4&#xff0c;通过GPIOF串口和RCC使能完成初始化操作。 控制…

MAC-OS低版本升级到高版本——亲测有效

关于MAC-OS 10.13.6 升级到10.15的实战 一.MAC 欧司如何查看他的系统版本 查看信息如图 二.,去官网下载新的MAC OS 系统 官网地址&#xff1a;如何下载和安装 macOS - 官方 Apple 支持 (中国) 三.点击安装 四.具体步骤可以参考官网 在兼容的 Mac 电脑上下载并安装最新或以前…

最新版idea 合并分支方法

前言 以下是最新版的idea2024&#xff0c;如果有人找不到按键可能是因为版本不同。 操作步骤 看右小角我的分支是submit&#xff0c;现在我要将test合并到我的submit分支上 找到test分支&#xff0c;选择update&#xff0c;这一步会拉取相应分支内容等同于pull 选择merge 选…

I2C,UART,SPI(STM32、51单片机)

目录 基本理论知识&#xff1a; 并行通信/串行通信&#xff1a; 异步通信/同步通信&#xff1a; 半双工通信/全双工通信: UART串口&#xff1a; I2C串口&#xff1a; SPI串口&#xff1a; I2C在单片机中的应用&#xff1a; 软件模拟&#xff1a; 51单片机&#xff1a;…

PHP-file_get_contents(练习1)

[题目信息]&#xff1a; 题目名称题目难度PHP-file_get_contents(练习1)1 [题目考点]&#xff1a; file_get_contents() 把整个文件读入一个字符串中。 该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持&#xff0c;还会使用内存映射技术来增…

同城O2O系统开发实战:外卖送餐APP的技术架构与实现

今天&#xff0c;我们将深入探讨同城O2O系统开发实战中&#xff0c;外卖送餐APP的技术架构与实现。 一、概述 外卖送餐APP是一种典型的O2O应用&#xff0c;通过移动互联网技术&#xff0c;将用户与商家连接起来&#xff0c;实现用户在线订餐&#xff0c;商家配送服务的模式。…

Git分布式版本控制系统——在IDEA中使用Git(一)

一、在IDEA中配置Git 本质上还是使用的本地安装的Git软件&#xff0c;所以需要在IDEA中配置Git 打开IDEA的设置页面&#xff0c;按照下图操作 二、在IDEA中使用Git获取仓库 1、本地初始化仓库 2、从远程仓库克隆 方法一&#xff1a; 方法二&#xff1a; 三、.gitignore文件…

简单的网站-表白墙(前后端交互)

提交信息后&#xff0c;就得到了下面的一行话 但是存在一些问题 在一个网站中&#xff0c;服务器起到的最主要的效果&#xff0c;就是 “存储数据” 因此服务器这边往往也就需要能够提供两种风格的接口。存数据 、取数据 二、实现前后端交互 1&#xff09;先规定此处请求和响…

2024-04-11最新dubbo+zookeeper下载安装,DEMO展示

dubbozookeeper下载安装 下载zookeeper&#xff1a; 下载地址 解压&#xff0c;并进入bin目录&#xff0c;启动 如果闪退可以编辑脚本&#xff0c;在指定位置加上暂停脚本 报错内容说没有conf/zoo.cfg&#xff0c;就复制zoo_sample.cfg重命名为zoo.cfg 再次启动脚本&#x…