`

Android 动态加载(防止逆向编译)技术

 
阅读更多

转自:http://blog.csdn.net/pang3510726681/article/details/12573407

      最近工作中接到了一个研究防止逆向编译的任务.研究了几天资料,最后基本实现了防破解技术,在这个工程中,也略有一些心得体会,现整理下来分享,供大家探讨参考研究。文中如有纰漏、失实之处,请大家及时给与指正。

           防破解技术主要有四种实现方式:1.代码混淆(ProGuard)技术 2.签名比对技术 3.NDK  .so 动态库技术 4.动态加载技术.

          参考资料:http://bbs.pediy.com/showthread.php?t=137112    (感谢看雪学院 ZhWeir)

          第一种 代码混淆技术(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包加密

[java] view plaincopy
 
  1. // 加密解密文件//  
  2. public static boolean enOrDecryptFile(byte[] paramArrayOfByte,  
  3.         String sourceFilePath, String destFilePath,int mode){  
  4.     File sourceFile = new File(sourceFilePath);  
  5.     File destFile = new File(destFilePath);  
  6.     CipherOutputStream cout = null;  
  7.     FileInputStream in  = null;  
  8.     FileOutputStream out = null;  
  9.     if (sourceFile.exists() && sourceFile.isFile()) {  
  10.         if (!destFile.getParentFile().exists()) {  
  11.             destFile.getParentFile().mkdirs();  
  12.         }  
  13.         try {  
  14.             destFile.createNewFile();  
  15.             in = new FileInputStream(sourceFile);  
  16.             out = new FileOutputStream(destFile);  
  17.             // 获取密钥//  
  18.             init();  
  19.             SecretKeySpec secretKeySpec = new SecretKeySpec(defPassword, "AES");  
  20.             Cipher cipher;  
  21.             cipher = Cipher.getInstance("AES");  
  22.             cipher.init(mode, secretKeySpec);  
  23.             cout = new CipherOutputStream(out, cipher);  
  24.             byte[] cache = new byte[CACHE_SIZE];  
  25.             int nRead = 0;  
  26.             while ((nRead = in.read(cache)) != -1) {  
  27.                 cout.write(cache, 0, nRead);  
  28.                 cout.flush();  
  29.             }  
  30.         }catch (IOException e) {  
  31.             e.printStackTrace();  
  32.             return false;  
  33.         } catch (NoSuchAlgorithmException e) {  
  34.             e.printStackTrace();  
  35.             return false ;  
  36.         } catch (NoSuchPaddingException e) {  
  37.             e.printStackTrace();  
  38.             return false ;  
  39.         }catch (InvalidKeyException e) {  
  40.             e.printStackTrace();  
  41.             return false;  
  42.         }finally{  
  43.                 if(cout != null){  
  44.                     try {  
  45.                         cout.close();  
  46.                     } catch (IOException e) {  
  47.                         e.printStackTrace();  
  48.                     }  
  49.                 }  
  50.                 if(out != null){  
  51.                     try {  
  52.                         out.close();  
  53.                     } catch (IOException e) {  
  54.                         e.printStackTrace();  
  55.                     }  
  56.                 }  
  57.                 if(in != null){  
  58.                     try {  
  59.                         in.close();  
  60.                     } catch (IOException e) {  
  61.                         e.printStackTrace();  
  62.                     }  
  63.                 }  
  64.         }  
  65.         return true;  
  66.     }  
  67.     return false;  
  68. }  

                 2.jar用SDK\platform-tools\下的dx命令进行dex格式转化:命令如下:

                     dx   --dex    --output=生成的目标文件的地址(绝对路径)     需要转化的jar文件(绝对路径)

                     例如:dx --dex --output=H:\classdex.jar     H:\mainwidget.jar

                 3.再用加密工具将生成jar文件进行加密

                 4.代码动态加载:

[java] view plaincopy
 
  1. File file = new File("/data/data/" + base.getPackageName() + "/.cache/");  
  2.         if (!file.exists()) {  
  3.             file.mkdirs();  
  4.         }  
  5.         try {  
  6.             Runtime.getRuntime().exec("chmod 755 " + file.getAbsolutePath()).waitFor();  
  7.         } catch (InterruptedException e1) {  
  8.             // TODO Auto-generated catch block  
  9.             e1.printStackTrace();  
  10.         } catch (IOException e1) {  
  11.             // TODO Auto-generated catch block  
  12.             e1.printStackTrace();  
  13.         }  
  14.         Util.copyJarFile(this);  
  15.         Object currentActivityThread = RefInvoke.invokeStaticMethod(  
  16.                 "android.app.ActivityThread""currentActivityThread",  
  17.                 new Class[] {}, new Object[] {});  
  18.         String packageName = getPackageName();  
  19.         HashMap mPackages = (HashMap) RefInvoke.getFieldOjbect(  
  20.                 "android.app.ActivityThread", currentActivityThread,  
  21.                 "mPackages");  
  22.         WeakReference wr = (WeakReference) mPackages.get(packageName);  
  23.         MyClassLoader dLoader = new MyClassLoader("/data/data/"  
  24.                 + base.getPackageName() + "/.cache/classdex.jar""/data/data/"  
  25.                 + base.getPackageName() + "/.cache""/data/data/"  
  26.                 + base.getPackageName() + "/.cache/", base.getClassLoader());  
  27.         try {  
  28.             Class<?>  class1 = dLoader.loadClass("com.example.test.TestActivity");  
  29.             Log.i("b364","----------->class1: "+class1);  
  30.         } catch (ClassNotFoundException e){  
  31.             Log.i("b364","----------->class not found Exception!");  
  32.             e.printStackTrace();  
  33.         }  
  34.         Log.i("b364","------>PackageInfo: "+wr.get());  
  35.         // DexClassLoader dLoader = new DexClassLoader(apkFileName, odexPath,  
  36.         // libPath, (ClassLoader) RefInvoke.getFieldOjbect(  
  37.         // "android.app.LoadedApk", wr.get(), "mClassLoader"));  
  38.         RefInvoke.setFieldOjbect("android.app.LoadedApk""mClassLoader",  
  39.                 wr.get(), dLoader);  

                            Demo工程详见附件:http://download.csdn.net/detail/pang3510726681/6378479

分享到:
评论

相关推荐

    Android软件安全与逆向分析_带书签_Android软件安全与逆向分析_带书签_android_

    2. 动态加载:通过动态加载库或代码来防止静态分析。 3. 代码签名与完整性检查:确保代码未被篡改,防止恶意篡改后运行。 通过《Android软件安全与逆向分析》的学习,开发者和安全研究人员可以深入了解Android应用...

    apk加壳和动态加载技术

    动态加载技术 该技术在Java中是一个比较成熟的技术,而Android中该技术还没有被大家充分利用起来。该技术思想主要分为以下几步: 1.将核心代码编译成dex文件的Jar包 2. 对jar包进行加密处理 3.在程序主入口利用NDK...

    android 反编译 逆向 vdex2dex odex2dex

    "android 反编译 逆向 vdex2dex odex2dex"这个主题涉及到的是如何通过特定工具和技术来查看和理解Android应用程序的内部工作原理。在本文中,我们将深入探讨这些概念,以及它们在Android应用逆向工程中的应用。 ...

    Android Studio 基于NDK加密,防止反编译获取加密key

    标题提到的"Android Studio 基于NDK加密,防止反编译获取加密key",这是一个关键的安全策略,旨在保护应用程序中的敏感数据,如API密钥、用户信息或者任何需要保密的数据。NDK(Native Development Kit)是Android...

    Android逆向技术大全

    Android逆向技术是近年来随着移动安全领域日益受到重视而兴起的技术,它的核心内容包括应用的破解与防破解技术、smali代码注入技术、动态调试技术以及应用加壳与脱壳技术。 首先,Android应用的破解与防破解技术是...

    AndroidKiller_1.3.1反编译工具

    这款工具集合了多种反编译工具,简化了对APK文件进行逆向工程的过程,无需复杂的配置和多步操作,只需双击运行,就能直接加载并分析目标APK。 **反编译的概念与重要性** 反编译是将已编译的二进制代码转换回可读的...

    Android系统安全和反编译实战源码

    在Android系统安全与反编译实战的领域中,开发者和安全研究人员都需要深入理解系统的底层机制,以便保护应用程序免受恶意攻击或逆向工程的威胁。本实战源码提供了多个实例,帮助我们掌握关键的安全策略和技术。 一...

    Android一键逆向助手

    此外,逆向过程中也可能遭遇反逆向机制,如代码混淆、动态加载等,这需要逆向工程师具备更高的技术水平和耐心。 总结来说,"Android一键逆向助手2.2"是Android逆向工程领域的一大进步,它降低了逆向分析的难度,...

    代码混淆—关于android被反编译的两种解决方案

    总之,防止Android应用被反编译是一个综合性的任务,需要结合多种技术手段,如代码混淆、权限控制、加密和反逆向框架等。开发者应根据应用的具体需求和安全级别选择合适的防护策略,确保代码的安全。在实践中,不断...

    Android逆向助手

    综上所述,"Android逆向助手"是一个全面的工具集,它涵盖了从APK的反编译、修改到回编译、签名等一系列逆向工程过程,对于Android开发者来说,无论是为了学习、调试还是安全分析,都是一款不可或缺的利器。...

    pk 加固工具apkprotect android 防止反编译

    标题中的“pk 加固工具apkprotect android 防止反编译”指的是ApkProtect,这是一款专为Android APK应用提供安全保护的工具。它的主要功能是通过一系列的技术手段增强APK的安全性,防止恶意用户对其进行反编译、调试...

    Android内存加载Dex文件示例代码

    在Android系统中,Dalvik虚拟机...同时,随着Android系统的不断演进,如ART的AOT(Ahead-Of-Time)编译,动态加载可能会变得更加高效和安全。开发者应持续关注最新的Android安全最佳实践,以保护应用程序免受潜在威胁。

    Androiid 逆向资源AndroidKiller

    《Android逆向技术详解——基于AndroidKiller工具》 在移动设备领域,Android操作系统占据了主导地位,而Android应用的安全性和隐私保护也因此变得至关重要。逆向工程是研究软件内部工作原理的一种技术,它对于安全...

    加壳apk逆向反编译工具.zip

    壳程序可能会混淆代码、加密资源或者执行动态加载,以防止被轻易反编译。然而,逆向工程师有时需要绕过这些壳来深入分析应用。 5. Charles配合使用:Charles与反编译工具结合使用,可以形成强大的分析链。例如,先...

    Android apk反编译

    9. **反反编译技术**:为了进一步阻止APK被反编译,有些开发者会采用动态加载、加密资源、使用自定义类加载器等方式。这增加了逆向工程的复杂度,但也可能导致调试和维护变得更加困难。 总之,Android APK反编译是...

    Android反编译工具包

    在Android开发领域,为了理解和分析已有的应用程序,或者进行二次开发,反编译技术成为了一项重要的技能。本文将详细讲解“Android反编译工具包”中的关键组件:Apktool、dex2jar以及jd-gui,它们是Android开发者...

    AndroidKiller1.3.1,反编译工具

    同时,它也可能具备检测应用是否使用了防逆向技术,如动态加载、加壳等。 5. **日志分析**:在某些情况下,AndroidKiller可能允许用户查看应用运行时的日志输出,这对调试和问题定位至关重要。 6. **代码混淆解除*...

    Android反编译工具-jadx

    在移动应用开发领域,尤其是Android平台,开发者们有时需要对APK文件进行逆向工程,以了解其内部工作原理、安全分析或二次开发。这时,Android反编译工具就显得尤为重要。本文将详细介绍一款名为jadx的高效反编译...

    Android apk包解压逆向工具

    - **资源篡改**:分析资源文件,看是否有动态加载或修改资源的行为,这可能涉及到应用的自定义主题或广告植入。 总的来说,通过使用“Android apk包解压逆向工具”,开发者和安全研究员可以深入了解APK的内部结构,...

Global site tag (gtag.js) - Google Analytics