在
两篇博客中 , 简单介绍了 禁用 dex2oat 机制 的原理 , 下面开始 实现 dex2oat 禁用功能 ;
在 【Android 逆向】ART 函数抽取加壳 ③ ( 禁用 dex2oat 操作 HOOK 点介绍 | 集成 InLineHook ) 博客中 , 介绍了 HOOK 点 , 以及 集成 HOOK C 代码的库 InLineHook ;
在 【Android 逆向】ART 函数抽取加壳 ④ ( 对 libc.so#execve 函数进行内联 HOOK 操作 ) 博客中 , 对 libc.so#execve 函数 进行了 内联 HOOK 操作 , 可以对该函数进行拦截 ;
本篇博客实现 自定义的 myexecve 函数 替换 libc.so#execve 函数 ;
libc.so#execve 函数 定义在 Android 源码的 " bionic/libc/include/unistd.h " 头文件中 , 函数原型如下 :
int execv(const char* __path, char* const* __argv);
int execvp(const char* __file, char* const* __argv);
int execvpe(const char* __file, char* const* __argv, char* const* __envp) __INTRODUCED_IN(21);
// ★ 此处为 execve 函数原型
int execve(const char* __file, char* const* __argv, char* const* __envp);
源码地址 : http://androidxref.com/8.0.0_r4/xref/bionic/libc/include/unistd.h
" int execve(const char* __file, char* const* __argv, char* const* __envp); " 函数解析 :
在 博客中 , 介绍了调用 " hook\include\inlineHook.h " 中定义的 " registerInlineHook " 函数注册被 Hook 的函数 , 其原型如下 :
enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr);
uint32_t target_addr
参数是 execve 函数在 libc.so 的地址 , uint32_t new_addr
参数是自定义替换 execve 函数执行的函数地址 , uint32_t **proto_addr
参数是 execve 原函数的地址 ;
首先 , 定义一个函数指针变量 , 接收
" int execve(const char* __file, char* const* __argv, char* const* __envp); " 函数
的地址 , 之后如果需要真实调用时需要用到 ;
int ( *android_execve )(const char* __file, char* const* __argv, char* const* __envp);
定义指针 , 指向一个函数 , 函数的参数是 const char* __file, char* const* __argv, char* const* __envp
, 返回值是 int
类型 ;
该函数指针在进行 " hook\include\inlineHook.h " 中定义的 " registerInlineHook " 函数时 被赋值 ;
复杂指针阅读技巧 ( 主要是 区分 函数指针 和 数组指针 ) 右左法则 :
然后 , 定义 自定义的 execve 函数 , 用于 替换 Android 自带的 execve 函数 , 主要用于拦截 dex2oat 字节码文件 ,
源码示例 :
// 用于接收 Android 自带的 execve 函数
int (*android_execve)(const char *__file, char *const *__argv, char *const *__envp);
// 自定义的 execve 函数 , 用于替换 Android 自带的 execve 函数
// 主要用于拦截 dex2oat 字节码文件
int myexecve(const char *__file, char *const *__argv, char *const *__envp) {
// 这里将需要拦截的字节码都放在 dex2oat 目录中
if (strstr(__file, "dex2oat")) {
return 0;
} else {
// 不需要拦截的 , 直接调用原函数执行
return android_execve(__file, __argv, __envp);
}
}