目录(?)[-]

  1. 继续
  2. 注入之后
    1. 示例三
    2. 输出
  3. 最后

继续

在前《一》、《二》、《三》里已经把注入的技术介绍完了,这章开始说注入之后需要做的事情。如果对注入技术已经比较熟悉了,那么可以直接看本章,否则建议先把前三章阅读一遍会比较好。

注入之后

完成了注入,那只是万里长征的第一步。
众所周知,Android的应用进程,都是由Zygote孵化的子进程,每个进程都运行在独立的JVM中。通过ptrace的注入方式,我们得到了在目标进程执行代码的机会,但距离修改JVM的内容,还差那么一点点。我们重新看一下《二》中被注入SO的关键代码:
[cpp] view plain copy
  1. void Main();
  2. static void* _main(void*){
  3. Main();
  4. return NULL;
  5. }
  6. class EntryClass {
  7. public:
  8. EntryClass() {
  9. pthread_t tid;
  10. pthread_create(&tid, NULL, _main, NULL);
  11. pthread_detach(tid);
  12. }
  13. } boy;

当so被注入后,我们的逻辑代码实际上是跑在一个Linux线程上,这样做的目的是为了不对主线程造成干扰。我们的目标是打通Java层,很自然的联想到JNI,通过JNI我们就是可以跟Java层互动了。但这里缺少了一个非常重要的元素——JNIEnv,没有这个对象,JNI就无从说起了。

示例三

我们知道,在JVM进程中,JavaVM是全局唯一的,而JNIEnv则是按线程分配。另外,Dalvik的线程跟Linux线程是一一对应的,因此我们可以把自身所在的线程Attatch到JavaVM,JavaVM就会为我们分配JNIEnv对象了。通过阅读Dalvik源码,从AndroidRuntime中我们可以得到JavaVm的地址,再通过JavaVm所提供的AttachCurrentThead和DetachCurrentThread两个函数,即可完成JNIEnv的获取,示例代码如下:
[java] view plain copy
  1. JNIEnv *jni_env = NULL;
  2. JavaVM *jvm = AndroidRuntime::getJavaVM();
  3. jvm-AttachCurrentThread(&jni_env, NULL);
  4. //TODO 使用JNIEnv
  5. jvm->DetachCurrentThread();

至此,我们就拿到了至关重要的JNIEnv对象了。接下来,我们通过DexClassLoader加载我们的dex文件,关键代码如下所示:

先找到SystemClassLoader
[cpp] view plain copy
  1. //ClassLoader.getSystemClassLoader()
  2. static jobject getSystemClassLoader(){
  3. jclass class_loader_claxx = jni_env->FindClass("java/lang/ClassLoader");
  4. snprintf(sig_buffer, 512, "()%s", JCLASS_LOADER);
  5. jmethodID getSystemClassLoader_method = jni_env->GetStaticMethodID(class_loader_claxx, "getSystemClassLoader", sig_buffer);
  6. return jni_env->CallStaticObjectMethod(class_loader_claxx, getSystemClassLoader_method);
  7. }

然后通过SystemClassLoader,生成DexClassLoader对象

[cpp] view plain copy
  1. snprintf(sig_buffer, 512, "(%s%s%s%s)V", JSTRING, JSTRING, JSTRING, JCLASS_LOADER);
  2. jmethodID dexloader_init_method = jni_env->GetMethodID(dexloader_claxx, "<init>", sig_buffer);
  3. snprintf(sig_buffer, 512, "(%s)%s", JSTRING, JCLASS);
  4. jmethodID loadClass_method = jni_env->GetMethodID(dexloader_claxx, "loadClass", sig_buffer);
  5. jobject class_loader = getSystemClassLoader();
  6. check_value(class_loader);
  7. jobject dex_loader_obj = jni_env->NewObject(dexloader_claxx, dexloader_init_method, apk_path, dex_out_path, NULL, class_loader);

