ImageVerifierCode 换一换
格式:DOCX , 页数:35 ,大小:31.88KB ,
资源ID:7180768      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7180768.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Android中的Apk的加固加壳原理解析和实现.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Android中的Apk的加固加壳原理解析和实现.docx

1、Android中的Apk的加固加壳原理解析和实现Android中的Apk的加固(加壳)原理解析和实现一、前言今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理。现阶段。我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk,结果被人反编译了,那心情真心不舒服。虽然我们混淆,做到native层,但是这都是治标不治本。反编译的技术在更新,那么保护Apk的技术就不能停止。现在网上有很多Apk加固的第三方平台,最有名的应当属于:爱加密和梆梆加固了。其实加固有些人认为很高深的技术,其实不然,说的简单点就是对源Apk进行加密,然后在

2、套上一层壳即可,当然这里还有一些细节需要处理,这就是本文需要介绍的内容了。二、原理解析下面就来看一下Android中加壳的原理:我们在加固的过程中需要三个对象:1、需要加密的Apk(源Apk)2、壳程序Apk(负责解密Apk工作)3、加密工具(将源Apk进行加密和壳Dex合并成新的Dex)主要步骤:我们拿到需要加密的Apk和自己的壳程序Apk,然后用加密算法对源Apk进行加密在将壳Apk进行合并得到新的Dex文件,最后替换壳程序中的dex文件即可,得到新的Apk,那么这个新的Apk我们也叫作脱壳程序Apk.他已经不是一个完整意义上的Apk程序了,他的主要工作是:负责解密源Apk.然后加载Apk

3、,让其正常运行起来。在这个过程中我们可能需要了解的一个知识是:如何将源Apk和壳Apk进行合并成新的Dex这里就需要了解Dex文件的格式了。下面就来简单介绍一下Dex文件的格式主要来看一下Dex文件的头部信息,其实Dex文件和Class文件的格式分析原理都是一样的,他们都是有固定的格式,我们知道现在反编译的一些工具:1、jd-gui:可以查看jar中的类,其实他就是解析class文件,只要了解class文件的格式就可以2、dex2jar:将dex文件转化成jar,原理也是一样的,只要知道Dex文件的格式,能够解析出dex文件中的类信息就可以了当然我们在分析这个文件的时候,最重要的还是头部信息,

4、应该他是一个文件的开始部分,也是索引部分,内部信息很重要。我们今天只要关注上面红色标记的三个部分:1) checksum 文件校验码 ,使用alder32 算法校验文件除去 maigc ,checksum 外余下的所有文件区域 ,用于检查文件错误 。2) signature 使用 SHA-1 算法 hash 除去 magic ,checksum 和 signature 外余下的所有文件区域 ,用于唯一识别本文件 。3) file_sizeDex 文件的大小 。为什么说我们只需要关注这三个字段呢?因为我们需要将一个文件(加密之后的源Apk)写入到Dex中,那么我们肯定需要修改文件校验码(chec

5、ksum).因为他是检查文件是否有错误。那么signature也是一样,也是唯一识别文件的算法。还有就是需要修改dex文件的大小。不过这里还需要一个操作,就是标注一下我们加密的Apk的大小,因为我们在脱壳的时候,需要知道Apk的大小,才能正确的得到Apk。那么这个值放到哪呢?这个值直接放到文件的末尾就可以了。所以总结一下我们需要做:修改Dex的三个文件头,将源Apk的大小追加到壳dex的末尾就可以了。我们修改之后得到新的Dex文件样式如下:那么我们知道原理了,下面就是代码实现了。所以这里有三个工程:1、源程序项目(需要加密的Apk)2、脱壳项目(解密源Apk和加载Apk)3、对源Apk进行加密

6、和脱壳项目的Dex的合并三、项目案例下面先来看一下源程序1、需要加密的源程序Apk项目:ForceApkObj需要一个Application类,这个到后面说为什么需要:MyApplication.Javajava view plain copypackage com.example.forceapkobj; import android.app.Application; import android.util.Log; public class MyApplication extends Application Override public void onCreate() super.onC

