Android 逆向Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )相关的知识,希望对你有一定的参考价值。





一、进程注入原理



调试进程 Attach 被调试进程 :

工具程序 ( 调试进程 ) 获取调试 目标进程 ( 被调试进程 ) 的权限 , 调用 ptrace 函数 , 传入 PTRACE_ATTACH 参数 ;

如果 目标进程 Attach 成功 , 该进程会自动挂起 , 暂停执行指令 ; 并返回 WUNTRACED 状态给 工具程序 , 表示 目标进程 已经进入 被调试状态 ;


调试进程 读取 被调试进程 寄存器值 :

工具程序 ( 调试进程 ) 调用 ptrace 函数 , 传入 PTRACE_GETREGS 参数 , 获取调试 目标进程 ( 被调试进程 ) 的寄存器值 , 获取成功后 , 返回给 工具程序 ( 调试进程 ) ;

工具程序 ( 调试进程 ) 中拿到寄存器值后 , 保存一份寄存器值 , 之后再进行远程调用等操作 , 最后 Detach 解除调试时 , 必须根据保存的寄存器值 , 恢复 目标进程 ( 被调试进程 ) 的寄存器值 ;


工具程序 ( 调试进程 ) 远程调用 目标进程 ( 被调试进程 ) :

远程调用 指的是 在 目标进程 ( 被调试进程 ) 中 , 执行 我们想要执行的程序 , 一般是加载 SO 动态库 或远程代码 , 使用 malloc 分配内存 , 然后将代码复制到该段内存中 , 给这块内存分配可执行权限 ;

一般情况是注入一个 SO 动态库 , 每个 SO 动态库 都是独立模块 , 这样不会破坏原有的代码体系 ,

然后 通过 远程调用 , 获取该内存的地址 , 之后就可以使用远程调用执行注入的代码 ;

注入代码 , 一般是用于修改 进程逻辑用的 , 修改 目标进程 ( 被调试进程 ) 内存中的数据 ;


进程注入原理图 :





二、远程调用流程 ( 获取 so 动态库地址 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )



远程调用 的 核心就是 要 准确的计算 要远程调用的 SO 动态库的库函数 在内存中的地址 ;


内存空间是一块线性的空间 , 内存地址从低到高依次线性排列 , 如 0x00 00 00 00 ~ 0x FF FF FF FF , 32 位地址对应的指针地址长度都是 4 字节 , 最多访问 4 GB 的内存空间 ;


工具程序 ( 调试进程 ) 又称为 " 控制进程 " , 对应下图的 控制进程 , 控制进程 在 内存中 , 占据一定的控件 ;

目标进程 ( 被调试进程 ) 又称为 " 被控制进程 " , 对应下图的 控制进程 , 被控制进程 在 内存中 , 也占据一定的控件 ;

控制进程 与 被控制进程 在内存中 , 先后顺序不确定 ;


下图的内存是 android 设备的整体内存 ;


在 /proc/pid 对应 进程的 目录下 , 有 mmaps 文件 , 在该文件中 , 会记录所有的 so 动态库的 起止 内存地址 ;

根据 /proc/pid/mmaps 文件 , 可以获取 工具程序 ( 调试进程 ) 的 libc.so 的起止地址 , 也可以获取 目标进程 ( 被调试进程 ) 的 libc.so 的起止地址 ;

在 libc.so 中存在 dlopen 函数 , dlopen 函数有一个函数指针 ( 函数地址 ) , 该函数指针可以直接获取到 , dlopen 的名称就代表该函数的地址 , libc.so 的起始地址可以通过 /proc/pid/mmaps 文件确定 , dlopen 函数在 libc.so 的相对偏移量 ( 如 : 8 字节 ) 也是确定的 , 这样就可以知道 dlopen 函数在内存中的地址 ;

获取到 dlopen 函数地址后 , 将 IP 寄存器设置成 r_dlopen 函数地址 ; IP 寄存器存储将要执行的下一条指令的偏移量 ;

通过 mmap 函数 , 分配一块新内存 , SP 寄存器指向这块新内存 , 之后 调用 ptrace 函数传入 PTRACE_CONT 参数 , 继续执行将控制权交还给 目标进程 ( 被调试进程 ) , 继续执行 , 直到下一个中断发生 ; SP 寄存器是堆栈指针寄存器 ;

以上是关于Android 逆向Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 进程注入工具开发 ( 注入代码分析 | 调试进程 ATTACH 附着目标进程 | 读取目标函数寄存器值并存档 )

Android 逆向Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )(代

Android 逆向Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )

Android 逆向Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )(代码片

Android 逆向Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )

Android 逆向Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )