Android 逆向ART 函数抽取加壳 ⑤ ( unistd.h#execve 函数分析 | 使用自定义的 myexecve 函数替换 libc.so#execve 函数 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向ART 函数抽取加壳 ⑤ ( unistd.h#execve 函数分析 | 使用自定义的 myexecve 函数替换 libc.so#execve 函数 )相关的知识,希望对你有一定的参考价值。

文章目录


两篇博客中 , 简单介绍了 禁用 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 函数 ;





一、bionic/libc/include/unistd.h#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); " 函数解析 :

  • const char* __file 参数 : 表示要运行的 二进制程序文件路径 , 这里指的是 Dex 字节码文件路径 , 如果要拦截 指定路径中的字节码文件不进行 OAT 优化 , 可以再此处进行过滤 , 检测到某个文件路径 , 直接返回空不执行任何代码逻辑 ;




二、使用自定义的 myexecve 函数替换 libc.so#execve 函数



在 博客中 , 介绍了调用 " 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 " 函数时 被赋值 ;


复杂函数指针参考博客 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读) 六. 函数指针 3. 解读 复杂的 指针声明 ( 难点 重点 | ①找出中心标识符 ②先右 后左 看 确定类型 提取 ③ 继续分析 左右看 … ) 进行分析 ;


复杂指针阅读技巧 ( 主要是 区分 函数指针 和 数组指针 ) 右左法则 :

  • 1.最里层标示符 : 先找到最里层的圆括号中的标示符;

    数组指针和函数指针的标示符 ( 指针变量名 ) 都在中间的圆括号中, 因此该步骤先找到指针变量名

  • 2.右左看 : 先往右看, 再往左看 ;

  • 3.确定类型 : 遇到 圆括号 “()” 或者 方括号 “[]” 确定部分类型, 调转方向 ; 遇到 * 说明是指针 , 每次确定完一个类型 , 将该类型提取出来 , 分析剩下的 ;

    一种可能性 :
    int (*) [5] , 遇到中括号说明是数组指针类型,
    int(*)(int, int) , 遇到圆括号 说明是函数指针类型 ;

  • 4.重复 2 , 3 步骤 : 一直重复, 直到 指针 阅读结束 ;


然后 , 定义 自定义的 execve 函数 , 用于 替换 Android 自带的 execve 函数 , 主要用于拦截 dex2oat 字节码文件 ,

  • 这里将需要拦截的字节码都放在 dex2oat 目录中 , 检测到 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);
    

以上是关于Android 逆向ART 函数抽取加壳 ⑤ ( unistd.h#execve 函数分析 | 使用自定义的 myexecve 函数替换 libc.so#execve 函数 )的主要内容,如果未能解决你的问题,请参考以下文章

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

Android 逆向ART 函数抽取加壳 ③ ( 禁用 dex2oat 操作 HOOK 点介绍 | 集成 InLineHook )

Android 逆向ART 函数抽取加壳 ( ART 下的函数抽取恢复时机 | 禁用 dex2oat 机制源码分析 )

Android 逆向ART 函数抽取加壳 ② ( 禁用 dex2oat 简介 | TurboDex 中禁用 dex2oat 参考示例 )

Android 逆向加壳技术识别 ( 函数抽取 与 Native 化加壳的区分 | VMP 加壳与 Dex2C 加壳的区分 )

Android 逆向脱壳解决方案 ( DEX 整体加壳 | 函数抽取加壳 | VMP 加壳 | Dex2C 加壳 | Android 应用加固防护级别 )