脱壳学习

前言

古早壳,小白学习脱壳入门,仅供技术交流分享,严禁恶意利用

引入

壳的存在有很多种,以下仅供参考

第一代 DEX整体加密(落地加载) DEX 加密后存于 APK,运行时解密写入磁盘再加载
第二代 DEX内存加载(不落地) DEX 解密后仅存在于内存,不写磁盘
第三代 方法抽取(Method Extraction) 只保留方法壳,真实指令运行时动态还原
第四代 VMP / Java2C / 自定义虚拟机 将 Java 字节码转为自定义字节码或 C 代码

具体实现方式有如下几种:

1.替换 AndroidManifest.xml 中的 Application 为壳的入口;

2.加密原始 DEX 文件(可能存于 assets、lib 或隐藏在 SO 中);

3.使用自定义 ClassLoader 加载解密后的 DEX;

4.插入反调试、反 Hook、反内存 dump 机制;


这里仅作简单介绍复现脱壳流程,其余细节后续专门做笔记

梆梆加固(BangBao/SecShell)

np dex->com/SecShell/SecShell/H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# static fields
.field public static ACFNAME:Ljava/lang/String; = "###ACFNAME###"

.field public static APPNAME:Ljava/lang/String; = "com.yanben.App" #复制这里的入口

.field public static ISMPAAS:Ljava/lang/String; = "###MPAAS###"

.field public static PKGNAME:Ljava/lang/String; = "com.yanben"

.field public static cl:Ljava/lang/ClassLoader;

