adbi学习:java hook实现机制
adbi的java hook实现代码ddi不在之前下载的文件中,下载地址:https://github.com/crmulliner/ddi,具体的编译看readme里面很详细的介绍了。注意ddi代码不能单独使用要跟之前的adbi相结合,因为adbi提供了注入so。本文不对代码进行详细的剖析(你可以看参考资料的文章),分析下2个问题:java如何hook;如何执行自己的java函数。
java hook:
其实在ddi的java hook和xposed的hook原理(不清楚的看我之前xposed的分析)是相同的,都是改变被hook函数的accessflag;将原本的java函数变成native函数,从而去执行自己定义的native函数;它实现的代码在dalvik_hook.c的dalvik_hook函数中。但不同于xposed是,它没有直接修改Mehtod结构的insns和nativeFunc而是调用了dvmUseJNIBridge函数来修改insns和nativeFunc。但在我看这个函数时发现其跟android源码中的dvmRegisterJNIMethod很相似:
static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
const char* signature, void* fnPtr)
{
// 解释下参数:
// clazz:类名"shy/luo/jni/ClassWithJni";
// methodName:需要注册的jni方法名 nanosleep;
// signature:方法的签名 实质是方法的参数和返回值,区别不同参数的函数
// fnPtr: jni方法函数地址 即shy_luo_jni_ClassWithJni_nanosleep函数;dalvik执行的就是这个函数,很重要哎
Method* method;
......
method = dvmFindDirectMethodByDescriptor(clazz, methodName, signature);
......
dvmUseJNIBridge(method, fnPtr);
......
}
dvmRegisterJNIMethod(关于此函数的解析,看dalvik浅析二:jni、so)函数中用dvmFindDirectMethodByDescriptor找到函数在dalvik中的Method结构,然后再dvmUseJNIBridge为Method注册native函数(在正常情况下,该Method的accessflag就是native所以无需修改)。下面来看ddi中的dalvik_hook函数实现
void* dalvik_hook(struct dexstuff_t *dex, struct dalvik_hook_t *h)
{ //dalvik_hook_t结构体中已包含函数所属的class、name、signature
......
h->method = dex->dvmFindVirtualMethodHierByDescriptor_fnPtr(target_cls, h->method_name, h->method_sig);
if (h->method == 0) {
h->method = dex->dvmFindDirectMethodByDescriptor_fnPtr(target_cls, h->method_name, h->method_sig);
}
......
//保留method的属性带以后还原
h->iss = h->method->insSize;
h->rss = h->method->registersSize;
h->oss = h->method->outsSize;
// 这里要处理
h->method->insSize = h->n_iss;
h->method->registersSize = h->n_rss;
h->method->outsSize = h->n_oss; h->method->jniArgInfo = 0x80000000; // <--- also important;这里很重要,下面要分析
......
h->access_flags = h->method->a; //保留原先函数的accessflag
h->method->a = h->method->a | h->af; // make method native
......
// bind function
dex->dvmUseJNIBridge_fnPtr(h->method, h->native_func);
......
}
显而易见,dalvik_hook按dvmRegisterJNIMethod的逻辑来编写的,所以hook其实是自己为java函数注册了一个jni方法!(熟读源码理解实现机制,你会发现很多框架和工具都是基于源码的)ok,上面的知识点大部分都是熟悉,注意蓝色代码很重要的是函数使用的dalvik寄存器个数,xposed也对其进行修正但不同的是jniArgInfo属性,xposed没对它修改,看下对jniArgInfo的描述
jniArgInfo:这个变量记录了一些预先计算好的信息,从而不需要在调用的时候再通过方法的参数和返回值实时计算了,方便了JNI的调用,提高了调用的速度。如果第一位为1(即0x80000000),则Dalvik虚拟机会忽略后面的所有信息,强制在调用时实时计算;
可以这么理解jniArgInfo相当于jni方法的cache标识符,若jniArgInfo不为0x80000000则dalvik会按之前调用过的jni方法去执行。回到xposed和ddi的区别:
xposed:在loadPackage时hook函数,而在此时绝对没有执行过函数的jni方法;
ddi:在app运行时hook函数,我们可不敢肯定此时没有执行过jni方法啊
执行自己的java函数:
在so中执行了上面的java hook后,app在调用被hook函数时就会执行我们的自定义的native函数。那我们又怎样去执行我们自己的java函数呢(难道不可以直接在native函数中实现逻辑?当然可以啊,但java开发android简单啊)?很简单,1.加载自己的dex(包含自定义java函数的文件);2.找到自定义java函数地址3.执java函数。下面对以上三步用到的知识点剖析。
const DalvikNativeMethod dvm_dalvik_system_DexFile[] = { // /dalvik/vm/native/dalvik_system_DexFile.cpp基于源码4.4
520 { "openDexFileNative", "(Ljava/lang/String;Ljava/lang/String;I)I",
521 Dalvik_dalvik_system_DexFile_openDexFileNative },
522 { "openDexFile", "([B)I",
523 Dalvik_dalvik_system_DexFile_openDexFile_bytearray },
524 { "closeDexFile", "(I)V",
525 Dalvik_dalvik_system_DexFile_closeDexFile },
526 { "defineClassNative", "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;",
527 Dalvik_dalvik_system_DexFile_defineClassNative },
528 { "getClassNameList", "(I)[Ljava/lang/String;",
529 Dalvik_dalvik_system_DexFile_getClassNameList },
530 { "isDexOptNeeded", "(Ljava/lang/String;)Z",
531 Dalvik_dalvik_system_DexFile_isDexOptNeeded },
532 { NULL, NULL, NULL },
533};
第一、二步的知识点都在上面的代码里。加载dex的知识我们在app加壳的文章中有所提及,ddi利用Dalvik_dalvik_system_DexFile_openDexFileNative直接加载目录里的dex文件。关于第二步找函数是利用Dalvik_dalvik_system_DexFile_defineClassNative来实现,具体可以看dalvik浅析三:类加载。 这里我有一点不明白的是为什么调用了Dalvik_dalvik_system_DexFile_defineClassNative还要再去调用(*env)->FindClass去得到ClassObject,明明2者都是调用dvmFindClassNoInit去实现的啊,有谁知道告诉我!第三步更简单了,得到函数的ClassObject后直接找到methodID,再调用CallVoidMethodA就可以在native执行java函数啦。
最后添幅图来理解下ddi的整个执行过程吧

