且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-05-30 04:32:28

文章目录

一、调试进程 ATTACH 附着目标进程

二、读取目标函数寄存器值并存档

1、主要操作流程

2、ptrace 函数 PTRACE_GETREGS 读取寄存器值





一、调试进程 ATTACH 附着目标进程


在 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具的 main 函数分析 ) 博客中 , 在 main 函数中获取了 进程号 PID , 下面开始将 SO 动态库注入该 PID 进程号对应的目标进程 ;


ptrace 函数调用的前提是 , 当前应用必须有 root 权限 , 否则调用会失败 ;


首先 , 调用


ptrace(PTRACE_ATTACH, pid, NULL, 0)


函数附着目标进程 , 获取目标进程的控制权 , 传入 PTRACE_ATTACH 参数 ;


具体的 ptrace 函数族的参数 , 参考 【Android 逆向】ptrace 函数 ( ptrace 函数族 | 进程附着 | 进程脱离 | 进程数据读写权限 | 进程对应的主线程寄存器读写 | 单步调试 |ptrace 函数族状态转换 ) 博客 ;


之后 , 需要 阻塞等待 被调试 的 目标进程返回 , 如果目标进程状态变为 WUNTRACED 被调试状态 , 就可以执行下一步的操作 ;


int status = 0;
    /* 等待关联进程结果返回 , 目标进程状态变为 WUNTRACED */
    waitpid(pid, &status, WUNTRACED);



附着目标进程完整代码 :


/* 附着目标进程 */
int ptrace_attach(pid_t pid)
{
    /* attach 关联 要调试的 目标进程 */
    if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0) {
  perror("ptrace_attach");
  return -1;
    }
    int status = 0;
    /* 等待关联进程结果返回 , 目标进程状态变为 WUNTRACED */
    waitpid(pid, &status, WUNTRACED);
    return 0;
}





二、读取目标函数寄存器值并存档



1、主要操作流程


声明两个结构体 , 分别用于寄存器值操作 和 存档 , 存档的结构体一定不要写入数据 , 之后恢复寄存器值时需要用到 ;


/* regs 结构体 用于存储寄存器值
    original_regs 结构体 用于存储寄存器值存档 */
    struct pt_regs regs, original_regs;


之后 , 调用 ptrace_getregs 函数 , 读取目标进程的寄存器值 ;


/* 获取寄存器值 */
    if (ptrace_getregs(target_pid, &regs) == -1)
  goto exit;


最后 , 将寄存器的值存档 ,


/* save original registers 寄存器值存档 */
    memcpy(&original_regs, &regs, sizeof(regs));


寄存器读取存档代码示例 :


/* regs 结构体 用于存储寄存器值
    original_regs 结构体 用于存储寄存器值存档 */
    struct pt_regs regs, original_regs;
    /* 获取寄存器值 */
    if (ptrace_getregs(target_pid, &regs) == -1)
  goto exit;
    /* save original registers 寄存器值存档 */
    memcpy(&original_regs, &regs, sizeof(regs));



2、ptrace 函数 PTRACE_GETREGS 读取寄存器值


在 ptrace_getregs 函数中 , 调用


ptrace(PTRACE_GETREGS, pid, NULL, regs)


方法 , 获取目标进程的寄存器数据 , 传入 PTRACE_GETREGS 参数 ;


具体的 ptrace 函数族的参数 , 参考 【Android 逆向】ptrace 函数 ( ptrace 函数族 | 进程附着 | 进程脱离 | 进程数据读写权限 | 进程对应的主线程寄存器读写 | 单步调试 |ptrace 函数族状态转换 ) 博客 ;


/* 获取寄存器值 */
int ptrace_getregs(pid_t pid, struct pt_regs* regs)
{
    if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) {
  perror("ptrace_getregs: Can not get register values");
  return -1;
    }
    return 0;
}