android hook 框架 xposed 如何实现注入
Android so注入-libinject2 简介、编译、运行
Android so注入-libinject2 如何实现so注入
Android so注入-Libinject 如何实现so注入
Android so注入挂钩-Adbi 框架简介、编译、运行
Android so注入挂钩-Adbi 框架如何实现so注入
Android so注入挂钩-Adbi 框架如何实现so函数挂钩
Android so注入挂钩-Adbi 框架如何实现dalvik函数挂钩
Android dalvik挂钩-Xposed框架如何实现注入
Android dalvik挂钩-Xposed框架如何实现挂钩
前面分析的adbi框架和libinject都是使用so注入的方式,实现将指定代码装入目标进程,这种方式有几个特点:
1. 是动态的,需要目标进程已经启动
2. 无法影响全局,比如注入A进程挂钩里边libc.so的open函数,此时,B进程使用的libc.so的open函数还是老函数,linux系统通过COW机制,在你注入A进程并执行对open的挂钩的时候,拷贝了新的页面,放入新的函数。如果要影响全局,应该注入到类似 Zygote 这样的进程,且应该在zygote进程启动之后马上注入,这样后续zygote进程生成子进程时就能使用挂钩后的函数
3. 需要依赖ptrace机制,某些情况下,目标进程无法被执行ptrace,则这种方式会失效
这一篇我们分析另外一种方式,是著名的xposed框架使用的方式,不需要动态注入,而是直接替换android系统的一个可执行程序。
一,android应用层进程启动最初始的几步
linux系统装载并初始化各个子系统完毕后,执行第一个应用层程序init, android 的 init 程序是自己定制的,与其它linux发行版不一样,它同样会解析并执行 init.rc 配置文件。其中,有一步如下,调用 app_process 程序启动 zygote 进程,xposed 替换的就是这个 /system/bin/app_process 程序
system/core/rootdir/init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
android\frameworks\base\cmds\app_process\app_main.cpp : main 函数
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
app_process 是native世界进入java世界的入口,它初始化了虚拟机的执行时环境,并根据不同的参数,调用 com.android.internal.os.ZygoteInit 或者 com.android.internal.os.RuntimeInit 这两个java类的main函数,如果是前者,则进入的 zygote 的世界。
Xposed\app_main.cpp : main 函数
if (zygote) {
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : "com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : "com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else { #define XPOSED_CLASS_DOTS "de.robv.android.xposed.XposedBridge"
与标准流程不一样的地方,如果检测到android版本支持xposed且已经安装了Xposed,则 runtime.start 启动的是 de.robv.android.xposed.XposedBridge 的main函数,进入了 xposed 的世界
xposedbridge.java
private static void main(String[] args) {
// the class the VM has been created for or null for the Zygote process
String startClassName = getStartClassName(); // initialize the Xposed framework and modules
try {
// initialize log file
try {
logFile = new File(BASE_DIR + "log/error.log");
if (startClassName == null && logFile.length() > MAX_LOGFILE_SIZE_SOFT)
logFile.renameTo(new File(BASE_DIR + "log/error.log.old"));
logWriter = new PrintWriter(new FileWriter(logFile, true));
logFile.setReadable(true, false);
logFile.setWritable(true, false);
} catch (IOException ignored) {} String date = DateFormat.getDateTimeInstance().format(new Date());
determineXposedVersion();
log("-----------------\n" + date + " UTC\n"
+ "Loading Xposed v" + XPOSED_BRIDGE_VERSION
+ " (for " + (startClassName == null ? "Zygote" : startClassName) + ")...");
if (startClassName == null) {
// Zygote
log("Running ROM '" + Build.DISPLAY + "' with fingerprint '" + Build.FINGERPRINT + "'");
} if (initNative()) {
if (startClassName == null) {
// Initializations for Zygote
initXbridgeZygote();
} loadModules(startClassName);
} else {
log("Errors during native Xposed initialization");
}
} catch (Throwable t) {
log("Errors during Xposed initialization");
log(t);
disableHooks = true;
} // call the original startup code
if (startClassName == null)
ZygoteInit.main(args);
else
RuntimeInit.main(args);
}
xposedbridge 类先初始化xposed需要的环境,然后加载注册到xposed框架里的 xposed 模块,这一步执行完后,所以 xposed 对虚拟机的挂钩已经完成,mian 函数最后,执行 ZygoteInit.main 或者 RuntimeInit.main , 进入正常的流程
从这里可以看出,xposed 对虚拟机的注入采用的是比动态注入更优雅的方式,有几个特点:
1. 由于替换了 app_process ,替换后的app_process 肯定是先启动 xposed 然后再进入 zygote ,而其他app都是 zygote 创建的,这样xposed 的挂钩一定的全局性的,所有app都会被影响
2. 只需要安装xposed时拥有root权限以替换系统的 app_process , 之后不再需要root权限,而前面采用 so动态注入的方式,每次要挂钩都需要注入,每次注入zygote 都需要root权限
3. 不需要依赖 ptrace 等机制
android hook 框架 xposed 如何实现注入的更多相关文章
- android hook 框架 xposed 如何实现挂钩
Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2 如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...
- 【转】Android Hook框架Xposed详解
1 Introduction 1.1 概述 Xposed 是 GitHUB 上 rovo89 大大设计的一个针对 Android 平台的动态劫持项目,通过替换 /system/bin/app_pro ...
- Android Hook框架Xposed详解
1 Introduction 1.1 概述 Xposed 是 GitHUB 上 rovo89 大大设计的一个针对 Android 平台的动态劫持项目,通过替换 /system/bin/app_pro ...
- [转载] Android.Hook框架xposed开发篇
本文转载自: http://www.52pojie.cn/thread-396793-1-1.html 原帖:http://drops.wooyun.org/tips/7488 作者:瘦蛟舞 官方教程 ...
- android hook 框架 libinject2 如何实现so注入
Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2 如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...
- android hook 框架 libinject 如何实现so注入
前面两篇 android hook 框架 libinject2 简介.编译.运行 android hook 框架 libinject2 如何实现so注入 实际运行并分析了 Android中的so注入( ...
- Android Hook框架adbi的分析(1)---注入工具hijack
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/74055505 一.Android Hook框架adbi的基本介绍 adbi是And ...
- android hook 框架 ADBI 如何实现dalvik函数挂钩
Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2 如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...
- android hook 框架 libinject2 简介、编译、运行
Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2 如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...
随机推荐
- C语言进阶——关于07中指针的补充
首先我们应该了解指针可以分为: 野指针: 野指针不是NULL指针,是未初始化或未清零的指针,他指向的内存地址不是程序员想要的.人们一般不会错用NULL指针,因为用if语句很容易判断.但是“野指针”是很 ...
- HyperLedger Fabric 1.4 比特币历史(1.1)
比特币是一种数字货币,也是一种创新思维,把人们带入到一个无中心化.完全可信任.安全可靠的全新思维领域:一个叫“中本聪”的人或组织,使我们思维产生化学反应,他在2008年10月31日发表了比特币白皮书& ...
- Black Box POJ1442
Description Our Black Box represents a primitive database. It can save an integer array and has a sp ...
- Eclipse 修改字符集---Eclipse教程第02课
默认情况下 Eclipse 字符集为 GBK,但现在很多项目采用的是 UTF-8,这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8, 设置步骤如下: 在菜单栏选择 Window ...
- laravel5.5事件广播系统
目录 1. 定义广播事件 1.1 广播名称 1.2 广播数据 1.3 广播队列 1.4 广播条件 2. 频道授权 2.1 定义授权路由 2.2 定义授权回调 3. 对事件进行广播 3.1 可以使用ev ...
- elasticsearch索引和映射
目录 1. elasticsearch如何实现搜索 1.1 搜索实例 1.2 es中数据的类型 1.3 倒排索引 1.4 分析与分析器 1.4.1 什么是分析器 1.4.2 内置分析器种类 1.4.3 ...
- ScrollView中ViewPager无法正常滑动问题
本文主要介绍如何解决ViewPager在ScrollView中滑动经常失效.无法正常滑动问题. 解决方法只需要在接近水平滚动时ScrollView不处理事件而交由其子View(即这里的ViewPage ...
- MD5--3D模型
在学习Away3D的过程中,接触到MD5模型和MD5动画这样两个词.之前对MD5的认识就是一种加密技术,怎么它又和动画扯上关系了呢. 一阵谷歌之后,终于在这个地方发现了关于3D方面的MD5介绍了:ht ...
- USACO Section2.2 Preface Numbering 解题报告 【icedream61】
preface解题报告----------------------------------------------------------------------------------------- ...
- (转\整)UE4游戏优化 多人大地型游戏的优化(四)内存的优化
施主分享随缘,评论随心,@author:白袍小道,当苦无妨 小道暗语: 1.因为小道这里博客目录没自己整,暂时就用随笔目录结构,所以二级目录那啥就忽略了.标题格式大致都是(原or转) 二级目录 (标题 ...