全部代码在这里下载:http://download.csdn.net/detail/a345017062/8133239

里面有两个exe。inj是一个C层进程注入的样例。inj_dalvik是我写的Java注入。
C层的进程注入借直接拉的洗大师的开源项目(https://code.google.com/p/libandroidinjector/)

Android的基础服务大部分都是使用Java写的,仅仅是C层的注入,想要直接訪问的话还是比較麻烦。所以须要在远端载入一个dex包(代码中写死了载入/data/local/inj文件夹下的dex)。

载入dex须要Dalvik虚拟机的Context。也就是JNIEnv,这个略微遇到了一些麻烦,直接在源代码上面编译的话。构建源代码的编译环境就比較费时间了。最后还是从源代码中拉出Header文件,又从我的手机(ZTE N5 4.1.2)中adb pull下来了android_runtime和nativehelper这两个.so才攻克了编译、链接的问题。
C层载入dex之后。能够调用Java的main方法运行Java代码了,可是想做一些訪问系统服务的事情的话,没有Context是不行的。所以通过反射调用ActivityThread。拿到Application。
我最初的想法是使用inj_dalvik注入到system_server进程,然后訪问里面全部的Android系统服务,但后来发现这样有两个问题,dex在system_server进程运行时不能使用PackageManager这种远端服务代理,仅仅能使用ServiceManager.getService("package")直接获取PackageManagerService实例。并且发现PackageManagerServer这种服务,接口变动比較频繁。版本号适配上比較麻烦。

所以最后还是决定注入到一个user为system的客户进程。比方com.android.settings。然后整个流程就跑通了。

如今面临的一个未解决的问题是com.android.setting这种进程并非系统Daemon,不是常驻进程,我们的代码注入后不能永远存活。但其他像/system/bin/surfaceflinger这种进程。由于本身是C程序。启动时并没有AndroidRuntime,无法载入我们的Dex并Java代码。

所以,要么在须要运行远端代码时后台偷偷启动com.android.settings进程,要么自己fork出一个具有AndroidRuntime的进程来。并把它注冊到init.rc中。

补充于2014.11.19

手机助手中通常都须要用到这种功能,停用某个用户不使用的系统应用,或者为了禁止应用被后台唤起而停用应用中的某个组件。通过Root后有一种比較简单的办法就是在su下运行pm命令。但这种方式有几个比較大的缺陷:一个是效率低,由于须要新开进程。

二个是假设一个组件的类是个内部类,类名中包括$这种符号的话,pm命令会运行失败。三个是应用自身能够恢复自身组件的停用状态。

这里提供一个比較简单的实现方案。
我们研究PackageManagerService代码发现,调用setComponentEnabledSetting、setApplicationEnabledSetting这样方法假设是针对其他应用的话,检查的是system权限。所以我们仅仅要造一个具有system权限的进程,并在这个进程内部调用这两个方法就OK。这一点已经通过上面的Android进程注入方案中,通过注入到com.android.settings包中得到了验证。我们须要这几步:
一、參考pm、am等工具的实现方式,在源代码下编译一个Jar包。在代码中启动一个Socket服务。接收外部命令。进行校验后运行。

二、把Jar包拷贝到/system/framework下,并在system/bin下建立启动入口。然后使用app_process启动该服务。

三、在init.rc中添加一个services项。以system权限启动该Jar包,这样下次开机时也能自己主动启动。

补充于2014.11.24

进程注入的流程例如以下:
一、attach目标进程。
使用ptrace来attach目标进程,内核将发送 SIGSTOP 将目标进程挂起。我们使用waitpid接收到SIGSTOP以后。使用ptrace_getregs把当前寄存器的内容保存在regs_t中(regs_t这个数据结构的定义在ptrace.h)。再调用PTRACE_CONT使用进程继续运行。
二、在linker找到dlopen,dlsym,dlclose的地址。
搜索/proc/$pid/maps中/system/bin/linker在虚拟进程中的地址。然后在linker的地址范围内搜索分别找到dlopen,dlsym,dlclose的地址。存储在数据结构dl_fl_t中。

三、载入并运行本地SO。
Android中的动态载入与Linux中有些不同,是没有懒载入的,C代码中引用到的.so会在进程启动时载入完毕。假设C代码中用到dlopen等显式动态载入方法时,须要在编译时加上libdl.so,但代码实际运行中逻辑实现是在linker中的。所以我们在linker中就能够找到dlopen,dlsym,dlclose的handle。

通过第二步拿到dlopen,dlsym的地址之后。就能够通过ptrace改写远程进程的寄存器的PC寄存器地址(R15)到dlopen的地址,然后ptrace_cont,就能够载入本地的SO库了。

Android进程注入的更多相关文章

  1. Android中通过进程注入技术改动广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了怎样通过进程的注入技术改动广播接收器的优先级.关于这个应用场景是非常多的.并且也非常重要.所以就非常急的去fixed了. Android中的四大组件中有一个广播:B ...

  2. Android中通过进程注入技术修改广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了如何通过进程的注入技术修改广播接收器的优先级,关于这个应用场景是很多的,而且也很重要,所以就很急的去fixed了. Android中的四大组件中有一个广播:Broa ...

  3. Android中通过进程注入技术修改系统返回的Mac地址

    致谢 感谢看雪论坛中的这位大神,分享了这个技术:http://bbs.pediy.com/showthread.php?t=186054,从这篇文章中学习到了很多内容,如果没有这篇好文章,我在研究的过 ...

  4. Android进程的so注入--Poison(稳定注入版)

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53869796 Android进程的so注入已经是老技术了,网上能用的Android ...

  5. Android进程so注入Hook java方法

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/53769331 Andorid的Hook方式比较多,现在来学习下,基于Android ...

  6. Android 进程常驻----开机广播的简单守护以及总结

    这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clean master获取root权限下都无法杀死进程 支持系统2.3到 ...

  7. Android so注入(inject)和Hook技术学习(三)——Got表hook之导出表hook

    前文介绍了导入表hook,现在来说下导出表的hook.导出表的hook的流程如下.1.获取动态库基值 void* get_module_base(pid_t pid, const char* modu ...

  8. Android 进程常驻(5)----开机广播的简单守护以及总结

    这是一个轻量级的库,配置几行代码.就能够实如今android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下.clean master获取root权限下都无法杀死进程 支持系统2.3到 ...

  9. Android so注入( inject)和Hook(挂钩)的实现思路讨论

    本文博客:http://blog.csdn.net/qq1084283172/article/details/54095995 前面的博客中分析一些Android的so注入和Hook目标函数的代码,它 ...

随机推荐

  1. Delphi7 中使用FastMM 转载

    http://blog.csdn.net/cai5/article/details/17142697 Delphi7 中使用FastMM 在工程的第一行引用FastMM4即可(注意,一定要在第一个Us ...

  2. static关键字与方法区和类加载

    1.static的作用 答:将成员变量或方法存储进方法区.因为方法区能保证数据只存在一份,只会加载一次(类加载器加载类的时候才加载一次) 注:static Object obj = new Objec ...

  3. Android实例剖析笔记(二)

    摘要:用实例讲解Andriod的开发过程,以NotesList为实例介绍Android的菜单机制 简介 android提供了三种菜单类型,分别为options menu,context menu,su ...

  4. python文本 字符串逐字符反转以及逐单词反转

    python文本 字符串逐字符反转以及逐单词反转 场景: 字符串逐字符反转以及逐单词反转 首先来看字符串逐字符反转,由于python提供了非常有用的切片,所以只需要一句就可以搞定了 >>& ...

  5. iptables只允许指定ip地址访问指定端口

    首先,清除所有预设置 iptables -F#清除预设表filter中的所有规则链的规则 iptables -X#清除预设表filter中使用者自定链中的规则 其次,设置只允许指定ip地址访问指定端口 ...

  6. 偏执却管用的10条Java编程技巧

    本文由 ImportNew - LynnShaw 翻译自 javacodegeeks.欢迎加入翻译小组.转载请见文末要求. 经过一段时间的编码(咦,我已经经历了将近20年的编程生涯,快乐的日子总是过得 ...

  7. sql递归查询子级

    WITH T(emp_no, name, dept_no, the_level, path,path1,manager_id) AS( SELECT emp_no, name, dept_no ,1 ...

  8. JQuery实现可直接编辑的表格

    本文实例讲述了JQuery实现可直接编辑的表格.分享给大家供大家参考.具体分析如下: 功能: 创建一个表格,用户单击某个单元格后,可以直接修改单元格文本.在编辑状态下,用户可按回车键确认修改,按ESC ...

  9. Map实现java缓存机制的简单实例

    缓存是Java中主要的内容,主要目的是缓解项目访问数据库的压力以及提升访问数据的效率,以下是通过Map实现java缓存的功能,并没有用cache相关框架. 一.缓存管理类 CacheMgr.java ...

  10. Java基础(十):封装

    在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装.隐藏起来的方法.封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访 ...