android inject so,android hook 框架 libinject 如何实现so注入
前面两篇
今天分析一下古河大神原始的 libinject 的源码,libinject2 与 原始的 libinject 大部分代码是一致的,各种 ptrace 的封装函数基本照抄,但有一点很不一样,古河的 libinject 在执行so注入及执行注入的so内的hook函数时,是将一连串的函数构造成一块统一的 shellcode ,然后整块shellcode 写入目标进程 mmap 出来的一块地址,设置目标进程寄存器,一次性调用。 而 libinject2 是分开多次设置目标进程的内存和寄存器,并多次调用实现同样的效果。从代码可读性看,libinject2 更清晰易懂。这一篇文章只分析两者不同的部分。
首先,shellcode 代码写在一个单独的汇编文件里, shellcode.s , 将需要在目标进程执行的 dlopen,dlsym,dlclose, 及hook函数都先用汇编写好,各个函数的真实地址和参数的真实值由 inject.c 里的函数动态指定,这份汇编会与 inject.c 编译后的汇编链接在一起
.global_dlopen_addr_s
.global_dlopen_param1_s
.global_dlopen_param2_s
.global_dlsym_addr_s
.global_dlsym_param2_s
.global_dlclose_addr_s
.global_inject_start_s
.global_inject_end_s
.global_inject_function_param_s
.global_saved_cpsr_s
.global_saved_r0_pc_s
.data
_inject_start_s:
@ debug loop3:
@sub r1, r1, #0@B 3b
@ dlopen
ldr r1, _dlopen_param2_s
ldr r0, _dlopen_param1_s
ldr r3, _dlopen_addr_s
blx r3
subs r4, r0, #0beq 2f
@dlsym
ldr r1, _dlsym_param2_s
ldr r3, _dlsym_addr_s
blx r3
subs r3, r0, #0beq 1f
@call our function
ldr r0, _inject_function_param_s
blx r3
subs r0, r0, #0beq 2f1:
@dlclose
mov r0, r4
ldr r3, _dlclose_addr_s
blx r32:
@restore context
ldr r1, _saved_cpsr_s
msr cpsr_cf, r1
ldr sp, _saved_r0_pc_s
ldmfd sp, {r0-pc}
_dlopen_addr_s:
.word0x11111111_dlopen_param1_s:
.word0x11111111_dlopen_param2_s:
.word0x2_dlsym_addr_s:
.word0x11111111_dlsym_param2_s:
.word0x11111111_dlclose_addr_s:
.word0x11111111_inject_function_param_s:
.word0x11111111_saved_cpsr_s:
.word0x11111111_saved_r0_pc_s:
.word0x11111111_inject_end_s:
.space0x400, 0.end
这里插入一下,怎么在android里使用这份代码呢,仍然是新建一个module,然后 Android.mk 如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=inject
LOCAL_SRC_FILES := ../inject.c ../shellcode.s
LOCAL_ARM_MODE :=arm
LOCAL_CFLAGS := -g
include $(BUILD_EXECUTABLE)
在Android.mk文件目录下执行 ndk-build 即可
libinject 的注入过程如下:
int inject_remote_process( pid_t target_pid, const char *library_path, const char *function_name, void *param, size_t param_size )
{int ret = -1;void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr;void *local_handle, *remote_handle, *dlhandle;
uint8_t*map_base;structpt_regs regs, original_regs;externuint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s,
_saved_cpsr_s, _saved_r0_pc_s; // shellcode.s 汇编代码定义的变量long parameters[10];
DEBUG_PRINT("[+] Injecting process: %d", target_pid );
if ( ptrace_attach( target_pid ) == -1 )
return EXIT_SUCCESS;
if ( ptrace_getregs( target_pid, ®s ) == -1)gotoexit;/*save original registers*/memcpy(&original_regs, ®s, sizeof(regs) ); // 第一步,attach目标进程,并保留注入前的寄存器状态
mmap_addr= get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap );/*call mmap*/parameters[0] = 0; //addr
parameters[1] = 0x4000; //size
parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; //prot
parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; //flags
parameters[4] = 0; //fd
parameters[5] = 0; //offset
DEBUG_PRINT("[+] Calling mmap in target process.");
if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s ) == -1 )
goto exit;
if ( ptrace_getregs( target_pid, ®s ) == -1)gotoexit;
map_base= (uint8_t *)regs.ARM_r0; // 第二步,在目标进程执行 mmap 分配一块内存
dlopen_addr= get_remote_addr( target_pid, linker_path, (void *)dlopen );
dlsym_addr= get_remote_addr( target_pid, linker_path, (void *)dlsym );
dlclose_addr= get_remote_addr( target_pid, linker_path, (void *)dlclose );
remote_code_ptr= map_base + 0x3C00;
local_code_ptr= (uint8_t *)&_inject_start_s; // 本进程 shellcode 的起始地址
_dlopen_addr_s=(uint32_t)dlopen_addr;
_dlsym_addr_s=(uint32_t)dlsym_addr;
_dlclose_addr_s=(uint32_t)dlclose_addr; //第三步,获取目标进程 dlopen,dlsym,dlclose函数地址并赋值给汇编文件定义的变量
code_length= (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s;
dlopen_param1_ptr= local_code_ptr + code_length + 0x20;
dlsym_param2_ptr= dlopen_param1_ptr +MAX_PATH;
saved_r0_pc_ptr= dlsym_param2_ptr +MAX_PATH;
inject_param_ptr= saved_r0_pc_ptr +MAX_PATH; // 设置dlopen,dlsym等函数的参数相对于汇编代码起始地址的地址
strcpy( dlopen_param1_ptr, library_path );
_dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr );
/*dlopen parameter 1: library name*/DEBUG_PRINT("[+] _dlopen_param1_s: %x", _dlopen_param1_s );/*dlsym parameter 2: function name*/strcpy( dlsym_param2_ptr, function_name );
_dlsym_param2_s=REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr );
DEBUG_PRINT("[+] _dlsym_param2_s: %x", _dlsym_param2_s );/*saved cpsr*/_saved_cpsr_s=original_regs.ARM_cpsr;/*saved r0-pc*/memcpy( saved_r0_pc_ptr,&(original_regs.ARM_r0), 16 * 4 ); //r0 ~ r15
_saved_r0_pc_s =REMOTE_ADDR( saved_r0_pc_ptr, local_code_ptr, remote_code_ptr );
DEBUG_PRINT("[+] _saved_r0_pc_s: %x", _saved_r0_pc_s );/*Inject function parameter*/memcpy( inject_param_ptr, param, param_size );
_inject_function_param_s=REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr );
DEBUG_PRINT("[+] _inject_function_param_s: %x", _inject_function_param_s );//第四步,计算要执行的 dlopen,dlsym函数及参数在目标进程内相对于前面mmap出来的地址的地址
DEBUG_PRINT("[+] Remote shellcode address: %x", remote_code_ptr );
ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr,0x400);//第五步: 将整块shellcode代码写入目标进程的内存
memcpy(®s, &original_regs, sizeof(regs) );
regs.ARM_sp= (long)remote_code_ptr;
regs.ARM_pc= (long)remote_code_ptr;
ptrace_setregs( target_pid,®s ); // 第六步,修改目标进程的栈顶指针 sp 执行shellcode 的初始位置,且设置pc寄存器也指向这个位置
ptrace_detach( target_pid ); // 第七步,detach目标进程,目标进程接下去会开始执行shellcode//inject succeeded
ret = 0;
exit:returnret;
}
我们看到,libinject 没有将 original_regs 恢复到目标进程的ptrace 操作,其实shellcode里执行完hook函数后,最后会执行 @restore context 的代码,这几句就是恢复寄存器状态的
到目前为止,一共分析了3份so注入代码,前两份为:
对比一下,
首先,3份注入代码原理是一样的,都是利用ptrace系统调用,获取目标进程寄存器,在目标进程调用dlopen/dlsym等动态库函数实现在目标进程加载指定的so, 加载之后执行挂钩函数时,hijack 利用 __attribute__ ((constructor)) 函数属性实现自动执行,libinject/libinject2 还是通过寄存器ptrace操作执行函数。
其次,古河的libinject和adbi的hijack都是事先构造一片‘shellcode’,再块拷贝到目标进程地址空间(先操作目标进程寄存器调用mmap分配一块),然后再执行这块预先构造好的‘shellcode’,不同是libinject 是用汇编代码构造,hijack是写在一个数组里。libinject2在实现注入时,将上述shellcode分成多次的 ptrace 调用,代码可读性更高,逻辑更清晰
最后,libinject/libinject2只是提高了注入的实现,没有挂钩的实现。 adbi 项目还提供了挂钩框架的实现
android inject so,android hook 框架 libinject 如何实现so注入相关推荐
- Android中免root的hook框架学习——whale(一)下载和基本介绍
本文是whale的基本介绍,下一篇将介绍实战demo 项目地址:https://github.com/asLody/whale 以下内容来自whale项目README的介绍 一.概述 Whale是一个 ...
- Android中免root的hook框架学习——whale(二)实战hook java方法
文末附项目完整代码下载地址 一.在android studio中创建一个新的项目 Hook Java, 把whale项目里的java文件夹的代码复制到自己的项目中. 复制 built/Android ...
- android hook 第三方app_基于 VirtualApp 结合 whale hook框架实现hook第三方应用
要点 1. whale hook framework 使用示例: 2. 参考项目:VirtualHook: 3. 按照 VirtualHook 修改 VirtualApp: 4. 编写 hook pl ...
- Android平台dalvik模式下java Hook框架ddi的分析(1)
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75710411 一.前 言 在前面的博客中已经学习了作者crmulliner编写的, ...
- 全能Android HOOK框架 JNI NATIVE JAVA ART DALVIK
OneHook 目前比较流行的几个安卓HOOK方案,都有功能上的欠缺,有的不支持art模式,有的不支持jni层,有的不支持侵入HOOK. 所以OneHook诞生了! 这是一个同时支持ART和Dalvi ...
- Android主流HOOK框架介绍与应用--游戏破解游戏外挂的必杀技
概述 使用HOOK方案主要是在分析的时候会经常用到,虽然二次打包重新修改代码也可以做到,但是一方面效率低,另一方面如果APP有校验的逻辑就需要进一步绕过,总体还是比较费时费力.所以,通过动态HOOK的 ...
- Android的so注入( inject)和函数Hook(基于got表) - 支持arm和x86
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53942648 前面深入学习了古河的Libinject注入Android进程,下面来 ...
- Android.Hook框架xposed篇(Http流量监控)
瘦蛟舞 · 2015/08/03 10:30 官方教程:github.com/rovo89/Xpos- 官网:repo.xposed.info/module/de.r- apk:dl-xda.xpos ...
- 【Android 插件化】Hook 插件化框架总结 ( 插件包管理 | Hook Activity 启动流程 | Hook 插件包资源加载 ) ★★★
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 【Android 插件化】Hook 插件化框架 ( 使用 Hook 方式替换插件 Activity 的 mResources 成员变量 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
最新文章
- nyoj 287(区间覆盖)
- android 全局进度条,Android:如何在中心显示全屏进度条
- [攻防世界 pwn]——pwn-200
- sql入侵 mysql日志_服务器入侵日志分析(一)——mysql日志位置确定
- C++ Lambda表达式demo
- 线性表9 - 数据结构和算法14
- markdown 书写代码
- 百度搜索排名优化和SEO搜索引擎优化
- spark-streaming 编程(四)自定义输出foreachRDD
- 根据地址查询经纬度Js
- 郑州财经学院第54次全国计算机,郑州财经学院第二期教师博士班开班
- OpenCV3实现橡皮擦功能[画板]
- el-tree 改变label
- 一、 Python 基础知识笔记 —— 《Python编程:从入门到实践(第二版)》学习笔记
- 【virtualbox】虚拟机virtualbox mac版使用教程
- 【Redis连接超时】io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.x.x:7000
- 职场生来不公平 透视四大潜规则
- 浅谈MOS管的米勒效应
- 深入了解css中的grid布局
- 项目管理与SSM框架——Maven
热门文章
- spring @POSTConstruction注解的作用
- SqlServer修改密码后登陆不上
- mysql中表示金钱的类型
- WPF中的Application类。
- Debian下安装搜狗拼音输入法
- 使用Supervisor让你的Swift Perfect服务器项目后台运行
- Asp.net MVC 移除视图引擎(WebFormViewEngine或者RazorViewEngine)
- 跨域访问JQuery+.NET实现的一种思路,以及极简单Demo
- 在java中2l是什么_(二)常量定义
- java swing 雪花_求用JAVA制作的飘雪花的效果