转:http://www.cnblogs.com/jiayy/p/4305018.html

前面分析的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-serverclassmain

socket zygote stream660root 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 voidmain(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(newDate());

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);elseRuntimeInit.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 等机制

注:经过实测,zygote,system_server,app的所有的进程的maps都包含有XposedBridge.jar及模块,如下:

root@lte26007:/ # cat /proc/9098/maps | grep xpose

cat /proc/9098/maps | grep xpose

5a50b000-5a50c000 r--s 00016000 b3:14 219257 /data/data/de.robv.android.xpos

ed.installer/bin/XposedBridge.jar

5b767000-5b788000 r--p 00000000 b3:14 56966 /data/dalvik-cache/data@data@de

.robv.android.xposed.installer@bin@XposedBridge.jar@classes.dex

5b788000-5b789000 r--p 00021000 b3:14 56966 /data/dalvik-cache/data@data@de

.robv.android.xposed.installer@bin@XposedBridge.jar@classes.dex

5b789000-5b78a000 r--p 00022000 b3:14 56966 /data/dalvik-cache/data@data@de

.robv.android.xposed.installer@bin@XposedBridge.jar@classes.dex

5b78a000-5b78c000 r--p 00023000 b3:14 56966 /data/dalvik-cache/data@data@de

.robv.android.xposed.installer@bin@XposedBridge.jar@classes.dex

5b78c000-5b7a6000 r--p 00025000 b3:14 56966 /data/dalvik-cache/data@data@de

.robv.android.xposed.installer@bin@XposedBridge.jar@classes.dex

root@lte26007:/ # cat /proc/9098/maps | grep dis

cat /proc/9098/maps | grep dis

5bd5b000-5bd5c000 r--s 00045000 b3:14 394 /data/app/com.disable.verifysig

nature-1.apk

5bd69000-5bdb2000 r--p 00000000 b3:14 56988 /data/dalvik-cache/data@app@com

.disable.verifysignature-1.apk@classes.dex

5bdb2000-5bdb3000 r--p 00049000 b3:14 56988 /data/dalvik-cache/data@app@com

.disable.verifysignature-1.apk@classes.dex

5bdb3000-5be1d000 r--p 0004a000 b3:14 56988 /data/dalvik-cache/data@app@com

.disable.verifysignature-1.apk@classes.dex

root@lte26007:/

Android应用防xposed注入,android hook 框架 xposed 如何实现注入相关推荐

  1. Android Hook框架Xposed进阶

    上一篇<Android Hook框架Xposed入门>,我们对xposed进行简单的介绍并hook自己写的登录app.这次我们对xposed进行深入的了解并hook系统应用和第三方应用. ...

  2. Android平台dalvik模式下java Hook框架ddi的分析(2)--dex文件的注入和调用

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/77942585 前面的博客<Android平台dalvik模式下java Ho ...

  3. 面试:Hook框架Xposed、Dexposed、Epic原理

    Xposed.Dexposed.Epic对比总结: 1.Xposed框架是需要root的,他的功能很全,能够hook掉系统方法,同时也可以hook掉其他应用的一些方法. 2.Dexposed框架是不需 ...

  4. Android.Hook框架xposed篇(Http流量监控)

    瘦蛟舞 · 2015/08/03 10:30 官方教程:github.com/rovo89/Xpos- 官网:repo.xposed.info/module/de.r- apk:dl-xda.xpos ...

  5. Android 关于模拟点击和Hook框架的杂谈

    1. 背景 就跟我们以前玩页游挂机一样,Android端也有游戏,而且样式繁多,如果重复的操作每次都要自己重复一遍操作,那不得烦死,所以就有了这篇文章,本文仅探讨方案,大家可以尝试.而且现在的模拟器( ...

  6. Android平台dalvik模式下java Hook框架ddi的分析(1)

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75710411 一.前 言 在前面的博客中已经学习了作者crmulliner编写的, ...

  7. 安卓逆向_22( 一 ) --- Xposed【 Android Studio + Xposed 实现简单的 hook 】

    From:使用渗透测试框架 Xposed 框架 hook 调试 Android APP:https://www.freebuf.com/articles/terminal/56453.html Xpo ...

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

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

  9. Android中的hook框架:epic简介

    epic是Android中的一个开源的hook框架,目前最新版本是:0.11.2,项目地址:https://github.com/tiann/epic. epic框架的优点有: 1.可以hook普通方 ...

最新文章

  1. js转Java的list_JS之JSON字符串到后台用Java转换成List实体类
  2. Vue_VueResource
  3. 关于$'\r': command not found错误的一点体会
  4. Python基础——pickle(保存与提取数据)
  5. 解决TortoiseGit文件夹和文件状态图标不显示问题
  6. php 深入,深入PHP解耦的三重境界(浅谈服务容器)
  7. 分析APP的安装流程 API29
  8. Web前端不同阶段工资待遇如何?前端开发真的很值钱吗?
  9. highchart 组织结构图
  10. 非因推荐 | 肿瘤微环境研究大剖析——肿瘤相关巨噬细胞
  11. python entry_tkinter常用控件演示(Entry)
  12. 【小沐学python】(二)Python常见问题汇总
  13. python中可以清空字典并保留变量的是,给定字典d,以下选项中可以清空该字典并保留变量的...
  14. QT调用IE浏览器COM插件完成网页浏览
  15. 六自由度机械臂正向运动学与姿态绘制with matlab
  16. 想按最低税率3%缴纳个税,月薪和年终奖最高多少最为合适?
  17. 【JavaScript基础-二维数组】JavaScript修改二维数组的某个元素时,其上下元素也受到影响
  18. CASIA-Webface数据集
  19. 为什么中层没有执行力?
  20. 快部署·快交付·快服务|企企通SaaS采购云,激活企业数字化采购价值

热门文章

  1. 《Fast Online Object Tracking and Segmentation: A Unifying Approach》
  2. 测试工程师等级评定细则
  3. WS2812硬件电路设计
  4. html斜线背景,PS斜线底纹如何制作?
  5. 有哪些高含金量的编程竞赛?
  6. 录屏的知识片段的记录与理解
  7. Alpha阶段敏捷冲刺②
  8. c++将浮点数转换为整数类型,要求四舍五入
  9. 智能微电网的核心技术
  10. 弘辽科技:改淘宝宝贝副标题有影响吗?如何修改宝贝标题没影响?