使用ptrace向已运行进程中注入 so并执行相关函数

本文介绍如何利用ptrace向已运行进程注入.so,并通过dlopen执行相关函数。详细阐述了如何找到目标进程空间、写入并执行加载代码、赋值全局变量、写入汇编代码以及实现过程。
摘要由CSDN通过智能技术生成

首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的。教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈~我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转到教程

               

1. 简介

    使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对应的地址,然后通过此地址便可在目标进程中进行调用。

     到底是如何注入的呢?

     本文实现方案为:在目标进程中,通过dlopen把需要注入的.so加载到目标进程的空间中。

2. 如何让目标进程执行dlopen加载.so?

     显然,目标进程本来是没有实现通过dlopen来加载我们想注入的.so,为了实现此功能,我们需要目标进程执行一段我们实现的代码,此段代码的功能为通过dlopen来加载一个.so。

3. 【加载.so的实现代码】

    加载需要注入的.so的实现代码如下所示:     

.global _dlopen_addr_s       @dlopen函数在目标进程中的地址     注:以下全局变化在C中可读写.global _dlopen_param1_s     @dlopen参数1<.so>在目标进程中的地址 .global _dlopen_param2_s     @dlopen参数2在目标进程中的地址.global _dlsym_addr_s        @dlsym函数在目标进程中的地址.global _dlsym_param2_s      @dlsym参数2在目标进程中的地址,其实为函数名.global _dlclose_addr_s      @dlcose在目标进程中的地址.global _inject_start_s      @汇编代码段的起始地址.global _inject_end_s        @汇编代码段的结束地址.global _inject_function_param_s  @hook_init参数在目标进程中的地址.global _saved_cpsr_s        @保存CPSR,以便执行完hook_init之后恢复环境.global _saved_r0_pc_s       @保存r0-r15,以便执行完hook_init之后恢复环境.data_inject_start_s: @ debug loop3: @sub r1, r1, #0 @B 3b @ dlopen ldr r1, _dlopen_param2_s        @设置dlopen第二个参数, flag ldr r0, _dlopen_param1_s        @设置dlopen第一个参数 .so ldr r3, _dlopen_addr_s          @设置dlopen函数 blx r3                          @执行dlopen函数,返回值位于r0中 subs r4, r0, #0                 @把dlopen的返回值soinfo保存在r4中,以方便后面dlclose使用 beq 2f @dlsym ldr r1, _dlsym_param2_s        @设置dlsym第二个参数,第一个参数已经在r0中了 ldr r3, _dlsym_addr_s          @设置dlsym函数 blx r3                         @执行dlsym函数,返回值位于r0中 subs r3, r0, #0                @把返回值<hook_init在目标进程中的地址>保存在r3中 beq 1f @call our function ldr r0, _inject_function_param_s  @设置hook_init第一个参数        blx r3                            @执行hook_init subs r0, r0, #0 beq 2f1: @dlclose                         mov r0, r4                        @把dlopen的返回值设为dlcose的第一个参数 ldr r3, _dlclose_addr_s           @设置dlclose函数 blx r3                            @执行dlclose函数2: @restore context ldr r1, _saved_cpsr_s             @恢复CPSR msr cpsr_cf, r1 ldr sp, _saved_r0_pc_s            @恢复寄存器r0-r15 ldmfd sp, {r0-pc}     _dlopen_addr_s:                           @初始化_dlopen_addr_s.word 0x11111111_dlopen_param1_s:.word 0x11111111_dlopen_param2_s:.word 0x2                                 @RTLD_GLOBAL_dlsym_addr_s:.word 0x11111111_dlsym_param2_s:.word 0x11111111_dlclose_addr_s:.word 0x11111111_inject_function_param_s:.word 0x11111111_saved_cpsr_s:.word 0x11111111_saved_r0_pc_s:.word 0x11111111_inject_end_s:                     @代码结束地址.space 0x400, 0                    @代码段空间大小.end

4. 如何把【加载.so的实现代码】写入目标进程并启动执行?

   为了把【加载.so的实现代码】写入目标进程,主要有以下两步操作:

   1) 在目标进程中找到存放【加载.so的实现代码】的空间(通过mmap实现)

   2) 把【加载.so的实现代码】写入目标进程指定的空间

   3) 启动执行

4.1 在目标进程中找到存放【加载.so的实现代码】的空间

    通过mmap来实现,其实现步骤如下:

   1) 获取目标进程中mmap地址
   2) 把mmap参数据放入r0-r3,另外两个写入目标进程sp 
   3) pc设置为mmap地址,lr设置为0
   4) 把准备好的寄存器写入目标进程(PTRACE_SETREGS),并启动目标进程运行(PTRACE_CONT)
   5) 分配的内存首地址位于r0 (PTRACE_GETREGS)

4.2 为【加载.so的实现代码】中的全局变量赋值

   1) 获取目标进程中dlopen地址并赋值给_dlopen_addr_s

   2) 获取目标进程中dlsym地址并赋值给_dlsym_addr_s

   3) 获取目标进程中dlclose地址并赋值给_dlclose_addr_s

   4) 把需要加载的.so的路径放入 汇编代码中,并获取此路径在目标进程中的地址然后赋值给_dlopen_param1_s

   5) 把需要加载的.so中的hook_init放入 汇编代码中,并获取此路径在目标进程中的地址然后赋值给_dlsym_param2_s

   6) 把目标进程中的cpsr保存在_saved_cpsr_s中

   7) 把目标进程中的r0-r15存入汇编代码中,并获取此变量在目标进程中的地址然后赋值给_saved_r0_pc_s

   8) 通过ptrace( PTRACE_POKETEXT,...)把汇编代码写入目标进程中,起始地址由前面的mmap所分配

   9) 把目标进程的pc设置为汇编代码的起始地址,然后调用ptrace(PTRACE_DETACH,...)以启动目标进程执行

5. 把汇编代码写入目标进程并执行的实现代码

5.1 主函数 writecode_to_targetproc

#include <stdio.h>#include <stdlib.h>#include <asm/ptrace.h>#include <asm/user.h>#include <asm/ptrace.h>#include <sys/wait.h>#include <sys/mman.h>#include <dlfcn.h>#include <dirent.h>#include <unistd.h>#include <string.h>#include <android/log.h>#include <sys/types.h>#include <sys/socket.h>#inc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值