本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78077603
Android应用的so库文件的加固一直存在,也比较常见,特地花时间整理了一下Android so库文件加固方面的知识。本篇文章主要是对看雪论坛《简单的so脱壳器》这篇文章的思路和代码的分析,很久之前就阅读过这篇文章但是一直没有时间来详细分析它的代码,最近比较有空来分析一下这篇文章中提到的Android so脱壳器的代码udog,github下载地址为:https://github.com/devilogic/udog,Android so加固的一般手法就是去除掉外壳Android so库文件的 ELF 链接视图 相关的信息,例如区节头表的偏移、区节头表的项数、区节头表名称字符串表的序号等,这样处理以后将Android so加固的外壳so库文件拖到IDA中去分析的时候,直接提示区节头表无效的错误,IDA工具不能对Android so加固的外壳so库文件进行分析,达到抗IDA工具静态分析的目的。
Android so加固中被保护的Android so库文件是由外壳Android so库文件在.init段或者.init_array段的构造函数里自定linker进行内存加载和解密的,被保护的Android so库文件自定义内存加载、映射完成以后将外壳Android so库文件的soinfo*(dlopen函数返回的)修改为被保护Android so库文件的soinfo*,这样被保护的Android so库文件的内存加载就成功了并且就可以被调用了。尽管被加固保护的Android so库文件被加密保护起来了,但是该Android so库文件还是会在内存中进行解密出来,因此我们可以在被加固保护的Android so库文件内存解密时进行内存dump处理,然后对dump出来的Android so库文件进行ELF文件格式的调整和修复以及section区节头表的重建,就可以实现被保护的Android so库文件的脱壳了。
简单so脱壳器这篇文章中提到的so脱壳器udog的代码比较简单,之前以为udog的代码比较复杂,后来整理了一下作者玩命的代码发现很多代码都是废弃的,核心关键的代码部分不是很复杂但是对于学习Android so加固的脱壳很有作用,也是Android so加固脱壳和内存dump后修复的第一步,玩命版主主要实现了被加固Android so库文件的内存dump和ELF文件格式部分参数的修复处理,对于脱壳后ELF文件的section区节头表等的重建并没有实现。
udog代码的入口 main函数 在linker.cpp文件中如下图所示:
在linker.cpp文件中,main函数工作流程是: 先对用户输入的命令行参数进行解析处理得到 用户参数解析结果描述结构体options_t,然后根据用户输入的命令参数解析的结果options_t 进行Android so的脱壳相关的操作。udog脱壳器中帮助命令行在文件options.cpp中实现,如下图所示:
用户输入的命令行参数解析结果保存结构体options_t中,如下图代码所示:
// 保存用户输入命令行参数的解析结果
struct options_t {
bool call_dt_init;
bool call_dt_init_array;
bool call_dt_finit;
bool call_dt_finit_array;
bool load_pre_libs;
bool load_needed_libs;
bool load;
bool not_relocal; /* 不对重定位表进行修复 */
bool make_sectabs; /* 重建elf文件的区节头表 */
bool dump;
bool help;
bool version;
bool debug;
bool check;
bool clear_entry;
int debuglevel;
unsigned xct_offset;
unsigned xct_size;
char dump_file[128];
char target_file[128];
};
对用户输入的命令行参数进行解析处理的操作在函数handle_arguments中实现,如下图代码所示:
// main函数在linker.cpp类
int main(int argc, char* argv[]) {
// 解析用户输入的命令行参数
g_opts = handle_arguments(argc, argv);
// 解析用户输入的命令行参数
struct