安卓逆向笔记--爱加密新老对比分析

参考链接:https://blog.csdn.net/chengyingzhilian/article/details/38372601

apk常见的保护

APK高级保护的方法(一)
         运行时验证运行时验证,主要是指在代码启动的时候本地获取签名信息,然后对签名信息进行检验来判断自己的应用是否是正版,如果签名信息不是正版则提示盗版或者直接崩溃。
         它的原理:APK的唯一识别是根据包名+签名,包名信息是写死在Android Manifest.xml里面的,但是签名则是与APK绑定的,一旦APK被反编译后签名会自动消失。APK的签名需要签名文件,签名文件的md5值基本上是无法伪造成一样的。
签名验证的方法也可以细分为3种:
1、Java 层验证
         获取签名信息和验证的方法都写在android 的java层。这种保护方法保护的意义并不大,因为反编译出源码后通过关键字搜索很快就能够找到验证的代码块,稍微一修改这验证保护就完全无效了。
2、服务器验证
         在android 的java层获取签名信息,上传服务器在服务端进行签名然后返回验证结果。这种保护还不如在纯java层验证有用,一旦没有网络验证保护就无效了。用android方法获取的签名信息用java方法也可以获取,验证存放在服务器上也是为了把保护正确的签名信息值,但是保护的意义其实没有任何作用,同样破解后全局搜索关键字然后伪造一个正确的签名信息就可完美破解了。
3、 NDK技术底层获取签名和验证
         通过把Context,Activity,PackageManager,PackageInfo四个对象中的一个作为参数参入底层,在底层获取签名信息并验证。因为获取和验证的方法都封闭在更安全的so库里面,能够起到一定意义上的保护作用。不过通过java层的hook技术一样可以把这种保护完美破解。但是相比于前两种,此保护的意义和价值就更大了。
4、爱加密APP安全保护
         它采用指纹校验保护APK中的文件,加密后APK中所有的文件都对应一个唯一的指纹。每次运行时,APK内部会再次进行指纹生成,如果生成的指纹和原本指纹不相同,则判断为被二次打包过的APK,程序就会自动退出或直接崩溃。该方法可以防止资源文件、主配置文件被修改或删除等操作,完全保证APK的安全。
5、伪加密
         伪加密是Android4.2.x系统发布前的加密方式之一,通过java代码对APK(压缩文件)进行伪加密,其修改原理是修改连续4位字节标记为”P K 01 02”的后第5位字节,奇数表示不加密偶数表示加密。
相较于应用来说,游戏apk因为采用cocos2d-x 或者 unity3D,采用的是c++ 和c# 编写的跨平台程序,在apk采用JNI的方式。所以没有smali,可以防止静态被破解apk包。
6、游戏的加密
         游戏包apk 在运行的时候,会把.*so加载到内存中。动态也是可以在内存中抓取相应的数据。只不NDK 相对于smali破解来说,根本不是一个层级的关系。
APK高级保护的第二种方法——文件夹混淆(二)
         文件夹混淆主要指的是利用Windows,Linux,Android 三个系统环境下的文件夹名的特殊性来对源码文件夹进行混淆,让混淆后的文件夹在Window看起来失去原有的逻辑性,但是完全不影响其在Android系统上的运行。
         它的原理是:在Windows和Linux下文件夹的名字是不区分大小写的,但是在Android环境下它却要区分大小写。.2在Linux算一个特殊符号,所以文件夹名字里面添加的.2会被忽略,但是windows下.2却是一个很普通的字符串。
具体方法:反编译开发完成的APK,找到包目录下的最后一层文件夹(例如:包名是com.example.test2222,找到test2222所在的文件夹),修改test2222文件夹名字为test2222.2并创建文件夹Test2222,然后随意存放一个有效的smali文件在Test2222里面,然后重新重写打包成APK签名。
         这种方法可以达到不错的保护效果,但是开发者一般都没有额外的时间和精力做加固保护。基本时间、技术等原因,爱加密为APK开发者提供免费的技术支持,对APK加壳隐藏源代码,从而防止反编译。它可以对XML 主配文件进行二次签名保护,保护SO文件不被破解和应用,同时可以保护APK不被二次打包!

第三种方式——花指令
         花指令是程序中有一些指令,由设计者特别构思,希望使反汇编的时候出错,让破解者无法清楚正确地反汇编程序的内容,迷失方向。“花指令”这个词来源于汇编语言,它的思想是非常不错的,它的另一个目的就是利用反编译工具漏洞,来使工具无法使用。
接下来,我们就在JAVA代码处制“花指令”,让反编译工具(jd-gui)无法反编译查询你的JAVA代码。jd-gui的bug其实挺多了,很多特殊代码块或者字段集都能够让其崩溃无法反编译出源码。
比如:
private static final char[] wJ = “0123456789abcdef”.toCharArray();
public static String imsi = “204046330839890”;
public static String p = “0”;
public static String keyword = “电话”;public static String tranlateKeyword = “%E7%94%B5%E8%AF%9D”;

爱加密加固的原理

