zoukankan      html  css  js  c++  java
  • Android APK加壳技术方案【2】

    本文章由Jack_Jia编写,转载请注明出处。  

    文章链接: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头信息。


           代码实现如下:

    [java] view plaincopy
    1. package com.android.dexshell;  
    2. import java.io.ByteArrayOutputStream;  
    3. import java.io.File;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileOutputStream;  
    6. import java.io.IOException;  
    7. import java.security.MessageDigest;  
    8. import java.security.NoSuchAlgorithmException;  
    9. import java.util.zip.Adler32;  
    10.   
    11. public class DexShellTool {  
    12.     /** 
    13.      * @param args 
    14.      */  
    15.     public static void main(String[] args) {  
    16.         // TODO Auto-generated method stub  
    17.         try {  
    18.             File payloadSrcFile = new File("g:/payload.apk");  
    19.             File unShellDexFile = new File("g:/unshell.dex");  
    20.             byte[] payloadArray = encrpt(readFileBytes(payloadSrcFile));  
    21.             byte[] unShellDexArray = readFileBytes(unShellDexFile);  
    22.             int payloadLen = payloadArray.length;  
    23.             int unShellDexLen = unShellDexArray.length;  
    24.             int totalLen = payloadLen + unShellDexLen +4;  
    25.             byte[] newdex = new byte[totalLen];  
    26.             //添加解壳代码  
    27.             System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen);  
    28.             //添加加密后的解壳数据  
    29.             System.arraycopy(payloadArray, 0, newdex, unShellDexLen,  
    30.                     payloadLen);  
    31.             //添加解壳数据长度  
    32.             System.arraycopy(intToByte(payloadLen), 0, newdex, totalLen-44);  
    33.                         //修改DEX file size文件头  
    34.             fixFileSizeHeader(newdex);  
    35.             //修改DEX SHA1 文件头  
    36.             fixSHA1Header(newdex);  
    37.             //修改DEX CheckSum文件头  
    38.             fixCheckSumHeader(newdex);  
    39.   
    40.   
    41.             String str = "g:/classes.dex";  
    42.             File file = new File(str);  
    43.             if (!file.exists()) {  
    44.                 file.createNewFile();  
    45.             }  
    46.               
    47.             FileOutputStream localFileOutputStream = new FileOutputStream(str);  
    48.             localFileOutputStream.write(newdex);  
    49.             localFileOutputStream.flush();  
    50.             localFileOutputStream.close();  
    51.   
    52.   
    53.         } catch (Exception e) {  
    54.             // TODO Auto-generated catch block  
    55.             e.printStackTrace();  
    56.         }  
    57.     }  
    58.       
    59.     //直接返回数据,读者可以添加自己加密方法  
    60.     private static byte[] encrpt(byte[] srcdata){  
    61.         return srcdata;  
    62.     }  
    63.   
    64.   
    65.     private static void fixCheckSumHeader(byte[] dexBytes) {  
    66.         Adler32 adler = new Adler32();  
    67.         adler.update(dexBytes, 12, dexBytes.length - 12);  
    68.         long value = adler.getValue();  
    69.         int va = (int) value;  
    70.         byte[] newcs = intToByte(va);  
    71.         byte[] recs = new byte[4];  
    72.         for (int i = 0; i < 4; i++) {  
    73.             recs[i] = newcs[newcs.length - 1 - i];  
    74.             System.out.println(Integer.toHexString(newcs[i]));  
    75.         }  
    76.         System.arraycopy(recs, 0, dexBytes, 84);  
    77.         System.out.println(Long.toHexString(value));  
    78.         System.out.println();  
    79.     }  
    80.   
    81.   
    82.     public static byte[] intToByte(int number) {  
    83.         byte[] b = new byte[4];  
    84.         for (int i = 3; i >= 0; i--) {  
    85.             b[i] = (byte) (number % 256);  
    86.             number >>= 8;  
    87.         }  
    88.         return b;  
    89.     }  
    90.   
    91.   
    92.     private static void fixSHA1Header(byte[] dexBytes)  
    93.             throws NoSuchAlgorithmException {  
    94.         MessageDigest md = MessageDigest.getInstance("SHA-1");  
    95.         md.update(dexBytes, 32, dexBytes.length - 32);  
    96.         byte[] newdt = md.digest();  
    97.         System.arraycopy(newdt, 0, dexBytes, 1220);  
    98.         String hexstr = "";  
    99.         for (int i = 0; i < newdt.length; i++) {  
    100.             hexstr += Integer.toString((newdt[i] & 0xff) + 0x10016)  
    101.                     .substring(1);  
    102.         }  
    103.         System.out.println(hexstr);  
    104.     }  
    105.   
    106.   
    107.     private static void fixFileSizeHeader(byte[] dexBytes) {  
    108.   
    109.   
    110.         byte[] newfs = intToByte(dexBytes.length);  
    111.         System.out.println(Integer.toHexString(dexBytes.length));  
    112.         byte[] refs = new byte[4];  
    113.         for (int i = 0; i < 4; i++) {  
    114.             refs[i] = newfs[newfs.length - 1 - i];  
    115.             System.out.println(Integer.toHexString(newfs[i]));  
    116.         }  
    117.         System.arraycopy(refs, 0, dexBytes, 324);  
    118.     }  
    119.   
    120.   
    121.     private static byte[] readFileBytes(File file) throws IOException {  
    122.         byte[] arrayOfByte = new byte[1024];  
    123.         ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();  
    124.         FileInputStream fis = new FileInputStream(file);  
    125.         while (true) {  
    126.             int i = fis.read(arrayOfByte);  
    127.             if (i != -1) {  
    128.                 localByteArrayOutputStream.write(arrayOfByte, 0, i);  
    129.             } else {  
    130.                 return localByteArrayOutputStream.toByteArray();  
    131.             }  
    132.         }  
    133.     }  
    134.   
    135.   
    136. }  


        2、 解壳程序流程及代码实现

              在解壳程序的开发过程中需要解决如下几个关键的技术问题:

             (1)解壳代码如何能够第一时间执行?

                      Android程序由不同的组件构成,系统在有需要的时候启动程序组件。因此解壳程序必须在Android系统启动组件之前运行,完成对解壳数                据的解壳及APK文件的动态加载,否则会使程序出现加载类失败的异常。

                      Android开发者都知道Applicaiton做为整个应用的上下文,会被系统第一时间调用,这也是应用开发者程序代码的第一执行点。因此通过对              AndroidMainfest.xml的application的配置可以实现解壳代码第一时间运行。

    [html] view plaincopy
    1. <application  
    2.     android:icon="@drawable/ic_launcher"  
    3.     android:label="@string/app_name"  
    4.     android:theme="@style/AppTheme" android:name="<span style="color: rgb(255, 0, 0);"><em><strong>com.android.dexunshell.ProxyApplication</strong></em></span>>  
    5. </application>  

             (2)如何替换回源程序原有的Application?

                      当在AndroidMainfest.xml文件配置为解壳代码的Application时。源程序原有的Applicaiton将被替换,为了不影响源程序代码逻辑,我们需要              在解壳代码运行完成后,替换回源程序原有的Application对象。我们通过在AndroidMainfest.xml文件中配置原有Applicaiton类信息来达到我们              的目的。解壳程序要在运行完毕后通过创建配置的Application对象,并通过反射修改回原Application。

    [html] view plaincopy
    1. <application  
    2.     android:icon="@drawable/ic_launcher"  
    3.     android:label="@string/app_name"  
    4.     android:theme="@style/AppTheme" android:name="<em><strong><span style="color: rgb(255, 0, 0);">com.android.dexunshell.ProxyApplication</span></strong></em>>  
    5.     <span style="color: rgb(255, 0, 0);"><em><strong><meta-data android:name="APPLICATION_CLASS_NAME" android:value="com.***.Application"/></strong></em></span>  
    6. </application>  

              

              (3)如何通过DexClassLoader实现对apk代码的动态加载。

                      我们知道DexClassLoader加载的类是没有组件生命周期的,也就是说即使DexClassLoader通过对APK的动态加载完成了对组件类的加载,              当系统启动该组件时,还会出现加载类失败的异常。为什么组件类被动态加载入虚拟机,但系统却出现加载类失败呢?

                      通过查看Android源代码我们知道组件类的加载是由另一个ClassLoader来完成的,DexClassLoader和系统组件ClassLoader并不存在关                  系,系统组件ClassLoader当然找不到由DexClassLoader加载的类,如果把系统组件ClassLoader的parent修改成DexClassLoader,我们就可              以实现对apk代码的动态加载。


             (4)如何使解壳后的APK资源文件被代码动态引用。

                     代码默认引用的资源文件在最外层的解壳程序中,因此我们要增加系统的资源加载路径来实现对借壳后APK文件资源的加载。


            解壳实现代码:

    [java] view plaincopy
    1. package com.android.dexunshell;  
    2.   
    3. import java.io.BufferedInputStream;  
    4. import java.io.ByteArrayInputStream;  
    5. import java.io.ByteArrayOutputStream;  
    6. import java.io.DataInputStream;  
    7. import java.io.File;  
    8. import java.io.FileInputStream;  
    9. import java.io.FileOutputStream;  
    10. import java.io.IOException;  
    11. import java.lang.ref.WeakReference;  
    12. import java.util.ArrayList;  
    13. import java.util.HashMap;  
    14. import java.util.Iterator;  
    15. import java.util.zip.ZipEntry;  
    16. import java.util.zip.ZipInputStream;  
    17.   
    18. import dalvik.system.DexClassLoader;  
    19. import android.app.Application;  
    20. import android.content.pm.ApplicationInfo;  
    21. import android.content.pm.PackageManager;  
    22. import android.content.pm.PackageManager.NameNotFoundException;  
    23. import android.os.Bundle;  
    24.   
    25. public class ProxyApplication extends Application {  
    26.   
    27.     private static final String appkey = "APPLICATION_CLASS_NAME";  
    28.     private String apkFileName;  
    29.     private String odexPath;  
    30.     private String libPath;  
    31.     @Override  
    32.     public void onCreate() {  
    33.         // TODO Auto-generated method stub  
    34.         super.onCreate();  
    35.         try {  
    36.             File odex = this.getDir("payload_odex", MODE_PRIVATE);  
    37.             File libs = this.getDir("payload_lib", MODE_PRIVATE);  
    38.             odexPath = odex.getAbsolutePath();  
    39.             libPath = libs.getAbsolutePath();  
    40.             apkFileName = odex.getAbsolutePath()+"/payload.apk";  
    41.             File dexFile = new File(apkFileName);  
    42.             if(!dexFile.exists())  
    43.                 dexFile.createNewFile();  
    44.             //读取程序classes.dex文件  
    45.             byte[] dexdata = this.readDexFileFromApk();  
    46.             //分离出解壳后的apk文件已用于动态加载  
    47.             this.splitPayLoadFromDex(dexdata);  
    48.             //配置动态加载环境  
    49.             this.configApplicationEnv();  
    50.               
    51.         } catch (Exception e) {  
    52.             // TODO Auto-generated catch block  
    53.             e.printStackTrace();  
    54.         }  
    55.     }  
    56.       
    57.     private void configApplicationEnv() throws NameNotFoundException, IllegalAccessException, InstantiationException, ClassNotFoundException, IOException{   
    58.   
    59.         Object currentActivityThread = RefInvoke.invokeStaticMethod("android.app.ActivityThread""currentActivityThread"new Class[]{}, new Object[]{});  
    60.         HashMap mPackages = (HashMap)RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mPackages");  
    61.         //替换组件类加载器为DexClassLoader,已使动态加载代码具有组件生命周期  
    62.         WeakReference wr = (WeakReference) mPackages.get(this.getPackageName());  
    63.         DexClassLoader dLoader = new DexClassLoader(apkFileName,  
    64.                 odexPath, libPath, (ClassLoader) RefInvoke.getFieldOjbect("android.app.LoadedApk", wr.get(), "mClassLoader"));  
    65.         RefInvoke.setFieldOjbect("android.app.LoadedApk""mClassLoader", wr.get(), dLoader);  
    66.   
    67.         //如果源应用配置有Appliction对象,则替换为源应用Applicaiton,以便不影响源程序逻辑。  
    68.         ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo(this.getPackageName(),PackageManager.GET_META_DATA);  
    69.         Bundle bundle =  appInfo.metaData;  
    70.         if(bundle != null && bundle.containsKey(appkey)){  
    71.               
    72.             String appClassName = bundle.getString(appkey);  
    73.             Application app = (Application)dLoader.loadClass(appClassName).newInstance();  
    74.             RefInvoke.setFieldOjbect("android.app.ContextImpl""mOuterContext"this.getBaseContext(), app);  
    75.             RefInvoke.setFieldOjbect("android.content.ContextWrapper""mBase", app, this.getBaseContext());  
    76.             Object mBoundApplication = RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mBoundApplication");  
    77.             Object info = RefInvoke.getFieldOjbect("android.app.ActivityThread$AppBindData", mBoundApplication, "info");  
    78.             RefInvoke.setFieldOjbect("android.app.LoadedApk""mApplication", info, app);  
    79.             Object oldApplication = RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mInitialApplication");  
    80.             RefInvoke.setFieldOjbect("android.app.ActivityThread""mInitialApplication", currentActivityThread, app);  
    81.             ArrayList<Application> mAllApplications = (ArrayList<Application>)RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mAllApplications");  
    82.             mAllApplications.remove(oldApplication);  
    83.             mAllApplications.add(app);  
    84.             HashMap mProviderMap = (HashMap) RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mProviderMap");  
    85.             Iterator it = mProviderMap.values().iterator();  
    86.             while(it.hasNext()){  
    87.                 Object providerClientRecord = it.next();  
    88.                 Object localProvider = RefInvoke.getFieldOjbect("android.app.ProviderClientRecord", providerClientRecord, "mLocalProvider");  
    89.                 RefInvoke.setFieldOjbect("android.content.ContentProvider""mContext", localProvider, app);  
    90.             }  
    91.             RefInvoke.invokeMethod(appClassName, "onCreate", app, new Class[]{}, new Object[]{});  
    92.         }  
    93.     }  
    94.       
    95.     private void splitPayLoadFromDex(byte[] data) throws IOException{  
    96.         byte[] apkdata = decrypt(data);  
    97.         int ablen = apkdata.length;  
    98.         byte[] dexlen = new byte[4];  
    99.         System.arraycopy(apkdata, ablen - 4, dexlen, 04);  
    100.         ByteArrayInputStream bais = new ByteArrayInputStream(dexlen);  
    101.         DataInputStream in = new DataInputStream(bais);  
    102.         int readInt = in.readInt();  
    103.         System.out.println(Integer.toHexString(readInt));  
    104.         byte[] newdex = new byte[readInt];  
    105.         System.arraycopy(apkdata, ablen - 4 - readInt, newdex, 0, readInt);  
    106.         File file = new File(apkFileName);  
    107.         try {  
    108.             FileOutputStream localFileOutputStream = new FileOutputStream(file);  
    109.             localFileOutputStream.write(newdex);  
    110.             localFileOutputStream.close();  
    111.   
    112.         } catch (IOException localIOException) {  
    113.             throw new RuntimeException(localIOException);  
    114.         }  
    115.           
    116.         ZipInputStream localZipInputStream = new ZipInputStream(  
    117.                 new BufferedInputStream(new FileInputStream(file)));  
    118.         while (true) {  
    119.             ZipEntry localZipEntry = localZipInputStream.getNextEntry();  
    120.             if (localZipEntry == null) {  
    121.                 localZipInputStream.close();  
    122.                 break;  
    123.             }  
    124.             String name = localZipEntry.getName();  
    125.             if (name.startsWith("lib/") && name.endsWith(".so")) {  
    126.                 File storeFile = new File(libPath+"/"+name.substring(name.lastIndexOf('/')));  
    127.                 storeFile.createNewFile();  
    128.                 FileOutputStream fos = new FileOutputStream(storeFile);  
    129.                 byte[] arrayOfByte = new byte[1024];  
    130.                 while (true) {  
    131.                     int i = localZipInputStream.read(arrayOfByte);  
    132.                     if (i == -1)  
    133.                         break;  
    134.                     fos.write(arrayOfByte, 0, i);  
    135.                 }  
    136.                 fos.flush();  
    137.                 fos.close();      
    138.             }  
    139.             localZipInputStream.closeEntry();  
    140.         }  
    141.         localZipInputStream.close();      
    142.           
    143.     }  
    144.       
    145.     private byte[] readDexFileFromApk() throws IOException {  
    146.         ByteArrayOutputStream dexByteArrayOutputStream = new ByteArrayOutputStream();  
    147.         ZipInputStream localZipInputStream = new ZipInputStream(  
    148.                 new BufferedInputStream(new FileInputStream(this.getApplicationInfo().sourceDir)));  
    149.         while (true) {  
    150.             ZipEntry localZipEntry = localZipInputStream.getNextEntry();  
    151.             if (localZipEntry == null) {  
    152.                 localZipInputStream.close();  
    153.                 break;  
    154.             }  
    155.             if (localZipEntry.getName().equals("classes.dex")) {  
    156.                 byte[] arrayOfByte = new byte[1024];  
    157.                 while (true) {  
    158.                     int i = localZipInputStream.read(arrayOfByte);  
    159.                     if (i == -1)  
    160.                         break;  
    161.                     dexByteArrayOutputStream.write(arrayOfByte, 0, i);  
    162.                 }  
    163.             }  
    164.             localZipInputStream.closeEntry();  
    165.         }  
    166.         localZipInputStream.close();  
    167.         return dexByteArrayOutputStream.toByteArray();  
    168.     }  
    169.       
    170.     ////直接返回数据,读者可以添加自己解密方法  
    171.     private byte[] decrypt(byte[] data){  
    172.         return data;  
    173.     }  
    174. }  


            RefInvoke为反射调用工具类:


    [java] view plaincopy
    1. package com.android.dexunshell;  
    2.   
    3. import java.lang.reflect.Field;  
    4. import java.lang.reflect.InvocationTargetException;  
    5. import java.lang.reflect.Method;  
    6.   
    7. public class RefInvoke {  
    8.       
    9.     public static  Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules){  
    10.           
    11.         try {  
    12.             Class obj_class = Class.forName(class_name);  
    13.             Method method = obj_class.getMethod(method_name,pareTyple);  
    14.             return method.invoke(null, pareVaules);  
    15.         } catch (SecurityException e) {  
    16.             // TODO Auto-generated catch block  
    17.             e.printStackTrace();  
    18.         }  catch (IllegalArgumentException e) {  
    19.             // TODO Auto-generated catch block  
    20.             e.printStackTrace();  
    21.         } catch (IllegalAccessException e) {  
    22.             // TODO Auto-generated catch block  
    23.             e.printStackTrace();  
    24.         } catch (NoSuchMethodException e) {  
    25.             // TODO Auto-generated catch block  
    26.             e.printStackTrace();  
    27.         } catch (InvocationTargetException e) {  
    28.             // TODO Auto-generated catch block  
    29.             e.printStackTrace();  
    30.         } catch (ClassNotFoundException e) {  
    31.             // TODO Auto-generated catch block  
    32.             e.printStackTrace();  
    33.         }  
    34.         return null;  
    35.           
    36.     }  
    37.       
    38.     public static  Object invokeMethod(String class_name, String method_name, Object obj ,Class[] pareTyple, Object[] pareVaules){  
    39.           
    40.         try {  
    41.             Class obj_class = Class.forName(class_name);  
    42.             Method method = obj_class.getMethod(method_name,pareTyple);  
    43.             return method.invoke(obj, pareVaules);  
    44.         } catch (SecurityException e) {  
    45.             // TODO Auto-generated catch block  
    46.             e.printStackTrace();  
    47.         }  catch (IllegalArgumentException e) {  
    48.             // TODO Auto-generated catch block  
    49.             e.printStackTrace();  
    50.         } catch (IllegalAccessException e) {  
    51.             // TODO Auto-generated catch block  
    52.             e.printStackTrace();  
    53.         } catch (NoSuchMethodException e) {  
    54.             // TODO Auto-generated catch block  
    55.             e.printStackTrace();  
    56.         } catch (InvocationTargetException e) {  
    57.             // TODO Auto-generated catch block  
    58.             e.printStackTrace();  
    59.         } catch (ClassNotFoundException e) {  
    60.             // TODO Auto-generated catch block  
    61.             e.printStackTrace();  
    62.         }  
    63.         return null;  
    64.           
    65.     }  
    66.       
    67.     public static Object getFieldOjbect(String class_name,Object obj, String filedName){  
    68.         try {  
    69.             Class obj_class = Class.forName(class_name);  
    70.             Field field = obj_class.getDeclaredField(filedName);  
    71.             field.setAccessible(true);  
    72.             return field.get(obj);  
    73.         } catch (SecurityException e) {  
    74.             // TODO Auto-generated catch block  
    75.             e.printStackTrace();  
    76.         } catch (NoSuchFieldException e) {  
    77.             // TODO Auto-generated catch block  
    78.             e.printStackTrace();  
    79.         } catch (IllegalArgumentException e) {  
    80.             // TODO Auto-generated catch block  
    81.             e.printStackTrace();  
    82.         } catch (IllegalAccessException e) {  
    83.             // TODO Auto-generated catch block  
    84.             e.printStackTrace();  
    85.         } catch (ClassNotFoundException e) {  
    86.             // TODO Auto-generated catch block  
    87.             e.printStackTrace();  
    88.         }  
    89.         return null;  
    90.           
    91.     }  
    92.       
    93.     public static Object getStaticFieldOjbect(String class_name, String filedName){  
    94.           
    95.         try {  
    96.             Class obj_class = Class.forName(class_name);  
    97.             Field field = obj_class.getDeclaredField(filedName);  
    98.             field.setAccessible(true);  
    99.             return field.get(null);  
    100.         } catch (SecurityException e) {  
    101.             // TODO Auto-generated catch block  
    102.             e.printStackTrace();  
    103.         } catch (NoSuchFieldException e) {  
    104.             // TODO Auto-generated catch block  
    105.             e.printStackTrace();  
    106.         } catch (IllegalArgumentException e) {  
    107.             // TODO Auto-generated catch block  
    108.             e.printStackTrace();  
    109.         } catch (IllegalAccessException e) {  
    110.             // TODO Auto-generated catch block  
    111.             e.printStackTrace();  
    112.         } catch (ClassNotFoundException e) {  
    113.             // TODO Auto-generated catch block  
    114.             e.printStackTrace();  
    115.         }  
    116.         return null;  
    117.           
    118.     }  
    119.       
    120.     public static void setFieldOjbect(String classname, String filedName, Object obj, Object filedVaule){  
    121.         try {  
    122.             Class obj_class = Class.forName(classname);  
    123.             Field field = obj_class.getDeclaredField(filedName);  
    124.             field.setAccessible(true);  
    125.             field.set(obj, filedVaule);  
    126.         } catch (SecurityException e) {  
    127.             // TODO Auto-generated catch block  
    128.             e.printStackTrace();  
    129.         } catch (NoSuchFieldException e) {  
    130.             // TODO Auto-generated catch block  
    131.             e.printStackTrace();  
    132.         } catch (IllegalArgumentException e) {  
    133.             // TODO Auto-generated catch block  
    134.             e.printStackTrace();  
    135.         } catch (IllegalAccessException e) {  
    136.             // TODO Auto-generated catch block  
    137.             e.printStackTrace();  
    138.         } catch (ClassNotFoundException e) {  
    139.             // TODO Auto-generated catch block  
    140.             e.printStackTrace();  
    141.         }     
    142.     }  
    143.       
    144.     public static void setStaticOjbect(String class_name, String filedName, Object filedVaule){  
    145.         try {  
    146.             Class obj_class = Class.forName(class_name);  
    147.             Field field = obj_class.getDeclaredField(filedName);  
    148.             field.setAccessible(true);  
    149.             field.set(null, filedVaule);  
    150.         } catch (SecurityException e) {  
    151.             // TODO Auto-generated catch block  
    152.             e.printStackTrace();  
    153.         } catch (NoSuchFieldException e) {  
    154.             // TODO Auto-generated catch block  
    155.             e.printStackTrace();  
    156.         } catch (IllegalArgumentException e) {  
    157.             // TODO Auto-generated catch block  
    158.             e.printStackTrace();  
    159.         } catch (IllegalAccessException e) {  
    160.             // TODO Auto-generated catch block  
    161.             e.printStackTrace();  
    162.         } catch (ClassNotFoundException e) {  
    163.             // TODO Auto-generated catch block  
    164.             e.printStackTrace();  
    165.         }         
    166.     }  
    167.   
    168. }  


    三、总结


           本文代码基本实现了APK文件的加壳及脱壳原理,该代码作为实验代码还有诸多地方需要改进。比如:

                 1、加壳数据的加密算法的添加。

                 2、脱壳代码由java语言实现,可通过C代码的实现对脱壳逻辑进行保护,以达到更好的反逆向分析效果。

  • 相关阅读:
    Top 10 Product Manager Skills To Boost Your Resume In 2021
    大数据知识梳理
    B端产品如何设计权限系统?
    华三盒式交换机MAC、ARP、Route性能表项参数查询
    中了传说中的挖矿病毒
    SqlServer 2019 事务日志传送
    docker中生成的pdf中文是方框的解决方案
    The Live Editor is unable to run in the current system configuration
    2021 面试题大纲
    五分钟搞定Docker安装ElasticSearch
  • 原文地址:https://www.cnblogs.com/daichangya/p/12959810.html
Copyright © 2011-2022 走看看