public class H {
public static String ACFNAME = "###ACFNAME###";
public static String APPNAME = "com.yanben.App";
public static String ISMPAAS = "###MPAAS###";
public static String PKGNAME = "com.yanben";
public static ClassLoader cl;

到AndroidManifest.xml中替换入口

1
2
3
4
5
6
7
<application
android:theme="@style/AppTheme"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:name="com.SecShell.SecShell.AW" //此处
android:debuggable="true"
android:resizeableActivity="true">

这里即应用程序入口,负责dex解密,跟进去看看,特征很明显,跟之前的H对上了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static {
System.loadLibrary("SecShell"); //解密
H.i();
}

try {
if (!"".equals(H.APPNAME)) { //从 H.APPNAME 获取真实 Application 的类名
f2S5I5LIsIOISII0OlsIIS5OIII = (Application) getClassLoader().loadClass(H.APPNAME).newInstance();
}
} catch (Exception unused) {
f2S5I5LIsIOISII0OlsIIS5OIII = null;

public void onCreate() {
m2S5Ill0sIsILIIlOlISLIIS();
super.onCreate();
Application application = f2S5I5LIsIOISII0OlsIIS5OIII; //创建实例
if (application != null) {
H.attach(application, null);
f2S5I5LIsIOISII0OlsIIS5OIII.onCreate();
}
}

样本到此为止,参考链接还有一处特征出现在 AndroidManifest.xml 中

1
2
3
4
5
6
7
8
9
10
<!-- com.secneo.apkwrapper.CP -->
<provider
android:name="com.secneo.apkwrapper.CP" <!--CP 代表 ContentProvider-->
android:exported="false"
android:authorities="com.yanben.CP"
android:initOrder="2147483647" />
<!-- Android 系统启动应用时,会按照 initOrder 从小到大初始化 ContentProvider。
这里的 Provider 会比应用中所有的其他组件(包括 Application 的 onCreate )更早被初始化。
壳利用这个机制,在开发者编写的 Application.onCreate() 执行之前,
就抢先运行解密逻辑、加载 Dex、初始化环境。 -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 示例eg -->
<manifest ...>
<application
android:name="com.SecShell.SecShell.AW"
android:label="@string/app_name"
... >

<!-- 大致在此处 -->
<provider
android:name="com.secneo.apkwrapper.CP"
android:exported="false"
android:authorities="com.yanben.CP"
android:initOrder="2147483647" />

<activity
android:name=".ui.activity.MainActivity"
... >
...
</activity>

</application>
</manifest>

接下来小黑盒脱壳,此样本为32位

https://github.com/CodingGay/BlackDex/releases/tag/v3.2

按dex命名规范重命名,按大小排序替换原dex,hook和cookie有些为重复内容选择删除,这里初解包为一个dex用np合并

adb pull /storage/emulated/0/NP/apks/1.apk D:\CTF\ctftimu\apk_demo

效果如下

腾讯御安全(Tencent Yushou/Tencent Protect)

dex com/wrapper/proxyapplication/WrapperProxyApplication

1
2
3
4
5
6
7
8
9
.field static baseContext:Landroid/content/Context; = null

.field static className:Ljava/lang/String; = ".App" //入口

.field static mLoader:Ljava/lang/ClassLoader; = null

.field static shellApp:Landroid/app/Application; = null

.field static tinkerApp:Ljava/lang/String; = "tinker not support"

androidmanifest.xml

1
2
3
4
5
6
7
<application
android:theme="@style/AppTheme"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:name="MyWrapperProxyApplication" //此处替换
android:debuggable="true"
android:resizeableActivity="true">

blackdex 之后同样套路

百度加固/百度乐固(Baidu Protect)

dex->appinfo

蛮犀加固(Manxi Protect)

dex->com/mx/dA/dpa

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
28
29
30
31
32
33
34
35
36
37
38
.method static constructor <clinit>()V
.registers 1

.line 26
const/4 v0, 0x0

sput-object v0, Lcom/mx/dA/dpa;->app:Landroid/app/Application;

.line 27
const-string v0, ""

sput-object v0, Lcom/mx/dA/dpa;->sCachePath:Ljava/lang/String;

.line 28
sput-object v0, Lcom/mx/dA/dpa;->sApkPath:Ljava/lang/String;

.line 30
const/4 v0, 0x0

sput-boolean v0, Lcom/mx/dA/dpa;->bAlreadyInit:Z

.line 32
const-string v0, "com.yanben.App" //入口

sput-object v0, Lcom/mx/dA/dpa;->sApplicationName:Ljava/lang/String;

.line 33
const-string v0, ""

sput-object v0, Lcom/mx/dA/dpa;->sAppComFactoryName:Ljava/lang/String;

.line 34
const-string v0, "COPYFALSE"

sput-object v0, Lcom/mx/dA/dpa;->CopyToLibs:Ljava/lang/String;

return-void
.end method

xml

1
2
3
4
5
6
7
8
<application
android:theme="@style/AppTheme"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:name="com.mx.dA.dpa" //此处替换
android:debuggable="true"
android:resizeableActivity="true"
android:appComponentFactory="com.mx.dAC.dac"> //此行去除

老套路,这里了解后可以直接删除壳特征相关dex,笔者偷懒全部合并

顶象加固(Dingxiang Protect)

dex->com/security/shell/AppStub1

1
2
3
4
5
6
7
.class public Lcom/security/shell/AppStub1;
.super Landroid/app/Application;
.annotation runtime Lcom/security/mobile/annotation/Config;
app = "com.one.tinker.MyApplication"#这个就是入口
appFactory = "android.support.v4.app.CoreComponentFactory"
versionStr = "dd2d09b486e704b2f124c173fbe65d37"
.end annotation
1
2
3
4
5
6
7
android:icon="@7f0d0005"
android:name="com.security.shell.AppStub1"#复制的入口替换到这里
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:resizeableActivity="false"
android:networkSecurityConfig="@7f120007"
android:appComponentFactory="com.security.shell.AppComponentFactory0"> <--!此行去除-->

BlackDex原理

本质是早期一二代壳dex解密后动态加载到内存然后被dump下来

首先BlackDex会涉及虚拟化技术启动目标app进程,详细源码可阅览参考链接,这里以图表形式方便理解

BlackDex 整体工作流程图



从 Java 层到 Native 内存地址

ART(Android Runtime)概念介绍:

安卓 5.0 及之后版本默认的应用程序运行引擎,它替代了老旧的 Dalvik 虚拟机。其核心职责是将应用的字节码转换为设备可执行的机器码。通过采用混合编译模式(结合安装不编译、运行时即时编译热点代码、空闲时后台预编译),ART 在保证安装速度和节省存储空间的同时,显著提升了应用的启动与运行效率,并优化了内存回收机制

frida-dexdump

也可以直接pip install frida-dexdump:https://github.com/hluwa/frida-dexdump

查壳工具安利:https://github.com/moyuwa/ApkCheckPack

启动frida-server

frida-dexdump -FU

-U usb -F 前端活动app -f com.app.pkgname

在线脱壳

https://56.al/upload.php

https://www.tosks.top/ (需下载)

https://json2.cc/dev/apk_parser

参考链接

https://www.52pojie.cn/forum.php?mod=viewthread&tid=1453091&extra=page%3D1%26filter%3Dtypeid%26typeid%3D343

https://buaq.net/go-167998.html

https://mezdosec.github.io/post/frida-dexdump-tuo-ke-de-zheng-que-zi-shi/


脱壳学习
https://alenirving.github.io/2026/03/09/脱壳学习/
作者
Ma5k
许可协议
CC-BY-NC-SA