Android脱壳

1.简介

以frida工具为基础,整理加密的Android应用脱壳技术,以及简单地修复方法。

WEB系统:代码主要运行在后端服务器

安卓APP:客户端和后端服务器均运行代码

故想要对APP客户端进行完整的分析,则需要对其进行脱壳,获得源码。

2.脱壳思路

  • HOOK删除方法(获得的类最为准确)
  • Dump内存中的类(获得的类较为精准)
  • HOOK ClassLinkerDefineClass 方法(获得的类包含了非目标app的类)

2.1HOOK删除方法

加壳APP运行前会将apk解密运行后删除,故捕获被删除的文件即可获得未加密的apk

安卓中删除方法有java.io.Filedelete方法和native层的unlink

1
2
3
4
5
6
7
8
9
10
11
12
13
//delete.js
//HOOK delete方法,不执行删除,仅仅获取被删除文件的路径并打印在日志里
Java.perform(function(){
var f = Java.use("java.io.File");
f.delete.implementation=function(){
var path = this.getAbsolutePath();
console.log(`[+] Delete catached => ${path}`);
return true;
}
})

//frida -U -l ./delete.js -f com.xxx.xxx
//com.xxx.xxx为app包名

image-20240310101102247

1
2
3
4
5
6
7
8
9
10
11
//unlink.js
//HOOK native层 unlink方法,使用Interceptor.replace替换unlink方法,不执行删除,仅仅获取被删除文件的路径并打印在日志里

var unlinkPtr = Module.findExportByName(null,"unlink");
Interceptor.replace(unlinkPtr,new NativeCallback(function(path){
console.log(`[+]unlink:${path.readCString()}`);
return 0;
},'int',['pointer']));

//frida -U -l ./unlink.js -f com.xxx.xxx
//com.xxx.xxx为app包名

image-20240310101033577

2.2Dump内存中的类

对加载到内存中的类进行捕获。

2.2.1自动化工具使用

1
2
3
4
5
//前置需要安装frida
//安装方法为 pip3 install frida && pip3 install frida-tools
pip3 install frida-dexdump
//com.xxx.xxx为目标app包名
frida-dexdump -U -f com.xxx.xxx

2.2.2手动dump

1
2
3
adb shell
//进入adb shell,使用命令找到运行app的pid,其中"xxx"是指的APP包名
# ps -A | grep -i "xxx"

image-20240310095235660

1
2
//根据找到的pid寻找maps中的dex文件
# cat /proc/{pid}/maps | grep -i "dex"

image-20240310101346798

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//dump.js
//硬编码对应的地址,不要关闭app,使用frida直接附加上去获取目标apk
//var starAddress = ptr(0x6eb16cb000);
//var endAddress = ptr(0x6eb32da000);

var starAddress = ptr(0x6eb16cb000);
var endAddress = ptr(0x6eb32da000);
var size = endAddress.sub(starAddress);
console.log(`[+] Dumping memory region ${starAddress} : ${endAddress}`);

var buffer = Memory.readByteArray(starAddress,parseInt(size,16));

var filePath = "/data/local/tmp/"+starAddress+"_dump.dex";
var fileHande = new File(filePath,"wb");

if(fileHande && fileHande!=null){
fileHande.write(buffer);
fileHande.flush();
fileHande.close();
console.log(`[*] File successfully dumped at ${filePath}`);
}

//frida-ps -Ua 查看目标app进程名
//frida -U -l ./dump.js 目标app进程名
//此处因为硬编码了地址,重新运行地址会变

//结果在/data/local/tmp/ 找 _dump.dex结尾的

2.3HOOK ClassLinkerDefineClass 方法

使用已有的frida脚本项目对目标进行dump

1
2
3
4
git clone  https://github.com/lasting-yang/frida_dump.git
cd frida_dump
frida -U -l dump_dex.js -f com.xxx.xxx
//com.xxx.xxx为目标包名

image-20240310101820442

3.简单修复

修复工具-MT管理器

3.1满足静态分析工具(步骤做完即可用jd或者jadx进行分析)

对加壳的apk内部的classes.dex进行重命名,并且解压到左边脱壳的部分

image-20240310102348374

全选所有的dex文件进行dex修复

image-20240310102117343

批量进行重命名,并将第一个classes1.dex更名为classes.dex,满足正常的dex命名规则

image-20240310102616047

将命名好的dex文件放回apk内

image-20240310102844877

将app的dex重新划分

image-20240310103042616

3.2 去除so层

此处以数字壳 jiagu 为例(旧版可用,新版不一定行)

将libjiagu.so 和 libjiagu_x86.so改为libxxxxx.so libxxxxx_x86.so

jiagu有五个字母,xxxxx可改为任意字符

此处用libxxxxx.so

image-20240310103950120

image-20240310104033222

将so文件里的所有jiagu都改为xxxxx

image-20240310104407472

如果需要正常运行,还需要考虑签名校验,后续可采用frida hook内部签名校验方法进行绕过。

参考:

How to Unpack Protected Android APK with Frida (youtube.com)

https://www.youtube.com/watch?v=FeJuxRQUVnU

https://github.com/lasting-yang/frida_dump