当然你也可以在my_init中hook到自定义native函数2中,省去native函数1的执行。
ok,adbi的分析就到此为止啦。总结下adbi在hijack中利用ptrace在目标进程注入代码,该代码会加载so;而在so里面可以进行so和java hook:
so hook:找到native函数的指令利用Inline hook去修改它,就可以在执行native函数时去执行自定义的函数;
java hook:改变函数的accessflag去执行自己的native函数,而在native中去执行自定义的java函数
参考资料:
1 Android平台下Dalvik层hook框架ddi的研究
adbi学习:java hook实现机制的更多相关文章
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- Java学习系列(一)Java的运行机制、JDK的安装配置及常用命令详解
俗话说:“十五的月亮十六圆”.那学习是不是也是如此呢?如果把月亮看成是我们的愿望,那十五便是我们所处的“高原期”,坚持迈过这个坎,我相信你的愿望终究会现实的.记得马云曾说:今天很残酷,明天更残酷,后天 ...
- JAVA的反射机制学习笔记(二)
上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...
- java学习笔记09--反射机制
java学习笔记09--反射机制 什么是反射: 反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来 ...
- 深入浅出学习hibernate框架(三):java的反射机制
上篇博客写到了JDBC的基本操作,今天准备写一篇关于JAVA反射机制的文章,因为java的反射机制和上一篇JDBC都是Hibernate框架的基本要素.在Hibernate的运行机制中,这两块的内容正 ...
- java学习笔记13--反射机制与动态代理
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...
- Java反射学习:深入学习Java反射机制
一.Java反射的理解(反射是研究框架的基础之一) Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的 ...
- java垃圾回收机制学习总结
最近学习了一下java垃圾回收机制,将其主要内容大致总结一下: 1.什么是垃圾回收机制 java GC机制(garbage collection,垃圾收集,垃圾回收),是java特有的机制,作为jav ...
- 学习AOP之JAVA的代理机制
从一个输出日志的实例分析JAVA的代理机制 一.通用的日志输出方法 :需要在每个类里都增加对输出日志信息的代码 二.通过面向接口编程实现日志的输出(JAVA的静态代理):虽然实现了业务逻辑与输出日志 ...
随机推荐
- 怎样将大批量文件进行循环分组(reduce)?
背景 当有时候一个文件夹下有几万个几十万个文件时,我们的桌面终端打开这个文件夹可能会卡.或者将文件进行批量上传时,如果是在文件夹下全选,那么基本上浏览器就卡死了,当然也不能这样子操作滴~ 题主 ...
- docker搭建redis集群和Sentinel,实现故障转移
0.引言 公司开发需要用到redis,虽然有运维自动搭建,还是记录下如何搭建redis集群和Sentinel. 采用的是vagrant虚拟机+docker的方式进行搭建. 搭建思路: 首先是借鉴下其他 ...
- WebSocket与即时通讯
HTTP 协议有一个缺陷:通信只能由客户端发起!HTTP 协议做不到服务器主动向客户端推送信息.这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦.我们只能使用"轮 ...
- java基础:变量、常量与作用域
变量就是可以变化的量,每个变量都必须声明其类型,Java 变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域.作用域 类变量 实例变量 局部变量常量初始化后不能在改变值,不会变动的值,它 ...
- git的回滚与撤销【reset and revert】
git的工作流程-- 3个区域 工作区:我们可以看到的文件内容 在操作 git add 之前的!! 缓存区:是不可见的 已经git add操作,还没git commit -m "" ...
- SpringMVC自定义兼容性Handler
写在前面 看到这篇博客时,默认你知道Spring MVC中handler的作用,及前台请求到响应的的流转. 感谢网上其他大佬博客给我的借鉴,博客地址这里忘记了. 自定义Handler 我有时候会考虑是 ...
- 数据库遇到的问题——mysql在线修改表结构大数据表的风险与解决办法归纳
互联网应用会频繁加功能,修改需求.那么表结构也会经常修改,加字段,加索引.在线直接在生产环境的表中修改表结构,对用户使用网站是有影响. 以前我一直为这个问题头痛.当然那个时候不需要我来考虑,虽然我们没 ...
- IntelliJ IDEA安装lombok
1. 搜索Plugins 点击下方的Browse repositories.. 2.点击安装,重新启动
- sqlmap在https下的一种错误 - ssl连接失败
在昨天与师傅的交流中师傅考了我一个问题,在用sqlmap跑的时候遇到ssl爆红该怎么办,因为在实战中并没有遇到过这种情况,所以今天补一下知识. 首先查询了ssl的概念,通俗来说,如果一个网站没有安装s ...
- Java系列教程-Spring 教程目录
Spring 教程目录 可参考MyBatis的官方文档也比较清楚 https://mybatis.org/mybatis-3/zh/getting-started.html 代码 目录 https:/ ...