第十二章 软件壳(三)(动态加载型壳)

本文详细介绍了Android动态加载型壳的脱壳方法,包括缓存脱壳法、内存Dump脱壳法、动态调试脱壳法、Hook脱壳法和系统定制脱壳法。针对DEX的加载和优化过程,分析了各种脱壳时机,讨论了如何利用调试器、Hook框架及系统定制来实现自动化脱壳。
摘要由CSDN通过智能技术生成

动态加载型壳

  • 即第一代壳
  • 其发展时期正是从 Android 4.4 向 Android 5.0 迈进的从 Dalvik 虚拟机向 ART 虚拟机转型时期
  • 这一时期的软件壳,早期版本主要针对 Dalvik 虚拟机的实现,特点是对本地 APK 中的数据加密,运行时在内存中解密

缓存脱壳法

  • 动态加载型壳用 DexClassLoader 方式将加密后的 DEX 在内存中解密后动态加载,但一些软件壳没有处理 DEX 优化时缓存的路径,最终使得系统执行 dexopt 命令对加载的 DEX 进行优化时,将优化结果放到默认的 /data/dalvik-cache 目录,因此只要将此目录下的 ODEX 取出,进行一次 deodex 操作,即可完成脱壳

内存 Dump 脱壳法

  • 因第一代壳在内存中完全解密,可从内存中 Dump 要解密 APK 的内存,完成脱壳

  • 脱壳工具:android-unpacker

  • 其核心是通过 find_magic_memory() 读取 /proc/pid/maps 内存映射表,找到 DEX 所在的内存起始位置,通过 dump_memory() 将内存 Dump

    int find_magic_memory(uint32_t clone_pid, int memory_fd, memory_region* memory[], char* extra_filter) {
         
        char maps[1024];
        snprintf(maps, sizeof(maps), "/proc/%d/maps", clone_pid);
     
        FILE* maps_file = NULL;
        if ((maps_file = fopen(maps, "r")) == NULL)
            return -1;
     
        char mem_line[1024];
        int found = 0;
        while (fscanf(maps_file, "%[^\n]\n", mem_line) >= 0) {
         
            if (extra_filter != NULL && strstr(mem_line, extra_filter) == NULL)
                continue;
     
            if (extra_filter == NULL && (strstr(mem_line, "/") != NULL || strstr(mem_line, "[") != NULL))
                continue;
     
            char mem_address_start[10];
            char mem_address_end[10];
            sscanf(mem_line, "%8[^-]-%8[^ ]", mem_address_start, mem_address_end);
     
            uint64_t mem_start = strtoul(mem_address_start, NULL, 16);
     
            off64_t offset = peek_memory(memory_fd, mem_start);
     
            if (extra_filter != NULL && offset < 0)
                offset = 0;
     
            if (offset >= 0) {
         
                memory[found] = malloc(sizeof(memory_region));
                memory[found]->start = mem_start + start;
                memory[found++]->end = strtoull(mem_address_end, NULL, 16);
            }
            else if (offset == -99) {
         
                // No offset found
            }
            else {
         
                perror(" [!] Error peeking at memory ");
            }
        }
        fclose(maps_file);
        return found;
    }
    int dump_memory(char* class_path, int memory_fd, memory_region* memory, const char* file_name, int ignore_class_path) {
         
        int ret 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值