记录一次成功反混淆脱壳及抓包激活app全过程

App脱壳抓包及激活的全过程记录
本文记录了对公司旧app进行脱壳抓包的全过程。因原代码丢失、激活服务器停用,需脱壳查看源码并修改激活。作者先后使用apktools等工具反编译,借助夜神模拟器,安装xposed、adb等软件,用dexdump和blackdex脱壳,修复dex文件,最后用Fiddler抓包修改请求激活app。
部署运行你感兴趣的模型镜像

前言

​ 近期接到一个需求,要对公司之前开发的一款app进行脱壳。因为该app是两年前开发的,源代码文件已经丢失,只有加壳后的apk文件,近期要查看其中一项功能的源代码,因此需要尝试进行脱壳处理,反编译后发现该app是使用某数字公司的加壳工具进行混淆加壳的。此外,该app是给特定平板使用的,需要激活码进行激活才能使用,而原激活码服务器已经停止运行,只能通过抓包修改激活码服务器地址进行激活。该文档记录了我成功脱壳抓包的全过程。

​ 我尝试的Xposed框架的工具均无效,使用IDA查看底层代码后发现JNI经过包装,修改难度较大,最终通过blackdex及frida框架的dexdump成功抓取dex文件。

​ 注意:软件必须激活能正常使用才能进行抓取dex文件。

1、使用apktools、dex2jar、jd-gui进行反编译,查看文件源码

这三种反编译工具的使用请自行查看相关教程:https://blog.youkuaiyun.com/helloc888/article/details/106712649?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-106712649-blog-123085977.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-106712649-blog-123085977.pc_relevant_default&utm_relevant_index=2。其实使用jadx也可以查看源码,但开始我没有使用jadx查看,而是使用这三种工具。

查看文件源码后发现该apk经过360加固混淆,无法查看相关源码,因此开始本次脱壳之路。

2、下载安装夜神模拟器,并配置

夜神模拟器下载:夜神安卓模拟器-安卓模拟器电脑版下载_安卓手游模拟器_手机模拟器_官网

由于手上没有用于测试的平板,因此安装夜神模拟器进行脱壳测试。通过网址下载安装即可,注意:电脑要在主板设置中开启VT,加快模拟器运行速度。

下载安装完成后,进入夜神模拟器并进行初步配置。文件管理、设置等都在工具文件夹中。

文件同步路径查看,文件同步类似于docker中的文件挂载,在该文件夹中的文件,模拟器和电脑都可以访问,需要传到电脑的文件直接放到该文件夹下就不用导出,导出也是导出到该文件夹下😂

在右上角 设置/基础 中开启root权限

3、安装可能需要使用的软件

3.1、安装xposed

如果需要xposed框架,那么直接在搜索栏中搜索xposed并安装,授予root权限

打开安装好的xposed软件,安装xposed框架

需要使用该框架时,则在左上角选项卡中的模块一栏运行相关脱壳软件即可

3.2、安装终端模拟器

模拟器中需要使用linux命令进行授权等操作的话,则要安装终端模拟器apk,使用adb其实也可以不用安装

安卓终端模拟器apk下载:Terminal Emulator for Android | F-Droid - Free and Open Source Android App Repository

使用这款模拟器主要是支持中文输入,可以查找中文文件进行相关操作,可以不安装F-Droid,只安装终端模拟器,个人推荐

建议使用本机下载apk后,使用夜神模拟器安装功能进行安装,使用夜神模拟器中的浏览器进行下载安装软件会出现失败的情况

模拟器操作与linux常用操作相同,su切换管理员

3.3、安装adb

Adb是Android Debug Bridge的简称,是一个Android调试工具

adb下载地址:https://dl.google.com/android/repository/platform-tools-latest-windows.zip,下载后解压即可使用,配置环境变量(此电脑→属性→高级系统设置→环境变量→Path(系统变量)→新建(添加adb绝对路径之后确定)),以便可以系统全局使用

查看adb版本

使用adb连接模拟器并查看连接设备

3.4、安装frida及frida-server

在cmd中通过命令行安装frida:

pip install frida
pip install frida-tools

查看frida版本及安卓设备版本

frida-server下载网址:https://github.com/frida/frida/releases,根据查到的安卓版本及frida版本到该网址下载对应的frida-server文件

下载frida-server后解压并安装到模拟器中:

