2019独角兽企业重金招聘Python工程师标准>>>

关于这方面技术,网上已经有大把的实现。在此,我只是记录下自己的学习过程。

0x1 原理

所谓的SO注入就是将代码拷贝到目标进程中,并结合函数重定向等其他技术,最终达到监控或改变目标进程行为的目的。Android是基于Linux内核的操作系统,而在Linux下SO注入基本是基于调试API函数ptrace实现的,同样Android的SO注入也是基于ptrace函数,要完成注入还需获取root权限。

0x2 流程

注入过程如下:

0x01 获取目标进程的pid,关联目标进程;

0x02 获取并保存目标进程寄存器值;

0x03 获取目标进程的dlopen,dlsym函数的绝对地址;

0x04 获取并保存目标进程的堆栈,设置dlopen函数的相关参数,将要注入的SO的绝对路径压栈;

0x05 调用dlopen函数;

0x06 调用dlsym函数,获取SO中要执行的函数地址;

0x07 调用要执行的函数;

0x08 恢复目标进程的堆栈,恢复目标进程寄存器值,解除关联,完成SO动态库注入;

(注:实际上,0x06和0x07并不属于SO动态库注入的步骤,然而仅仅注入是完全没有意义的,通常我们需要执行SO中的函数)

0x3 实现

0x01 获取目标进程的pid,关联目标进程:

通过遍历查找/proc/pid/cmdline文件中是否含有目标进程名process_name,若有则进程名对应的进程号即为pid。接着,直接调用函数ptrace_attach(pid)即可完成关联。

0x02 获取并保存目标进程寄存器值:

直接调用ptrace(PTRACE_GETREGS, pid, NULL, &saved_regs),当然saved_regs要定义为全局变量。

0x03 获取目标进程的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同理,不再详述。

0x04 获取并保存目标进程的堆栈,设置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存放,超过四个参数则压入堆栈。

0x05 调用dlopen函数:

参数设置好后,设置ARM_pc = dlopen_addr, ARM_lr = 0。调用ptrace_setregs(pid, regs)写入修改后的寄存器值,调用ptrace_continue( pid )使目标进程继续运行。(注:dlopen_addr为0x03获取到的目标进程dlopen函数的绝对地址,ARM_lr = 0的目的在于当目标进程执行完dlopen函数,使目标进程发生异常,从而让本进程重新获得控制权)

0x06 调用dlsym函数,获取SO中要执行的函数地址:

实现方式与调用dlopen函数类似,不再详述。

0x07 调用要执行的函数:

实现方式与调用dlopen函数类似,不再详述。

0x08 恢复目标进程的堆栈,恢复目标进程寄存器值,解除关联,完成SO动态库注入:

调用ptrace_writedata(pid, (uint8_t *)saved_regs.ARM_sp, (uint8_t *)sbuf, sizeof(sbuf))恢复堆栈,调用ptrace_setregs(pid, &saved_regs)恢复寄存器值,调用ptrace_detach(pid)解除关联,完成SO动态库注入。

0x4 代码

贴一下主要逻辑代码:

pid_t pid = find_pid_of("xxx");
ptrace_attach(pid);
uint32_t *inject_so_of(pid_t pid, const char *so_path) {int status = 0;struct pt_regs regs;memcpy(&regs, &saved_regs, sizeof(regs));ptrace_readdata(pid, (void *)regs.ARM_sp, (void *)sbuf, sizeof(sbuf));ptrace_writedata(pid, (void *)regs.ARM_sp, (void *)so_path, strlen(so_path) + 1);uint32_t parameters[2];parameters[0] = regs.ARM_sp;parameters[1] = RTLD_NOW;if ( ptrace_call(pid, find_dlopen_addr(pid), parameters, 2, &regs ) == -1 )DPRINTF("dlopen error\n");ptrace_getregs(pid, &regs);uint32_t r0 = regs.ARM_r0;DPRINTF("[+2]\t注入动态库成功,返回的句柄为: %x\n", r0);ptrace_setregs(pid, &saved_regs);ptrace_writedata(pid, (uint8_t *)saved_regs.ARM_sp, (uint8_t *)sbuf, sizeof(sbuf));ptrace_detach(pid);return (uint32_t *)r0;
}

0x5 参考

玩转ptrace:http://blog.csdn.net/sealyao/article/details/6710772

《转载》linux动态库注入:http://blog.chinaunix.net/uid-7247280-id-2060516.html