[1]老版爱加密加固
加固后apk的dex文件变成了其他代码,也就是运行使用jni加载so库的代码。
NativeApplication 类,加载exec.so和execmain.so ,里面应该是固定的代码,是调用so库对源码进行解密。

	package com.shell;
	
	import android.app.Application;

	public class NativeApplication
	{
	  static
	  {
   	 		System.loadLibrary("exec");
   	 		System.loadLibrary("execmain");
 	  }
 		public static native boolean load(Application paramApplication, String paramString);
 	 	public static native boolean run(Application paramApplication, String paramString);
 	 	public static native boolean runAll(Application paramApplication, String paramString);
	}

SuperApplication继承自Application,程序主入口:

	package com.shell;
	
	import android.app.Application;
	import android.content.Context;
	
	public class SuperApplication extends Application
	{
		protected void attachBaseContext(Context paramContext)
		{
			super.attachBaseContext(paramContext);
			NativeApplication.load(this, "com.example.gamechange");
		}
	
		public void onCreate()
		{
			NativeApplication.run(this, "android.app.Application");
			super.onCreate();
		}
	}

在加密之后的apk包中,多了一个assets目录,该目录下,有一些ijiami.dat,这个就是我们原来的classex.dex文件。
安卓逆向笔记--爱加密新老对比分析_第1张图片
基本原理是在jni层, 使用DexClassLoader动态加载技术完成对加密classex.dex的动态加载,内存中解密classex.dex,完成动态加载。

[2]现在爱加密加固(企业版免费加固)
首先源程序就是一个获得当前包名的程序
安卓逆向笔记--爱加密新老对比分析_第2张图片
加固之后的发现包名没有改变,运行之后也没有任何改变,但是当使用killer打开的时候就会发现不同。
加固前:
安卓逆向笔记--爱加密新老对比分析_第3张图片
加固后:
安卓逆向笔记--爱加密新老对比分析_第4张图片
再看java代码
加固前:
安卓逆向笔记--爱加密新老对比分析_第5张图片
具体代码

package com.example.demo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity
  extends AppCompatActivity
{
  private String getAppInfo()
  {
    try
    {
      String str = getPackageName();
      return str;
    }
    catch (Exception localException)
    {
      for (;;)
      {
        Object localObject = null;
      }
    }
  }
  
  protected void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2131296283);
    ((TextView)findViewById(2131165306)).setText("当前包名为:" + getAppInfo());
  }
}

加固后:
安卓逆向笔记--爱加密新老对比分析_第6张图片
具体代码

package com.example.demo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity
  extends AppCompatActivity
{
  private String getAppInfo()
  {
    throw new Runtime("d2j fail translate: java.lang.NullPointerException\r\n\tat com.googlecode.dex2jar.ir.ts.ExceptionHandlerCurrectTransformer.transform(ExceptionHandlerCurrectTransformer.java:89)\r\n\tat com.googlecode.d2j.dex.Dex2jar$2.optimize(Dex2jar.java:133)\r\n\tat com.googlecode.d2j.dex.Dex2Asm.convertCode(Dex2Asm.java:414)\r\n\tat com.googlecode.d2j.dex.ExDex2Asm.convertCode(ExDex2Asm.java:42)\r\n\tat com.googlecode.d2j.dex.Dex2jar$2.convertCode(Dex2jar.java:128)\r\n\tat com.googlecode.d2j.dex.Dex2Asm.convertMethod(Dex2Asm.java:509)\r\n\tat com.googlecode.d2j.dex.Dex2Asm.convertClass(Dex2Asm.java:406)\r\n\tat com.googlecode.d2j.dex.Dex2Asm.convertDex(Dex2Asm.java:422)\r\n\tat com.googlecode.d2j.dex.Dex2jar.doTranslate(Dex2jar.java:172)\r\n\tat com.googlecode.d2j.dex.Dex2jar.to(Dex2jar.java:272)\r\n\tat com.googlecode.dex2jar.tools.Dex2jarCmd.doCommandLine(Dex2jarCmd.java:108)\r\n\tat com.googlecode.dex2jar.tools.BaseCmd.doMain(BaseCmd.java:288)\r\n\tat com.googlecode.dex2jar.tools.Dex2jarCmd.main(Dex2jarCmd.java:32)\r\n");
  }
  
  protected void onCreate(Bundle paramBundle) {}
}

apk包的对比:
安卓逆向笔记--爱加密新老对比分析_第7张图片
通过对比可以看到源文件比加密后的文件少了一个so文件存放的地点lib,以及一个assets
看着花里胡哨了很多,但是最基本的原理还是没有变的,只不过利用了jd-jui的bug导致无法看到源码

static
	  {
   	 		System.loadLibrary("exec");
   	 		System.loadLibrary("execmain");
 	  } 	  

安卓逆向笔记--爱加密新老对比分析_第8张图片

爱加密实现步骤

也就是说,不管是新的加固还是老的加固,还是下面的步骤:
1.把原来的classex.dex 用未知的加密算法实现加密成assets/ijiami.dat
2.把事先写好的jni代码和相应的classex.dex替换到原有的位置
3.程序安装完运行起来以后,先运行爱加密的加壳程序,在jni里面动态加载原 来的classex.dex代码,从而达到加壳保护的目的.

你可能感兴趣的:(安卓逆向笔记)