adb push C:\Users\admin\Downloads\frida-server-16.0.1-android-x86 /data/local/tmp/frida-server-16.0.1-android-x86
adb shell 
su
cd /data/local/tmp
chmod 755 frida-server-16.0.1-android-x86
./frida-server-16.0.1-android-x86 &

frida-server运行成功界面:

测试frida-server安装成功:

4、开始脱壳

本次脱壳尝试了多种dexdump方法,最后有效的有两种:dexdump和blackdex

4.1、安装FRIDA-DEXDump

FRIDA-DEXDump项目地址:GitHub - hluwa/frida-dexdump: A frida tool to dump dex in memory to support security engineers analyzing malware.

通过命令行安装:

pip3 install frida-dexdump

使用dexdump抓取加壳app的dex文件:

frida-dexdump -U -f com.app.pkgname

需要开启执行抓取命令后,在模拟器中需要脱壳的安装好的app,运行成功界面:

4.2、下载BlackDex文件

BlackDex项目地址:https://github.com/CodingGay/BlackDex,下载地址:https://github.com/CodingGay/BlackDex/releases,下载apk安装到模拟器即可。

下载界面:

运行界面:

运行成功:

需要脱壳的应用无需运行,该项目通过虚拟化技术将程序运行,初始化Application,启动成功后调用handleDumpDex核心方法来dump内存中的dex文件

5、抓取到的dex文件修复

安装MT管理器:MT管理器

同样使用本机下载apk,安装到模拟器中,使用MT管理器修复抓取到的dex文件。MT还有很多其他的实用功能可以使用,在这里没有用到所以不再详述。

6、使用jadx查看修复后的项目,进行反混淆后保存

jadx项目地址:https://github.com/skylot/jadx,下载后解压即可使用,需要配置环境变量跟上文中类似

在cmd中输入jadx-gui即可运行jadx的gui界面

在jadx中打开脱壳并修复后的dex文件

进行反混淆操作后,在 文件→全部保存 中保存全部项目文件

查看保存后的项目代码示例

7、Fiddler抓包并修改请求激活app

Fiddler是一款强大的抓包软件,可以对拦截到的包进行修改后在将修改后的请求发出

我们要脱壳的是我们几年之前开发的app,当时的服务器已经停止运行了,所以要修改服务器地址进行激活app

Fiddler下载:https://www.telerik.com/fiddler/fiddler-everywhere,下载后正常安装即可(正版有10天试用期足够了)。

夜神模拟器开启网桥模式

通过ipconfig查看本机IP,修改夜神模拟器wlan代理(长按WiredSSID)为手动,并设置主机名为本机IP,端口为8888(fiddler默认端口),保存

访问本机IP+端口8888下载证书并保存到模拟器中:

运行界面(已经可以抓到夜神模拟器的请求):

fiddler右上角设置中打开HTTPS抓包,并忽略服务认证错误:

新建拦截规则,拦截到包含目标url的包并替换替换为新的服务器url地址:

修改完后软件可以正常运行

注意:我们只要获取源码即可,不需要回编为app,回编为app还需要打开dex文件详细查看并删除libjiagu、stub等文件,过签重命名修改文件等操作,详情可参考该文章:https://www.52pojie.cn/thread-1453091-1-1.html。

作者:wangyudong

出处:wydilearn - 博客园

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

