Android APK脱壳--腾讯乐固、360加固一键脱壳
概述
现在使用Proguard进行混淆的代码,也很容易被破解,所以就出现了加固工具,让反编译的难度更大。但是有了加固技术,就会有反加固技术,正所谓道高一尺魔高一丈。
经过加固后的apk,通过 dex2jar
反编译:
腾讯乐固:
360加固:
从上面可以看出,经过加固后的apk,通过常规方法反编译无法获取到源码。
下载工具
脱壳工具FDex2
通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。
下载地址:
链接:https://pan.baidu.com/s/1smxtinr 密码:dk4v
VirtualXposed
VirtualXposed:无需root手机即可使用xp框架。
下载地址:
https://vxposed.com/
脱壳
Step1:
将 VirtualXposed
、 FDex2
和需要脱壳的应用都安装到手机上。
Step2:
启动 VirtualXposed
,并在 VirtualXposed
中安装 FDex2
:
Step3:
在 VirtualXposed
中激活 FDex2
:
Step4:
在 VirtualXposed
中安装要脱壳的应用,方法和Step2一样。
Step5:
启动 VirtualXposed
中的 FDex2
,并配置要脱壳的应用。
Step6:
在 VirtualXposed
中运行要脱壳的应用。
Step7:
脱壳后的dex文件:
导出脱壳的dex文件:
root设备:
adb root
adb pull /data/user/0/iv.va.exposed/virtual/data/user/0/{packageName} {电脑上的目录}
未root设备:
在 VirtualXposed
中,设置-->高级设置-->文件管理,安装文件管理器,然后通过文件管理器进入到指定的目录,通过 分享
功能发到电脑上。
Step8:
通过 dex2jar
对 脱壳的dex进行反编译:
从上图就可以看到脱壳后的dex文件被成功的反编译。
FDex2核心代码MainHook
package com.ppma.xposed;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class MainHook implements IXposedHookLoadPackage {
XSharedPreferences xsp;
Class Dex;
Method Dex_getBytes;
Method getDex;
String packagename;
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
xsp = new XSharedPreferences("com.ppma.appinfo", "User");
xsp.makeWorldReadable();
xsp.reload();
initRefect();
packagename = xsp.getString("packagename", null);
XposedBridge.log("设定包名:"+packagename);
if ((!lpparam.packageName.equals(packagename))||packagename==null) {
XposedBridge.log("当前程序包名与设定不一致或者包名为空");
return;
}
XposedBridge.log("目标包名:"+lpparam.packageName);
String str = "java.lang.ClassLoader";
String str2 = "loadClass";
XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class cls = (Class) param.getResult();
if (cls == null) {
//XposedBridge.log("cls == null");
return;
}
String name = cls.getName();
XposedBridge.log("当前类名:" + name);
byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
if (bArr == null) {
XposedBridge.log("数据为空:返回");
return;
}
XposedBridge.log("开始写数据");
String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
XposedBridge.log(dex_path);
File file = new File(dex_path);
if (file.exists()) return;
writeByte(bArr, file.getAbsolutePath());
}
} );
}
public void initRefect() {
try {
Dex = Class.forName("com.android.dex.Dex");
Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void writeByte(byte[] bArr, String str) {
try {
OutputStream outputStream = new FileOutputStream(str);
outputStream.write(bArr);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
XposedBridge.log("文件写出失败");
}
}
}
参考链接
- https://www.52pojie.cn/forum.php?mod=viewthread&tid=758726&fromguid=hot
- https://bbs.pediy.com/thread-224105.htm
- Android:全面解析熟悉而陌生 的 Application 类使用
- ToggleButton和Switch使用大全
- Android 无需权限显示悬浮窗, 兼谈逆向分析 App
- android数据保存之greendao
- CheckBox和RadioButton使用大全
- 关于 Android 实现滑动返回的几种方法总结
- android 面试之listview
- 放yy直播点赞动画
- TableLayout和Viewpager实现切换
- Android 数据库框架ormlite
- SwipeRefreshLayout实现上拉下拉刷新
- 常见Button使用详解
- android Gradle的几个基本概念
- EditText的属性和使用方法
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【深度学习】基于web端和C++的两种深度学习模型部署方式
- 作为DBA,你有必要了解一下tcpdump
- Linux用户管理
- 有赞 GO 项目单测、集成、增量覆盖率统计与分析
- RSA--通过模和指数加密模板--无填充
- 有赞发号器多机房方案
- python爬虫以及后端开发--实用加密模板整理
- APP脱壳方法三
- Flink Checkpoint 原理流程以及常见失败原因分析
- Docker原理之 - OverlayFS设计与实现
- 有赞零售跨平台打印库方案
- [Go] Golang练习项目-GO语言实现快速排序-第一个数作为基准更容易理解
- 有赞移动基础设施建设的实践和思考
- 大数据理论篇HDFS的基石——Google File System
- 6. 二十不惑,ObjectMapper使用也不再迷惑