Android 动态加载(防止逆向编译) jar混淆加密
最近工作中接到了一个研究防止逆向编译的任务.研究了几天资料,最后基本实现了防破解技术,在这个工程中,也略有一些心得体会,现整理下来分享,供大家探讨参考研究。文中如有纰漏、失实之处,请大家及时给与指正。
防破解技术主要有四种实现方式:1.代码混淆(ProGuard)技术 2.签名比对技术 3.NDK .so 动态库技术 4.动态加载技术.
参考资料:http://bbs.pediy.com/showthread.php?t=137112
第一种 代码混淆技术(ProGuard) 该技术主要是进行代码混淆,降低代码逆向编译后的可读性,但该技术无法防止加壳技术进行加壳(加入吸费、广告、病毒等代码),而且只要是细心的人,依然可以对代码依然可以对代码进行逆向分析,所以该技术并没有从根本解决破解问题,只是增加了破解难度。
第二种 签名比对技术 该技术主要防止加壳技术进行加壳,但代码逆向分析风险依然存在。而且该技术并不能根本解决被加壳问题,如果破解者将签名比对代码注释掉,再编译回来,该技术就被破解了。
第三种 NDK .so动态库技术,该技术实现是将重要核心代码全部放在C文件中,利用NDK技术,将核心代码编译成.so动态库,再用JNI进行调用。该技术虽然能将核心代码保护起来,但被加壳风险依然存在。
第四种 动态加载技术 该技术在Java中是一个比较成熟的技术,而Android中该技术还没有被大家充分利用起来。该技术思想主要分为以下几步:
1.将核心代码编译成dex文件的Jar包 --> 2. 对jar包进行加密处理 3.在程序主入口利用NDK进行解密 4再利用ClassLoader将jar包进行动态加载.5.利用反射技术将ClassLoader 设置成系统的ClassLoader。
该技术可以有效的防止逆向分析、被破解、被加壳等问题。
主要优点有:
1.核心代码在被加密的jar中,所以破解者无法解压出class文件,如果加密秘钥被破解者拿到,那将是另外一层面的安全问题了。
2.该技术也可以有效防止加壳技术,代码是动态加载上来的,破解者的壳程序无法加入到已加密的jar包中,及时破解者注入壳程序入口,壳程序因为不在ClassLoader 的jar包中,所以也无法被执行起来,除非破解者替换ClassLoader的jar包,关掉NDK解密代码.但这种安装到手机上,已经不在是我们的应用,用户一定会将其卸载掉。
所以综合起来比较,第四种动态加载技术是最安全的,但效率问题,本人并没做严格测试,粗略实验了一下,效率并没有明显降低。
现将研究过程的技术节点分享给大家:
1.Jar包加密
// 加密解密文件//
public static boolean enOrDecryptFile(byte[] paramArrayOfByte,
String sourceFilePath, String destFilePath,int mode){
File sourceFile = new File(sourceFilePath);
File destFile = new File(destFilePath);
CipherOutputStream cout = null;
FileInputStream in = null;
FileOutputStream out = null;
if (sourceFile.exists() && sourceFile.isFile()) {
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
try {
destFile.createNewFile();
in = new FileInputStream(sourceFile);
out = new FileOutputStream(destFile);
// 获取密钥//
init();
SecretKeySpec secretKeySpec = new SecretKeySpec(defPassword, "AES");
Cipher cipher;
cipher = Cipher.getInstance("AES");
cipher.init(mode, secretKeySpec);
cout = new CipherOutputStream(out, cipher);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
cout.write(cache, 0, nRead);
cout.flush();
}
}catch (IOException e) {
e.printStackTrace();
return false;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return false ;
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return false ;
}catch (InvalidKeyException e) {
e.printStackTrace();
return false;
}finally{
if(cout != null){
try {
cout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
return false;
}
2.jar用SDK\platform-tools\下的dx命令进行dex格式转化:命令如下:
dx --dex --output=生成的目标文件的地址(绝对路径) 需要转化的jar文件(绝对路径)
例如:dx --dex --output=H:\classdex.jar H:\mainwidget.jar
3.再用加密工具将生成jar文件进行加密
4.代码动态加载:
File file = new File("/data/data/" + base.getPackageName() + "/.cache/");
if (!file.exists()) {
file.mkdirs();
}
try {
Runtime.getRuntime().exec("chmod 755 " + file.getAbsolutePath()).waitFor();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Util.copyJarFile(this);
Object currentActivityThread = RefInvoke.invokeStaticMethod(
"android.app.ActivityThread", "currentActivityThread",
new Class[] {}, new Object[] {});
String packageName = getPackageName();
HashMap mPackages = (HashMap) RefInvoke.getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mPackages");
WeakReference wr = (WeakReference) mPackages.get(packageName);
MyClassLoader dLoader = new MyClassLoader("/data/data/"
+ base.getPackageName() + "/.cache/classdex.jar", "/data/data/"
+ base.getPackageName() + "/.cache", "/data/data/"
+ base.getPackageName() + "/.cache/", base.getClassLoader());
try {
Class<?> class1 = dLoader.loadClass("com.example.test.TestActivity");
Log.i("b364","----------->class1: "+class1);
} catch (ClassNotFoundException e){
Log.i("b364","----------->class not found Exception!");
e.printStackTrace();
}
Log.i("b364","------>PackageInfo: "+wr.get());
// DexClassLoader dLoader = new DexClassLoader(apkFileName, odexPath,
// libPath, (ClassLoader) RefInvoke.getFieldOjbect(
// "android.app.LoadedApk", wr.get(), "mClassLoader"));
RefInvoke.setFieldOjbect("android.app.LoadedApk", "mClassLoader",
wr.get(), dLoader);
Android 动态加载(防止逆向编译) jar混淆加密的更多相关文章
- Android动态加载jar、apk的实现
前段时间到阿里巴巴参加支付宝技术分享沙龙,看到支付宝在Android使用插件化的技术,挺好奇的.正好这几天看到了农民伯伯的相关文章,因此简单整理了下,有什么错误希望大神指正. 核心类 1.1 ...
- 【Android】Android动态加载Jar、APK的实现
本文介绍Android中动态加载Jar.APK的实现.而主要用到的就是DexClassLoader这个类.大家都知道Android和普通的Java虚拟机有差别,它只能加载经过处理的dex文件.而加载这 ...
- Android动态加载jar/dex
前言 在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优 ...
- 深入浅出Android动态加载jar包技术
在实际项目中,由于某些业务频繁变更而导致频繁升级客户端的弊病会造成较差的用户体验,而这也恰是Web App的优势,于是便衍生了一种思路,将核心的易于变更的业务封装在jar包里然后通过网络下载下来,再由 ...
- [转载] Android动态加载Dex机制解析
本文转载自: http://blog.csdn.net/wy353208214/article/details/50859422 1.什么是类加载器? 类加载器(class loader)是 Java ...
- Android 动态加载 (一) 态加载机制 案例一
在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...
- Android动态加载技术初探
一.前言: 现在,已经有实力强大的公司用这个技术开发应用了,比如淘宝,大众点评,百度地图等,之所以采用这个技术,实际上,就是方便更新功能,当然,前提是新旧功能的接口一致,不然会报Not Found等错 ...
- Android 动态加载 (二) 态加载机制 案例二
探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法 重要说明 在实践的过程中大家都会发现资源引用的问题,这里重点声明两点: 1. 资源文件是不能直接inflate的,如果简单的话直接在程序 ...
- Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类
前言 近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流! 关键字:Android动态加载 声明 欢迎转载, ...
- Android动态加载代码技术
Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...
随机推荐
- 使用NPOI-创建Excel
这里简单的使用一下NPOI ,什么是NPOI? 既然你已经在需要使用了,就一定知道NPOI是干什么用的了. 开始正题吧. 我用控制台程序来给大家演示一下: 一.创建控制台程序 自行脑补 二.添加NPO ...
- Python3 面向对象编程之程序设计思想发展
概述 1940年以前:面向机器 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语 ...
- 机器学习技法:10 Random Forest
Roadmap Random Forest Algorithm Out-Of-Bag Estimate Feature Selection Random Forest in Action Summar ...
- codevs 搜索题汇总(钻石+大师级)
1043 方格取数 2000年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 设有N*N的方格图 ...
- [AtCoder arc090E]Avoiding Collision
Description 题库链接 给出一张 \(N\) 个节点, \(M\) 条边的无向图,给出起点 \(S\) 和终点 \(T\) .询问两个人分别从 \(S\) 和 \(T\) 出发,走最短路不相 ...
- [HNOI 2008]越狱
Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果 相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 I ...
- [Jsoi2011]分特产
Description JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望 ...
- ●BZOJ 4596 [Shoi2016]黑暗前的幻想乡
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4596 题解: 容斥,矩阵树定理,矩阵行列式 先说说容斥:(一共有 N-1个公司) 令 f[i ...
- ●BZOJ 3143 [Hnoi2013]游走
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3143题解: 期望dp,高斯消元 首先有这样一种贪心分配边的编号的方案:(然后我没想到,233 ...
- poj 1873 凸包+枚举
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6198 Accepted: 1 ...