发个Android平台上的注入代码:http://bbs.pediy.com/showthread.php?t=141355

转载于:https://my.oschina.net/u/1777508/blog/664025

Android安全-SO动态库注入相关推荐

  1. [免费专栏] Android安全之利用JDB调试Android应用程序(动态代码注入技术)

    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...

  2. Android开发之动态库调用

    发信人: yangAlbert (蓝), 信区: Android 标  题: Android开发之动态库调用 发信站: 武汉白云黄鹤站 (2011年02月20日23:20:51 星期天) 1.编写并生 ...

  3. 【Android 逆向】Android 中常用的 so 动态库 ( 拷贝 /system/lib/ 中的 Android 系统 so 动态库 )

    文章目录 一.拷贝 /system/lib/ 中的 Android 系统 so 动态库 一.拷贝 /system/lib/ 中的 Android 系统 so 动态库 将 Android 系统的 /sy ...

  4. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  5. WIN动态库注入(远线程注入)

    所谓动态库注入是指,将自己编写的动态库,通过自己的程序来注入到别的进程中去,然后运行. 原理: 在目标进程,开辟一段内存,然后写入要注入的动态库.dll .然后让目标运行加载动态库函数,将该动态库载入 ...

  6. 动态库注入app以及在非越狱手机使用

    动态库注入app以及在非越狱手机使用 1. 动态库编写 动态库编写有多种方式,可以使用Xcode创建动态库,也可以通过tweak生成动态库 对于越狱手机,可以直接编写tweak,将tweak打包成动态 ...

  7. iOS安全攻防(十九):基于脚本实现动态库注入

    基于脚本实现动态库注入 MobileSubstrate可以帮助我们加载自己的动态库,于是开发者们谨慎的采取了对MobileSubstrate的检索和防御措施. 那么,除了依靠MobileSubstra ...

  8. android.mk编译动态库,安卓之Android.mk多文件以及动态库编译

    1.多文件编译 多文件编译共有两种方式: (1) 在Android.mk中一一添加 LOCAL_PATH:= $(call my-dir) #定义当前模块的相对路径 include $(CLEAR_V ...

  9. C/C++劫持技术(函数劫持、dll注入、动态库注入、HOOK)

    目录 劫持 detours 实现劫持 步骤: 1. 安装Detours 2. 编译Detours工程 3. 把静态库和头文件引入工程 4. 函数指针与函数的定义 5.拦截 劫持QQ 实现劫持syste ...

最新文章

  1. 3梅林刷官改变砖_陶瓷透水砖的四大明显优势
  2. Tornado--基于H5图片的上传
  3. 326. Power of Three
  4. P1458 顺序的分数 Ordered Fractions(有技巧的枚举)+C++类封装=精简代码
  5. js app缓存自动刷新_如何通过清除缓存来刷新App Store中的内容
  6. 这个 Python 代码自动补全神器搞得我卧槽卧槽的
  7. 数据结构-动态查找树表与平衡二叉树 红黑树简单介绍
  8. FireEye红队失窃工具大揭秘之:分析复现Zoho ManageEngine RCE (CVE-2020-10189)
  9. Charles抓包-解决显示乱码问题
  10. 并联串联混合的电压和电流_如何从本质上判断电压表测量谁的电压?
  11. ADODB.Recordset 错误 '800a0e7d' 的解决方法
  12. 看完这个,让你分分钟搞定罗盘与加计校准!
  13. 互联网公司裁员还有秘密?我知道了!
  14. 拼多多无货源开店需要用哪些店群软件
  15. 基于CAN的网络管理
  16. linux给分区扩容
  17. Fintech趣店总部(厦门)技术招聘
  18. 招商银行证书到期后不同机器恢复导致的问题——“用户密码、证件号码和证书错误#3”
  19. 天干地支(python)
  20. BVR电线与RV电线的区别有哪些?

热门文章

  1. uva 1218——Perfect Service
  2. 662. 二叉树最大宽度 golang
  3. 213. 打家劫舍 II golang 动态规划
  4. 557. 反转字符串中的单词 III golang 数组和字符串反转
  5. 用英文单词模拟数字计算c语言,C语言程序设计用英文单词模拟数学计算
  6. 【剑指offer】_01 (二维数组中的查找)
  7. 转:C++中const、volatile、mutable的用法
  8. 05-树7 堆中的路径 (25 分)
  9. scrapy从安装到爬取煎蛋网图片
  10. Jmeter测试普通java类说明