最后再通过dex_loader_obj加载dex,找到自定义方法的入口,并调用

[cpp] view plain copy
  1. jstring class_name = jni_env->NewStringUTF("com.demo.inject2.EntryClass");
  2. jclass entry_class = static_cast<jclass>(jni_env->CallObjectMethod(dex_loader_obj, loadClass_method, class_name));
  3. jmethodID invoke_method = jni_env->GetStaticMethodID(entry_class, "invoke", "(I)[Ljava/lang/Object;");
  4. check_value(invoke_method);
  5. jobjectArray objectarray = (jobjectArray) jni_env->CallStaticObjectMethod(entry_class, invoke_method, 0);

至此我们的dex逻辑开始执行了。我让com.demo.inject2.EntryClass.invoke作为的入口函数,从invoke里用上《三》示例中的com.demo.inject的代码,对com.demo.host打印的数据再进行修改(同一个进程被连续注入两次,应该是比较痛苦的)。下面看看inject2中invoke的代码:

[java] view plain copy
  1. package com.demo.inject2;
  2. import java.lang.reflect.Method;
  3. import android.content.Context;
  4. import android.util.Log;
  5. /**
  6. *
  7. * @author boyliang
  8. *
  9. */
  10. public final class EntryClass {
  11. public static Object[] invoke(int i) {
  12. try {
  13. Log.i("TTT", ">>>>>>>>>>>>>I am in, I am a bad boy 2!!!!<<<<<<<<<<<<<<");
  14. Context context = ContexHunter.getContext();
  15. Class<?> MainActivity_class = context.getClassLoader().loadClass("com.demo.host.MainActivity");
  16. Method setA_method = MainActivity_class.getDeclaredMethod("setA", int.class);
  17. setA_method.invoke(null, 1);
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. return null;
  22. }
  23. }

代码跟《三》的示例非常相似,只是入口点不一样罢了。注意,这里同样有双亲委派的限制。

输出

am start com.demo.host/.MainActivity
./poison /data/local/tmp/libimportdex.so 738
看看示例三的输出
[plain] view plain copy
  1. com.demo.inject starts.
  2. I/TTT     (  738): com.demo.host starts
  3. I/TTT     (  738): 1
  4. I/TTT     (  738): 2
  5. I/TTT     (  738): 3
  6. I/TTT     (  738): 4
  7. I/TTT     (  738): 5
  8. I/TTT     (  738): >>>>>>>>>>>>>I am in, I am a bad boy!!!!<<<<<<<<<<<<<<
  9. I/TTT     (  738): 998
  10. I/TTT     (  738): 999
  11. I/TTT     (  738): 1000
  12. I/TTT     (  738): 1001
  13. I/TTT     (  738): 1002
  14. I/TTT     (  738): 1003
  15. I/TTT     (  738): >>>>>>>>>>>>>I am in, I am a bad boy 2!!!!<<<<<<<<<<<<<<
  16. I/TTT     (  738): 1
  17. I/TTT     (  738): 2
  18. I/TTT     (  738): 3
  19. I/TTT     (  738): 4
  20. I/TTT     (  738): 5
  21. I/TTT     (  738): 6
  22. I/TTT     (  738): 7

从两次的字符串输出,证明这次的注入修改已经成功了。

示例中的所有代码,都已经上传到https://github.com/boyliang/Java_Injection

最后

到目前为止,我们已经实现如下功能:

  • 注入目标进程
  • 获取JNIEnv地址;
  • 另目标进程加载Dex,并执行指定的方法;

距离我们的目标,还差一步——截获broadcastIntent方法,在《五》里我会再介绍一种叫BinderProxy的技术,通过这种技术,我们可以截获任意的BinderService的方法。

原文地址: http://blog.csdn.net/l173864930/article/details/38467497

进击的Android Hook 注入术《四》相关推荐

  1. 进击的Android Hook 注入术《二》

    目录(?)[-] 继续 注入 分类 本质 目的 过程 示例一 Host代码 libmysoso代码 调用 示例代码 继续 在<一>里,我把基本思路描述了一遍,接下为我们先从注入开始入手. ...

  2. 进击的Android Hook 注入术《三》

    目录(?)[-] 继续 Component Injection 原理 示例二 comdemohost comdemoinject 绕过ClassLoader双亲委托 输出 最后 继续 在<二&g ...

  3. 进击的Android Hook 注入术《一》

    目录(?)[-] 写在前面 短信拦截 场景 问题 解决方案 问题来了 基本思路 写在前面 这个系列本来是在公司的一个分享,内容比较多,所以就把这个PPT重新组织整理成博客,希望对大家学习有所帮助.我会 ...

  4. 进击的Android Hook 注入术《五》

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 继续 BinderProxy 原理 获取AMS引用 获取JavaBBinder 替换mObject对象 示例四 最后 继续 在A ...

  5. xposed hook java_[原创]Android Hook 系列教程(一) Xposed Hook 原理分析

    章节内容 一. Android Hook 系列教程(一) Xposed Hook 原理分析 二. Android Hook 系列教程(二) 自己写APK实现Hook Java层函数 三. Androi ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  7. linux qt getpid,[QTA] Android 动态注入原理分析

    一.前言 Android 的 UI 自动化测试可以通过注入式和非注入式分别实现,通过注入式可以更加方便地与应用进行交互.QTA 团队提供的 Android UI 自动化测试框架QT4A, 是通过动态注 ...

  8. Frida Android hook

    From:https://eternalsakura13.com/2020/07/04/frida/ 目录 1.r0ysue 大佬 2.Frida 环境 2.1 pyenv 2.2 frida 安装 ...

  9. android hook 第三方app_基于 VirtualApp 结合 whale hook框架实现hook第三方应用

    要点 1. whale hook framework 使用示例: 2. 参考项目:VirtualHook: 3. 按照 VirtualHook 修改 VirtualApp: 4. 编写 hook pl ...

最新文章

  1. nagios 使用MSN 发报警消息
  2. Fedora 18下 升级内核后VirtualBox不能正常使用的问题
  3. php socket
  4. 数据表操作(DQL)
  5. Quartz-Trigger详解
  6. 阿里面试题:如何检测并避免 Java 中的死锁?
  7. win7乱码 字符集解决方案
  8. 逻辑斯蒂回归_逻辑斯蒂回归详细解析 | 统计学习方法学习笔记 | 数据分析 | 机器学习...
  9. Java高级开发面试,Java面试没有项目经验
  10. 大数据技术对互联网的影响
  11. 电商平台环境下的图像分析在线服务产品——电商图像分析
  12. 数据结构和算法(十三)排序算法
  13. 飞机飞行原理之空气流动基本规律
  14. Python初学者必刷的五个项目,你做过几个?
  15. 黑苹果10.15.7使用
  16. 托福高频真词List13 // 附托福TPO阅读真题
  17. MindManager思维导图软件中如何下载使用行业分析模板教程分享
  18. 【USACO题库】1.5.4 Checker Challenge跳棋的挑战
  19. Luogu P2129 小Z的情书
  20. Linux 第九章-系统进程和服务管理

热门文章

  1. 重写StyleSheetTheme
  2. shell中条件判断if中的-z到-d的意思
  3. f2py支持在fortran语言中调用其他Fortran函数或C代码或Python代码
  4. WPS for Linux(ubuntu)字体缺失解决办法(转)
  5. Report20201016 benchmark vs袁颖 PANTHER初步模拟结果
  6. [MATLAB粒子模拟笔记]差分泊松方程求静电场分布
  7. VTK修炼之道6_仔细分析一个复杂程序
  8. 删除数据库中所有存储过程和函数的sql语句
  9. 【CyberSecurityLearning 37】网络安全常用Linux系统命令以及 源码包的安装过程
  10. 操作系统课设——吃水果问题