【Android 逆向】ART 函数抽取加壳 ④ ( 对 libc.so#execve 函数进行内联 HOOK 操作 )

2023-03-30 17:22:18 浏览数 (2)

文章目录

  • 一、对 libc.so#execve 函数进行内联 HOOK 操作

  • 【Android 逆向】ART 函数抽取加壳 ① ( ART 下的函数抽取恢复时机 | 禁用 dex2oat 机制源码分析 )
  • 【Android 逆向】ART 函数抽取加壳 ② ( 禁用 dex2oat 简介 | TurboDex 中禁用 dex2oat 参考示例 )

两篇博客中 , 简单介绍了 禁用 dex2oat 机制 的原理 , 下面开始 实现 dex2oat 禁用功能 ;

在 【Android 逆向】ART 函数抽取加壳 ③ ( 禁用 dex2oat 操作 HOOK 点介绍 | 集成 InLineHook ) 博客中 , 介绍了 HOOK 点 , 以及 集成 HOOK C 代码的库 InLineHook ;

一、对 libc.so#execve 函数进行内联 HOOK 操作


要 HOOK libc 函数库 中的 exec_utils.cc#execve 函数 , 首先要查找到 libc 库的基地址 , 然后查找 exec_utils.cc#execve 函数的地址 ;

execve 函数 定义在 bionic/libc/include/unistd.h 中 , 在 exec_utils.cc 中进行调用 ;

使用 在 【Android 逆向】ART 函数抽取加壳 ③ ( 禁用 dex2oat 操作 HOOK 点介绍 | 集成 InLineHook ) 博客中继承的 InLineHook 函数库 实现上述 native 中的 HOOK 操作 ;

首先 , 调用 hookdlfcndlfcn_compat.h 中的 dlopen_compat 函数 , 传入 libc 库的文件名即 " libc.so " 作为第一个参数 , 传入 RTLD_NOW 作为第二个参数作为标志位 , 该函数的原型如下 :

代码语言:javascript复制
void *dlopen_compat(const char *filename, int flags);

该操作也可以使用 dlopen 函数 , 这里对该函数进行封装 , 是因为在 Android 7.0 之后 , 这些函数都受 命名空间限制 , 对于某些函数库可能执行失败 ;

然后 , 调用 hookdlfcndlfcn_compat.h 中的 dlsym_compat 函数 查找 exec_utils.cc#execve 函数 在 " libc.so " 函数库 中的地址 , 第一个参数是 " libc.so " 函数库的基地址 , 第二个参数是函数名称即 " execve " , 该函数的原型如下 :

代码语言:javascript复制
void *dlsym_compat(void *handle, const char *symbol);

该操作也可以使用 dlsym 函数 , 这里对该函数进行封装 , 是因为在 Android 7.0 之后 , 这些函数都受 命名空间 限制 , 对于某些函数库可能执行失败 ;

再后 , 注册内联 HOOK 操作 , 调用 " hookincludeinlineHook.h " 中定义的 " registerInlineHook " 函数 , 传入的参数含义如下 :

  • uint32_t target_addr 参数 : execve 函数在 " libc.so " 函数库中的地址 ;
  • uint32_t new_addr 参数 : HOOK 后要替换的函数地址 , 使用自定义的函数替代原函数执行 ;
  • uint32_t **proto_addr 参数 : 保存原函数地址 , 用于在新函数中调用原函数 , 实现代理模式 ;
代码语言:javascript复制
enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr);

最后 , 执行内联 HOOK 操作 , 注册完毕后 , 调用 " hookincludeinlineHook.h " 中定义的 " inlineUnHook " 函数 , 传入被 HOOK 的函数地址 , 也就是 exec_utils.cc#execve 函数在 " libc.so " 函数库中的地址 ;

代码语言:javascript复制
enum ele7en_status inlineUnHook(uint32_t target_addr);

执行成功 , 该函数返回 0 , 失败返回其它值 ;

本部分代码示例如下 :

代码语言:javascript复制
// 导入 inLineHook 头文件
extern "C" {
	#include "hook/dlfcn/dlfcn_compat.h"
	#include "hook/include/inlineHook.h"
}

// 注册执行 Hook 操作
void hookLibc() {
	// 查找 libc.so 函数库的基地址
    void *libc_addr = dlopen_compat("libc.so", RTLD_NOW);
    // 查找 execve 在 libc.so 函数库的偏移地址 
    void *execve_addr = dlsym_compat(libc_addr, "execve");
    
    // 地址不为空才能向后执行
    if (execve_addr != NULL) {
    	// 注册内联 Hook 函数 , 传入参数 
    	// ① execve 在 libc.so 函数库的偏移地址 , 
    	// ② 自己实现的 myexecve 函数 
    	// ③ Android 自带的原始的 execve 函数地址
    	// 返回 0 即注册成功 
        if (ELE7EN_OK == registerInlineHook((uint32_t) execve_addr, (uint32_t) myexecve,
                                            (uint32_t **) &android_execve)) {
            // 正式执行 Hook 操作 
            if (ELE7EN_OK == inlineHook((uint32_t) execve_addr)) {
                LOGD("Hook Success");
            } else {
                LOGD("Hook Fail");
            }
        }
    }
}

0 人点赞