Android Hook Dexposed原理小析
dexposed是阿里巴巴在xposed框架上面开发的hotpatch一套框架
当然hotpatch的方式有很多,这里先介绍下dexposed原理
Demo中有个test函数, 在调用hook之前正常返回”11111”; 调用hook之后, 却返回”newTestMethod”, 被我们给修改了
public class Demo
{
String TAG = "===[hookdemo]===";
public static String staticTest(String param1)
{
return "staticTest";
}
public String test(String param1)
{
return "11111";
}
public void demo()
{
String param1 = "param1";
Log.d(TAG, "===========before hook test:" + this.test(param1));
hook(Demo1.class, "test", "(Ljava/lang/String;)Ljava/lang/String;");
Log.d(TAG, "===========after hook test:" + this.test(param1));
Log.d(TAG, "===========before hook staticTest:" + this.staticTest(param1));
hook(Demo1.class, "staticTest", "(Ljava/lang/String;)Ljava/lang/String;");
Log.d(TAG, "===========after hook staticTest:" + this.staticTest(param1));
}
private native void hook(Class<?> clazzToHook, String methodName, String methodSig);
}
ndk 中的部分
#include <jni.h>
#include "log.h"
#include "Dalvik.h"
static void showMethodInfo(const Method* method)
{
//看看method的各个属性都是啥:
LOGD("accessFlags:%d",method->accessFlags);
LOGD("clazz->descriptor:%s",method->clazz->descriptor);
LOGD("clazz->sourceFile:%s",method->clazz->sourceFile);
LOGD("methodIndex:%d",method->methodIndex);
LOGD("name:%s",method->name);
LOGD("shorty:%s",method->shorty);
}
/**
* 使用jni GetMethodID 方法获取jmethodID 强制转为 Method 的hook 方法 示例
*/
static void newTestMethod(const u4* args, JValue* pResult,
const Method* method, struct Thread* self) {
// args 是原来函数的参数数组, 原来test函数只有一个String型参数
// 并且要注意, 如果是不是static函数, 下标0 是函数所在类的实例obj
// 在dvm中Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
// String类对应StringObject
// 取出参数打印出来看看
StringObject* param1 = NULL;
if(dvmIsStaticMethod(method))
param1 = (StringObject*)args[0];
else
param1 = (StringObject*)args[1];
LOGD("param1:%s",dvmCreateCstrFromString(param1));
//JValue 是个union ,要返回int 就 pResult->i=1; 返回Object对象就 pResult->l = ojb;
// 但是, 在dvm中的Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
// 所以, 我们这里使用dvm的函数来创建一个StringObject*
pResult->l = dvmCreateStringFromCstr("newTestMethod");
// 一般情况应该使用宏 : RETURN_XXX(result);
return;
}
extern "C" JNIEXPORT void JNICALL
Java_com_zhaoxiaodan_hookdemo_Demo1_hook(JNIEnv *env, jobject instance, jobject clazzToHook,
jstring methodName_, jstring methodSig_) {
const char *methodName = env->GetStringUTFChars(methodName_, 0);
const char *methodSig = env->GetStringUTFChars(methodSig_, 0);
jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig);
// 找不到有可能是个static
if(nullptr == methodIDToHook){
env->ExceptionClear();
methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName,methodSig);
}
if(methodIDToHook != nullptr)
{
//主要在这里替换
//jmethodID 在dvm里实际上就是个Method 结构体
Method* method = (Method*) methodIDToHook;
//看看method的各个属性都是啥:
showMethodInfo(method);
//设置Method 的 accessFlags 为 枚举型
// ACC_NATIVE 表示 这个method 切换成了一个native 方法
// 这个枚举 在 dalvik/libdex/DexFile.h
// 类似:
// ACC_PUBLIC = 0x00000001, // class, field, method, ic
// ACC_PRIVATE = 0x00000002, // field, method, ic
// ACC_PROTECTED = 0x00000004, // field, method, ic
SET_METHOD_FLAG(method, ACC_NATIVE);
//既然是一个native方法, 那就把 nativeFunc 指针指向我们的hook, 用来替换test的新方法
method->nativeFunc = &newTestMethod;
// registersSize是函数栈大小, insSize是参数占用大小
// 如果是native方法, 就没有额外开销了
// 所有开销就是参数占用, 所以把它设置成跟参数占用空间
method->registersSize=method->insSize;
//未知
method->outsSize=0;
}
env->ReleaseStringUTFChars(methodName_, methodName);
env->ReleaseStringUTFChars(methodSig_, methodSig);
}
原理就是, Method结构体表示了一个java层函数, 而其中的accessFlags属性如果是ACC_NATIVE ,
dvm在call 原java层函数的时候, 则会转向调用 属性nativeFunc 所指向的函数
所以我们把不是native的java层函数的accessFlags强制改为ACC_NATIVE, 然后把nativeFunc 指向我们的新函数,
则完成了方法的修改只不过, 这里使用native方法替换了java层的原方法
Android Hook Dexposed原理小析的更多相关文章
- Android热补丁技术—dexposed原理简析(手机淘宝采用方案)
上篇文章<Android无线开发的几种常用技术>我们介绍了几种android移动应用开发中的常用技术,其中的热补丁正在被越来越多的开发团队所使用,它涉及到dalvik虚拟机和android ...
- Android热补丁技术—dexposed原理简析(阿里Hao)
本文由嵌入式企鹅圈原创团队成员.阿里资深工程师Hao分享. 上篇文章<Android无线开发的几种常用技术>我们介绍了几种android移动应用开发中的常用技术,其中的热补丁正在被越来越多 ...
- android GC内存回收小析
由于时间问题,简单的谈谈自己的理解. 大家都知道,在android开发中,不需要自己去管理,有垃圾回收机制会自动帮我们去回收 没有被引用到的对象. 那垃圾回收机制到底是怎样的呢?下面列出本人的一些理解 ...
- Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...
- Android插件化原理解析——Hook机制之动态代理
转自 http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/ 使用代理机制进行API Hook进而达到方法增强是框架的常 ...
- Java Annotation 及几个常用开源项目注解原理简析
PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示 ...
- android MultiDex multidex原理原理下遇见的N个深坑(二)
android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multi ...
- Android Hook框架adbi的分析(3)---编译和inline Hook实践
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75200800 一.序言 在前面的博客中,已经分析过了Android Hook框架a ...
- 【转】Android Hook框架Xposed详解
1 Introduction 1.1 概述 Xposed 是 GitHUB 上 rovo89 大大设计的一个针对 Android 平台的动态劫持项目,通过替换 /system/bin/app_pro ...
随机推荐
- vim - Simple commands to remove unwanted whitespace
http://vim.wikia.com/wiki/Remove_unwanted_spaces 1. manual commandremove trailing whitespace::%s/\s\ ...
- ubuntu dpkg 依赖问题处理
ubuntu dpkg 依赖问题处理 使用 apt-get 安装软件期间,如果出现意外中断的情况,下次安装时会出现 dpkg 的一系列依赖问题,提示如下 :: dpkg: error processi ...
- SQL Nexus
在前面的SQLdiag系列中有提到SQLNexus,当时我们用SQLNexus查看了Perfmon Summary(性能计数器).ReadTrace Reports(跟踪文件)两项报表.SQLNexu ...
- Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)
一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...
- C# 遍历类的属性并取出值
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精 今天有点胡思乱想,想遍历MVC Model的属性并 ...
- resin or tomcat .war e.g. note
经常想在后台找WEB对应文件,做个记录 jar cvf step1.war . 命令将jsp(内含有html等数据局),等编译成war包目录下的文件有index.jps,eg.css -------- ...
- Log4j用法
本篇仅仅是简单介绍了在写一个测试例子时,怎么使用log4j的经验,如果用于生产环境,估计还需要在深入一步去了解更多详细的配置信息. log4j.properties 配置信息: log4j.rootL ...
- 简明python教程 --C++程序员的视角(二):函数及作用域
函数通过def关键字定义.def关键字后跟一个函数的标识符名称,然后跟一对圆括号.圆括号之中可以包括一些变量名,该行以冒号结尾.接下来是一块语句,它们是函数体. 函数的基本概念 1 位置:从左往右进行 ...
- Struts2自定义类型转换,和处理类型转换错误
Struts2自定义类型转换: 从前台接受到的类型全部是字符串,Struts2自带的一些基本类型转换有时不能满足我们的特别需要,如:日期字符串输入格式,还有一些自定义的类,直接传到后台,我们需要一些自 ...
- flexigrid扩展(添加全选,格式化表单)
1.关于flexigrid的属性这里不多说,百度一大把. 这里主要说一个参数process process参数:编写对某一列进行自定义处理的函数 function 方法名(tddiv,pid){}// ...