文章链接:http://blog.csdn.net/jiazhijun/article/details/8809542
作者:Jack_Jia 邮箱: 309zhijun@163.com
一、序言
在上篇“Android APK加壳技术方案”(http://blog.csdn.net/jiazhijun/article/details/8678399)博文中,根据加壳数据在解壳程序Dex文件所处的位置,我提出了两种Android Dex加壳技术实现方案,本片博文将对方案1代码实现进行讲解。博友可以根据方案1的代码实现原理对方案2自行实现。
在方案1的代码实现过程中,各种不同的问题接踵出现,最初的方案也在不同问题的出现、解决过程中不断的得到调整、优化。
本文的代码实现了对整个APK包的加壳处理。加壳程序不会对源程序有任何的影响。
二、代码实现
本程序基于Android2.3代码实现,因为牵扯到系统代码的反射修改,本程序不保证在其它android版本正常工作,博友可以根据实现原理,自行实现对其它Android版本的兼容性开发。
1、 加壳程序流程及代码实现
1、加密源程序APK为解壳数据
2、把解壳数据写入解壳程序DEX文件末尾,并在文件尾部添加解壳数据的大小。
3、修改解壳程序DEX头中checksum、signature
和file_size头信息。
代码实现如下:
- package com.android.dexshell;
- 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.NoSuchAlgorithmException;
- import java.util.zip.Adler32;
- public class DexShellTool {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- try {
- File payloadSrcFile = new File("g:/payload.apk");
- File unShellDexFile = new File("g:/unshell.dex");
- byte[] payloadArray = encrpt(readFileBytes(payloadSrcFile));
- byte[] unShellDexArray = readFileBytes(unShellDexFile);
- int payloadLen = payloadArray.length;
- int unShellDexLen = unShellDexArray.length;
- int totalLen = payloadLen + unShellDexLen +4;
- byte[] newdex = new byte[totalLen];
- //添加解壳代码
- System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen);
- //添加加密后的解壳数据
- System.arraycopy(payloadArray, 0, newdex, unShellDexLen,
- payloadLen);
- //添加解壳数据长度
- System.arraycopy(intToByte(payloadLen), 0, newdex, totalLen-4, 4);
- //修改DEX file size文件头
- fixFileSizeHeader(newdex);
- //修改DEX SHA1 文件头
- fixSHA1Header(newdex);
- //修改DEX CheckSum文件头
- fixCheckSumHeader(newdex);
- String str = "g:/classes.dex";
- File file = new File(str);
- if (!file.exists()) {
- file.createNewFile();
- }
- FileOutputStream localFileOutputStream = new FileOutputStream(str);
- localFileOutputStream.write(newdex);
- localFileOutputStream.flush();
- localFileOutputStream.close();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- //直接返回数据,读者可以添加自己加密方法
- private static byte[] encrpt(byte[] srcdata){
- return srcdata;
- }
- private static void fixCheckSumHeader(byte[] dexBytes) {
- Adler32 adler = new Adler32();
- adler.update(dexBytes, 12, dexBytes.length - 12);
- long value = adler.getValue();
- int va = (int) value;
- byte[] newcs = intToByte(va);
- byte[] recs = new byte[4];
- for (int i = 0; i < 4; i++) {
- recs[i] = newcs[newcs.length - 1 - i];
- System.out.println(Integer.toHexString(newcs[i]));
- }
- System.arraycopy(recs, 0, dexBytes, 8, 4);
- System.out.println(Long.toHexString(value));
- System.out.println();
- }
- public static byte[] intToByte(int number) {
- byte[] b = new byte[4];
- for (int i = 3; i >= 0; i--) {
- b[i] = (byte) (number % 256);
- number >>= 8;
- }
- return b;
- }
- private static