实现对第三方应用任意SO注入
0x01
应用在Android中运行,从外部对该进程可以进行任意SO文件动态注入,就是应用动态运行我们的SO文件
0x02
基本的逻辑是:
1. 获取目标进程的pid,关联目标进程:通过遍历查找/proc/pid/cmdline文件中是否含有目标进程名process_name,若有则进程名对应的进程号即为pid。接着,直接调用函数ptrace_attach(pid)即可完成关联。
2. 获取并保存目标进程寄存器值:用ptrace(PTRACE_GETREGS, pid, NULL, &saved_regs)
3. 获取目标进程的dlopen,dlsym函数的绝对地址:首先通过遍历/proc/pid/maps文件分别得到本进程中dlopen函数所在动态库的基地址local_module_base和目标进程dlopen函数所在动态库的基地址remote_module_base,接着获取本进程dlopen函数的绝对地址local_addr = (void*)dlopen。需要明白的是,不同进程中相同的动态库中的同一个函数的偏移地址一定是一样的,所以目标进程dlopen函数的绝对地址为:local_addr – local_module_base + remote_module_base。dlsym同理
4. 获取并保存目标进程的堆栈,设置dlopen函数的相关参数,将要注入的SO的绝对路径压栈:当我们的要执行的函数的某些参数需要压入堆栈的时候,就需要提前保存堆栈状态,调用ptrace_readdata(pid, (void *)regs.ARM_sp, (void *)sbuf, sizeof(sbuf)),其中sbuf为char数组,用来存放堆栈。调用ptrace_writedata(pid, (void *)regs.ARM_sp, (void *)so_path, strlen(so_path) + 1),其中so_path为SO的绝对路径。函数传参规则:前四个参数分别由寄存器r0、r1、r2、r3存放,超过四个参数则压入堆栈。
5. 调用dlopen函数:参数设置好后,设置ARM_pc = dlopen_addr, ARM_lr = 0。调用ptrace_setregs(pid, regs)写入修改后的寄存器值,调用ptrace_continue( pid )使目标进程继续运行。(注:dlopen_addr为0x03获取到的目标进程dlopen函数的绝对地址,ARM_lr = 0的目的在于当目标进程执行完dlopen函数,使目标进程发生异常,从而让本进程重新获得控制权)
6. 调用dlsym函数,获取SO中要执行的函数地址:实现方式与调用dlopen函数类似,不再详述
7. 调用要执行的函数:实现方式与调用dlopen函数类似
8. 恢复目标进程的堆栈,恢复目标进程寄存器值,解除关联,完成SO动态库注:调用ptrace_writedata(pid, (uint8_t *)saved_regs.ARM_sp, (uint8_t *)sbuf, sizeof(sbuf))恢复堆栈,调用ptrace_setregs(pid, &saved_regs)恢复寄存器值,调用ptrace_detach(pid)解除关联,完成SO动态库注入
0x03
我知道都不爱看上边原理,下面直接开始吧
首先我有一个可以root机器(没有别玩了,我是自己买的5儿子)
Linux下安装NDK 在环境变量里配好(kali /etc/profile),加上解压后的NDK路径
下面我们需要编译两个文件 xxxx.so(你的SO),nject(用来注入的)
为了编译我们需要创建两个文件夹在任意目录下
两个文件夹都是xxx.c+jni(文件夹) ,jni下放的是Android.mk文件
1.hello 下的 hello.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <elf.h>
#include <fcntl.h>
#define LOG_TAG “DEBUG”
#define LOGD(fmt, args…) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
int hook_entry(char * a){
LOGD(“Hook success, pid = %d\n”, getpid());
LOGD(“Hello %s\n”, a);
return 0;
}
hello/jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog #增加了对android log 库的链接
LOCAL_MODULE := hello
LOCAL_SRC_FILES := ../hello.c
include $(BUILD_SHARED_LIBRARY) #指定编译为动态库
2.libinject2下的ject.c (太长了加个链接)
http://blog.csdn.net/jinzhuojun/article/details/9900105
找不到asm/user.h 请改为sys/user.h
libinject2/jni/Android.mk
OCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := inject
LOCAL_SRC_FILES := ../inject.c
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
include $(BUILD_EXECUTABLE)
下面就是进行编译这两个文件
一个是so文件一个可执行文件
把他俩push到手机的/data/local/tmp文件夹下 chmod 777 即可
随便PS找到一个进程(我用的com.android.phone)找到进程号,执行./inject
这里要先把libhello文件移动到上面的路径,运行,监控logcat
这里的Hook success 和Hello就是SO内容了,到此SO动态注入成功了
感谢:
http://blog.csdn.net/jinzhuojun/article/details/9900105
http://www.cnblogs.com/jiayy/p/4286828.html
实现对第三方应用任意SO注入的更多相关文章
- Vue导入非模块化的第三方插件功能无效解决方案
一.问题: 最近在写vue项目时,想引入某些非模块化的第三方插件时,总是发现会有报错.且在与本地运行插件测试对比时发现插件根本没有注入到jQuery中(console.log($.fn)查看当前jq有 ...
- 控制反转IOC的依赖注入方式
引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...
- spring boot servlet 注入
spring boot 注入servlet的方法是借助ServletRegistrationBean这个类 例子如下: 先建一个servlet import java.io.IOException; ...
- NetCore+Dapper WebApi架构搭建(四):仓储的依赖注入
上一节我们讲到实体,仓储接口和仓储接口的实现需要遵循约定的命名规范,不仅是规范,而且为了依赖注入,现在我们实现仓储的依赖注入 在NetCore WebApi项目中新添加一个文件夹(Unit),当然你也 ...
- SQL注入工具实践
程序简介 超级SQL注入工具(SSQLInjection)是一款基于HTTP协议自组包的SQL注入工具,支持出现在HTTP协议任意位置的SQL注入,支持各种类型的SQL注入,支持HTTPS模式注入. ...
- JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(7):装配SpringBean·依赖注入装配
一.依赖注入的三种方式 在实际环境中实现IoC容器的方式主要分为两大类,一类是依赖查找,依赖查找是通过资源定位,把对应的资源查找回来.另一类则是依赖注入.一般而言,依赖注入可分为3中方式: ...
- C++代码注入
一.C++代码注入原则: 在注入代码中不允许使用API. 在注入代码中不允许使用全局变量. 在注入代码中不允许使用字符串(编译时也被当做全局变量). 在注入代码中不允许使用函数嵌套. 二.注入代码编写 ...
- 重新整理 .net core 实践篇————依赖注入应用[二]
前言 这里介绍一下.net core的依赖注入框架,其中其代码原理在我的另一个整理<<重新整理 1400篇>>中已经写了,故而专门整理应用这一块. 以下只是个人整理,如有问题, ...
- 【转载】Android app 安全测试调研及执行
本文来源于:http://testerhome.com/topics/2209 一.通过在线工具进行测试 1.腾讯金刚审计系统http://service.security.tencent.com 优 ...
随机推荐
- http加密原理
HTTPS原理 客户端向服务器发送请求 服务器向客户端发送自己的证书 客户端验证证书的有效性(是否是可信用机构CA颁发的证书,如果不是则提出警告)并对比里面信息是否正确,不通过则立刻断开连接 向服务器 ...
- c++ how to make your own class a valid key type for std::map?
In Java, if you want your own class to be a valid key type of the container, you just need to make i ...
- 实战c++中的string系列--std::string与MFC中CString的转换
搞过MFC的人都知道cstring,给我们提供了非常多便利的方法. CString 是一种非常实用的数据类型. 它们非常大程度上简化了MFC中的很多操作,使得MFC在做字符串操作的时候方便了非常多.无 ...
- openWRT自学---初始化过程和主要脚本的分析
参考文档: http://wiki.openwrt.org/doc/techref/process.boot http://blog.csdn.net/jk110333/article/details ...
- 第一百七十二节,jQuery,动画效果
jQuery,动画效果 学习要点: 1.显示.隐藏 2.滑动.卷动 3.淡入.淡出 4.自定义动画 5.列队动画方法 6.动画相关方法 7.动画全局属性 一.显示.隐藏 jQuery 中显示方法为:. ...
- tcp/iP协议族——IP工作原理及实例具体解释(下)
IP协议具体解释 上一篇文章文章主要介绍了IP服务的特点,IPv4头部结构IP分片.并用tcpdump抓取数据包,来观察IP数据报传送过程中IP的格式,以及分片的过程.本文主要介绍IP路由,IP ...
- vs2010 sp1安装
错误 1 Installing Visual Studio 2010 SP1 fails with Generic Trust Failure Installation did not succee ...
- Eigen求矩阵行列式 及 行列式本质
转置.伴随.行列式.逆矩阵 小矩阵(4 * 4及以下)eigen会自动优化,默认采用LU分解,效率不高 #include <iostream> #include <Eigen/Den ...
- html中div获取焦点,去掉input div等获取焦点时候的边框
经测试只有在IE chrome才会在获取焦点时有边框 使用CSS div{ outline:none; } DIV焦点事件详解 --[focus和tabIndex] 摘自:http://my.osc ...
- python3 - 生成器genarator
在Python中,这种一边循环一边计算的机制,称为生成器:generator. 生成器保存的是算法,每次调用 next() ,就计算出 下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 ...