dexposed
它基于ROOT社区著名开源项目Xposed改造剥离了ROOT部分,演化为服务于所在应用自身的AOP框架。Xposed是XDA社区用户rovo89开发并管理的一个项目,它通过修改Android Dalvik运行时的Zygote进程,使用Xposed Bridge将第三方代码注入到Android应用的方法调用中,实现非侵入式的在运行期动态修改系统和应用行为的能力。从推出到现在,它受到广大开发者和用户的欢迎,出现了数千个模块和适配不同Android ROM的安装器。dexposed 这个项目相当不错, 之前就想着怎么动态替换jvm中的代码, 一直没有思路; 现在好好学习一下。
最简单的hook
Demo1中有个test函数, 在调用hook之前正常返回”11111”; 调用hook之后, 却返回”newTestMethod”, 被我们给修改了public class Demo1 { 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); }
以上权当学习理解,用直接用淘宝封装好的工程!
https://github.com/alibaba/dexposed
本地下载: dexposed-master
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2302
- 用户1336
- 访客10968998
每日一句
Qingming Festival invites us to honor ancestors with quiet reflection and respect.
清明节邀请我们以静思与敬意祭奠祖先。
清明节邀请我们以静思与敬意祭奠祖先。
新会员