7、reate(); Log.i(demo, source apk onCreate:+this); 就是打印一下onCreate方法。MainActivity.Javajava view plain copypackage com.example.forceapkobj; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.On

8、ClickListener; import android.widget.TextView; public class MainActivity extends Activity Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); TextView content = new TextView(this); content.setText(I am Source Apk); content.setOnClickListener(new OnClickLis

9、tener() Override public void onClick(View arg0) Intent intent = new Intent(MainActivity.this, SubActivity.class); startActivity(intent); ); setContentView(content); Log.i(demo, app:+getApplicationContext(); 也是打印一下内容。2、加壳程序项目:DexShellTools加壳程序其实就是一个Java工程,因为我们从上面的分析可以看到,他的工作就是加密源Apk,然后将其写入到脱壳Dex文件中,修

10、改文件头,得到一个新的Dex文件即可。看一下代码:java view plain copypackage com.example.reforceapk; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorith

11、mException; import java.util.zip.Adler32; public class mymain /* * param args */ public static void main(String args) / TODO Auto-generated method stub try File payloadSrcFile = new File(force/ForceApkObj.apk); /需要加壳的程序 System.out.println(apk size:+payloadSrcFile.length(); File unShellDexFile = new

12、File(force/ForceApkObj.dex); /解客dex byte payloadArray = encrpt(readFileBytes(payloadSrcFile);/以二进制形式读出apk,并进行加密处理/对源Apk进行加密操作 byte unShellDexArray = readFileBytes(unShellDexFile);/以二进制形式读出dex int payloadLen = payloadArray.length; int unShellDexLen = unShellDexArray.length; int totalLen = payloadLen

13、+ unShellDexLen +4;/多出4字节是存放长度的。 byte newdex = new bytetotalLen; / 申请了新的长度 /添加解壳代码 System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen);/先拷贝dex内容 /添加加密后的解壳数据 System.arraycopy(payloadArray, 0, newdex, unShellDexLen, payloadLen);/再在dex内容后面拷贝apk的内容 /添加解壳数据长度 System.arraycopy(intToByte(payload

14、Len), 0, newdex, totalLen-4, 4);/最后4为长度 /修改DEX file size文件头 fixFileSizeHeader(newdex); /修改DEX SHA1 文件头 fixSHA1Header(newdex); /修改DEX CheckSum文件头 fixCheckSumHeader(newdex); String str = force/classes.dex; File file = new File(str); if (!file.exists() file.createNewFile(); FileOutputStream localFileOu

15、tputStream = new FileOutputStream(str); localFileOutputStream.write(newdex); localFileOutputStream.flush(); localFileOutputStream.close(); catch (Exception e) e.printStackTrace(); /直接返回数据,读者可以添加自己加密方法 private static byte encrpt(byte srcdata) for(int i = 0;isrcdata.length;i+) srcdatai = (byte)(0xFF s

16、rcdatai); return srcdata; /* * 修改dex头,CheckSum 校验码 * param dexBytes */ private static void fixCheckSumHeader(byte dexBytes) Adler32 adler = new Adler32(); adler.update(dexBytes, 12, dexBytes.length - 12);/从12到文件末尾计算校验码 long value = adler.getValue(); int va = (int) value; byte newcs = intToByte(va);

17、/高位在前,低位在前掉个个 byte recs = new byte4; for (int i = 0; i = 0; i-) bi = (byte) (number % 256); number = 8; return b; /* * 修改dex头 sha1值 * param dexBytes * throws NoSuchAlgorithmException */ private static void fixSHA1Header(byte dexBytes) throws NoSuchAlgorithmException MessageDigest md = MessageDigest.

18、getInstance(SHA-1); md.update(dexBytes, 32, dexBytes.length - 32);/从32为到结束计算sha-1 byte newdt = md.digest(); System.arraycopy(newdt, 0, dexBytes, 12, 20);/修改sha-1值(12-31) /输出sha-1值,可有可无 String hexstr = ; for (int i = 0; i newdt.length; i+) hexstr += Integer.toString(newdti & 0xff) + 0x100, 16) .subst

19、ring(1); System.out.println(hexstr); /* * 修改dex头 file_size值 * param dexBytes */ private static void fixFileSizeHeader(byte dexBytes) /新文件长度 byte newfs = intToByte(dexBytes.length); System.out.println(Integer.toHexString(dexBytes.length); byte refs = new byte4; /高位在前,低位在前掉个个 for (int i = 0; i 、加密源程序A

20、pk文件java view plain copybyte payloadArray = encrpt(readFileBytes(payloadSrcFile);/以二进制形式读出apk,并进行加密处理/对源Apk进行加密操作 加密算法很简单:java view plain copy/直接返回数据,读者可以添加自己加密方法 private static byte encrpt(byte srcdata) for(int i = 0;i、合并文件:将加密之后的Apk和原脱壳Dex进行合并java view plain copyint payloadLen = payloadArray.lengt

21、h; int unShellDexLen = unShellDexArray.length; int totalLen = payloadLen + unShellDexLen +4;/多出4字节是存放长度的。 byte newdex = new bytetotalLen; / 申请了新的长度 /添加解壳代码 System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen);/先拷贝dex内容 /添加加密后的解壳数据 System.arraycopy(payloadArray, 0, newdex, unShellDexLen, pa

22、yloadLen);/再在dex内容后面拷贝apk的内容 3、在文件的末尾追加源程序Apk的长度java view plain copy/添加解壳数据长度 System.arraycopy(intToByte(payloadLen), 0, newdex, totalLen-4, 4);/最后4为长度 4、修改新Dex文件的文件头信息:file_size; sha1; check_sumjava view plain copy/修改DEX file size文件头 fixFileSizeHeader(newdex); /修改DEX SHA1 文件头 fixSHA1Header(newdex);

23、 /修改DEX CheckSum文件头 fixCheckSumHeader(newdex); 具体修改可以参照之前说的文件头格式,修改指定位置的字节值即可。这里我们还需要两个输入文件:1、源Apk文件:ForceApkObj.apk2、脱壳程序的Dex文件:ForceApkObj.dex那么第一个文件我们都知道,就是上面的源程序编译之后的Apk文件,那么第二个文件我们怎么得到呢?这个就是我们要讲到的第三个项目:脱壳程序项目,他是一个Android项目,我们在编译之后,能够得到他的classes.dex文件,然后修改一下名称就可。3、脱壳项目:ReforceApk在讲解这个项目之前,我们先来了解

24、一下这个脱壳项目的工作:1、通过反射置换android.app.ActivityThread 中的mClassLoader为加载解密出APK的DexClassLoader,该DexClassLoader一方面加载了源程序、另一方面以原mClassLoader为父节点,这就保证了即加载了源程序又没有放弃原先加载的资源与系统代码。关于这部分内容,不了解的同学可以看一下ActivityThread.java的源码:如何得到系统加载Apk的类加载器,然后我们怎么将加载进来的Apk运行起来等问题都在这篇文章中说到了。2、找到源程序的Application,通过反射建立并运行。这里需要注意的是,我们现在是

25、加载一个完整的Apk,让他运行起来,那么我们知道一个Apk运行的时候都是有一个Application对象的,这个也是一个程序运行之后的全局类。所以我们必须找到解密之后的源Apk的Application类,运行的他的onCreate方法,这样源Apk才开始他的运行生命周期。这里我们如何得到源Apk的Application的类呢?这个我们后面会说道。使用meta标签进行设置。下面来看一下代码:java view plain copypackage com.example.reforceapk; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.WeakReference; import java

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1