<think>我们讨论的是AndroidAPP脱壳技术。在Android安全领域,脱壳是指从加壳的APP中还原出原始DEX文件的过程。加壳是为了保护APP不被逆向分析,而脱壳则是逆向分析的关键步骤。常见的加壳技术:1.动态加载:将原始DEX加密后存放在assets或其它目录,运行时解密并加载。2.类抽取:将DEX中的关键方法代码移除,在运行时动态恢复。3.VMP保护:将方法转换为自定义的指令集,在私有虚拟机中执行。脱壳的常见方法:1.**内存Dump脱壳**:在APP运行时,从内存中提取解密后的DEX文件。2.**动态调试脱壳**:通过调试器在关键点(如解密后、加载前)提取DEX。3.**Hook框架脱壳**:使用Xposed、Frida等Hook框架拦截类加载器,获取解密后的DEX。4.**定制ROM脱壳**:修改Android系统源码,在DEX加载时自动dump。下面以内存Dump脱壳为例,给出一个简单的实现思路(需要root权限):###内存Dump脱壳代码示例```javaimportjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.lang.reflect.Method;importjava.nio.ByteBuffer;importjava.util.ArrayList;publicclassDexDumper{publicstaticvoiddump(){try{//获取当前应用的ClassLoaderClassLoaderclassLoader=DexDumper.class.getClassLoader();//通过反射获取BaseDexClassLoader中的pathList字段Class<?>baseDexClassLoader=Class.forName("dalvik.system.BaseDexClassLoader");ObjectpathList=getField(baseDexClassLoader,"pathList",classLoader);//获取DexPathList中的dexElements数组Class<?>dexPathList=Class.forName("dalvik.system.DexPathList");Object[]dexElements=(Object[])getField(dexPathList,"dexElements",pathList);//遍历dexElementsArrayList<File>dexFiles=newArrayList<>();Class<?>dexElement=Class.forName("dalvik.system.DexPathList$Element");for(Objectelement:dexElements){//获取Element中的dexFile字段ObjectdexFile=getField(dexElement,"dexFile",element);//获取DexFile中的mCookie字段(在Android8.0之前是int,之后是long)Objectcookie=getField(dexFile,"mCookie",dexFile);//获取DexFile中的mFileName字段StringfileName=(String)getField(dexFile,"mFileName",dexFile);//通过mCookie获取内存中DEX的字节数据byte[]dexBytes=getDexBytes(cookie);//保存到文件FileoutputFile=newFile("/sdcard/dump/"+newFile(fileName).getName());FileOutputStreamfos=newFileOutputStream(outputFile);fos.write(dexBytes);fos.close();dexFiles.add(outputFile);}}catch(Exceptione){e.printStackTrace();}}privatestaticObjectgetField(Class<?>clazz,StringfieldName,Objectobject)throwsException{java.lang.reflect.Fieldfield=clazz.getDeclaredField(fieldName);field.setAccessible(true);returnfield.get(object);}//根据Android版本适配获取DEX字节数据privatestaticbyte[]getDexBytes(Objectcookie)throwsException{if(cookieinstanceofLong){//Android8.0+MethodgetBytesMethod=Class.forName("dalvik.system.DexFile").getDeclaredMethod("getDexBytes",long.class);getBytesMethod.setAccessible(true);return(byte[])getBytesMethod.invoke(null,cookie);}elseif(cookieinstanceofInteger){//Android7.0-MethodgetBytesMethod=Class.forName("dalvik.system.DexFile").getDeclaredMethod("getDexBytes",int.class);getBytesMethod.setAccessible(true);return(byte[])getBytesMethod.invoke(null,cookie);}else{thrownewRuntimeException("Unsupportedcookietype:"+cookie.getClass());}}}```注意:1.此代码需要在加壳APP的进程内执行(如通过注入或Hook框架)。2.需要处理不同Android版本的差异(如mCookie类型变化)。3.需要root权限写入/sdcard目录。###防护措施为了防止被脱壳,加固厂商会采用以下防护手段:1.**反内存Dump**:检测内存访问,加密内存中的DEX。2.**反调试**:使用ptrace检测、轮询检查调试状态。3.**代码混淆**:对关键代码进行混淆,增加分析难度。4.**环境检测**:检测root、Xposed、Frida等环境。###§§相关问题§§:1.什么是Android的DEX文件?2.加壳技术中的类抽取是如何实现的?3.如何检测应用是否运行在Xposed环境中?4.Frida工具在脱壳过程中起什么作用?</think>### Android APP 脱壳技术与防护策略详解 #### 核心脱壳技术原理 脱壳是指从加固保护的 APK 中提取原始 DEX 文件的过程。主要技术原理: 1. **内存 Dump 技术**: - 在运行时从内存中提取解密后的 DEX - 关键时机:`ClassLoader` 加载 DEX 后、`Application` 初始化时 2. **动态加载拦截**: - 通过 Hook `DexClassLoader` 或 `PathClassLoader` 获取解密后的字节码 - 使用 Xposed/Frida 等框架拦截加载过程 3. **指令级重建**: - 对 VMP(虚拟机保护)方案,通过分析自定义指令集重建原始代码 #### 脱壳实战代码示例(需 Root) ```java // 内存 DEX 提取工具 public class DexDumper { public static void dumpDex(ClassLoader loader) { try { // 反射获取 DexElements Class<?> pathClass = Class.forName("dalvik.system.DexPathList"); Field dexElementsField = pathClass.getDeclaredField("dexElements"); dexElementsField.setAccessible(true); // 获取当前 ClassLoader 的 PathList Class<?> baseLoader = Class.forName("dalvik.system.BaseDexClassLoader"); Field pathListField = baseLoader.getDeclaredField("pathList"); pathListField.setAccessible(true); Object pathList = pathListField.get(loader); // 遍历所有 DexFile Object[] dexElements = (Object[]) dexElementsField.get(pathList); for (Object element : dexElements) { // 获取 DexFile 对象 Field dexFileField = element.getClass().getDeclaredField("dexFile"); dexFileField.setAccessible(true); Object dexFile = dexFileField.get(element); // 提取内存 DEX 数据 if (dexFile != null) { Method getDexMethod = dexFile.getClass().getDeclaredMethod("getDex"); getDexMethod.setAccessible(true); Object dex = getDexMethod.invoke(dexFile); // 获取字节数组 Field bytesField = dex.getClass().getDeclaredField("bytes"); bytesField.setAccessible(true); byte[] dexBytes = (byte[]) bytesField.get(dex); // 保存到文件 saveDex(dexBytes); } } } catch (Exception e) { e.printStackTrace(); } } private static void saveDex(byte[] data) { String fileName = "dump_" + System.currentTimeMillis() + ".dex"; try (FileOutputStream fos = new FileOutputStream("/sdcard/" + fileName)) { fos.write(data); Log.i("DEX_DUMP", "DEX saved to: " + fileName); } catch (IOException e) { Log.e("DEX_DUMP", "Save failed", e); } } } // 在 Application 中调用 public class MyApp extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); DexDumper.dumpDex(getClassLoader()); } } ``` #### 主流加固方案对抗策略 | 加固类型 | 脱壳方法 | 防护手段 | |----------------|----------------------------------|------------------------------| | 第一代壳 | 内存 Dump | 反调试检测 | | 类抽取壳 | 动态加载时 Hook | 方法执行时解密 | | VMP 虚拟化保护 | 指令跟踪重建 | 自定义指令集+代码混淆 | | Java2C | IDA 反编译分析 | LLVM 编译优化 | #### 高级防护方案(防脱壳) 1. **内存加密技术**: ```java // 关键类内存加密 public class SecureClassLoader extends DexClassLoader { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] encrypted = loadEncryptedClass(name); byte[] decrypted = decrypt(encrypted); // 动态解密 return defineClass(name, decrypted, 0, decrypted.length); } // 立即清除内存中的解密数据 private void cleanMemory(byte[] data) { Arrays.fill(data, (byte) 0); } } ``` 2. **反调试机制**: ```java // 多线程轮询检测调试器 new Thread(() -> { while (true) { if (Debug.isDebuggerConnected()) { System.exit(0); // 强制退出 } try { Thread.sleep(3000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }).start(); ``` 3. **运行时完整性校验**: ```java public class IntegrityCheck { public static void verify() { String realHash = "a3f5d9..."; // 正确哈希值 String currentHash = calculateClassHash(MainActivity.class); if (!realHash.equals(currentHash)) { triggerSelfDestruct(); } } private static void triggerSelfDestruct() { // 1. 删除关键数据 // 2. 通知服务器封禁设备 // 3. 使APP崩溃 throw new RuntimeException("Security breach detected"); } } ``` #### 脱壳检测与响应 ```java public class AntiDumpMonitor { // 检测常见脱壳工具特征 public static boolean detectDumpTools() { // 检查调试端口 if (new File("/proc/net/tcp").exists()) { try (BufferedReader br = new BufferedReader(new FileReader("/proc/net/tcp"))) { String line; while ((line = br.readLine()) != null) { if (line.contains(":5D8A")) { // Frida默认端口 return true; } } } catch (IOException ignore) {} } // 检查Xposed框架 try { Class.forName("de.robv.android.xposed.XposedBridge"); return true; } catch (ClassNotFoundException e) { return false; } } // 响应处理 public static void onDetect() { // 延迟触发反制措施 new Handler(Looper.getMainLooper()).postDelayed(() -> { Runtime.getRuntime().exit(0); }, 5000); } } ``` ### 防护体系设计要点 1. **分层防御架构**: - 外层:代码混淆 + 签名校验 - 中层:运行时环境检测 + 反调试 - 内层:内存加密 + 自毁机制 2. **动态更新策略**: - 定期更换加密算法 - 服务器下发防护策略更新 3. **敏感操作分离**: - 核心算法放入 JNI - 关键验证逻辑放在服务端 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值