Android开发学习之路-脱壳反编译

Posted 东月之神

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发学习之路-脱壳反编译相关的知识,希望对你有一定的参考价值。

前言

  • 想研究下某app里面的实现技术,使用常规的反编译发现竟然是加固的,所谓Apk加固,就是对dex文件进行加密,防止App被反编译,保证apk的安全。市面上有很多的加固平台,有360加固,腾讯乐固,爱加密等等。
  • 上一篇文章我们了解了加固,也有了加固后的apk,这里我们利用工具脱壳查看源码。

1. 脱壳工具FDex2

道高一尺魔高一丈嘛,有加固平台,也有脱壳工具,常见的脱壳工具有FDex2,dumpdex,drizzleDumper等。这里我们使用FDex2来实现脱壳。

FDex2通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。

下载地址:

链接:https://pan.baidu.com/s/1smxtinr 密码:dk4v

我们看下主要的源码:

public class MainHook implements IXposedHookLoadPackage 
  Class Dex;
  
  Method Dex_getBytes;
  
  Method getDex = (Method)null;
  
  XSharedPreferences shared;
  
  @Override
  public void handleLoadPackage(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) 
    this.shared = new XSharedPreferences("formatfa.xposed.Fdex2", "package");
    this.shared.reload();
    initRefect();
    String str = this.shared.getString("packagename", (String)null);
    if (str == null) 
      return;
     
    if (!paramLoadPackageParam.packageName.equals(str))
      return; 
    XposedBridge.log(str + " has hook");
    ClassLoader classLoader = paramLoadPackageParam.classLoader;
    try 
      Class clazz = Class.forName("java.lang.String");
      XposedHelpers.findAndHookMethod("java.lang.ClassLoader", classLoader, "loadClass", new Object[]  clazz, boolean.class, new XC_MethodHook(this, str, paramLoadPackageParam) 
              private final MainHook this$0;
              
              private final String val$aim;
              
              private final XC_LoadPackage.LoadPackageParam val$p1;
              
              @Override
              protected void afterHookedMethod(MethodHookParam param1MethodHookParam) 
                XposedBridge.log(" after hook : ");
                boolean bool = true;
                clazz = (Class)param1MethodHookParam.getResult();
                if (clazz == null)
                  return; 
                try 
                  str = clazz.getName();
                  try 
                    Class clazz1;
                    (clazz1 = Class.forName("formatfa.xposed.Fdex2.MainHook")).forName(str, false, clazz1.getClassLoader().getSystemClassLoader());
                   catch (ClassNotFoundException str) 
                    throw new NoClassDefFoundError(str.getMessage());
                   
                 catch (ClassNotFoundException classNotFoundException) 
                  bool = false;
                 
                if (bool)
                  return; 
                try 
                  Object object = this.this$0.getDex.invoke(clazz, new Object[0]);
                  byte[] arrayOfByte = (byte[])this.this$0.Dex_getBytes.invoke(object, new Object[0]);
                  if (arrayOfByte != null) 
                    "/data/data/" + this.val$aim + "/" + this.val$aim + arrayOfByte.length + ".dex";
                    File file = new File(this.this$0.shared.getString("dir", "/sdcard"), this.val$p1.packageName + arrayOfByte.length + ".dex");
                    if (!file.exists())
                      FIO.writeByte(arrayOfByte, file.getAbsolutePath()); 
                   
                  return;
                 catch (Exception clazz) 
                  XposedBridge.log(clazz.toString());
                  return;
                 
              
              
              @Override
              protected void beforeHookedMethod(MethodHookParam param1MethodHookParam) 
             );
      return;
     catch (ClassNotFoundException paramLoadPackageParam) 
      throw new NoClassDefFoundError(paramLoadPackageParam.getMessage());
     
  
  
  public void initRefect() 
    try 
      this.Dex = Class.forName("com.android.dex.Dex");
      this.Dex_getBytes = this.Dex.getDeclaredMethod("getBytes", new Class[0]);
      if (!MainActivity.h.endsWith("0"))
        return; 
      int i = MainActivity.s.length();
      if (i != 91)
        return; 
      try 
        Class clazz = Class.forName("java.lang.Class");
        this.getDex = clazz.getDeclaredMethod("getDex", new Class[0]);
       catch (ClassNotFoundException classNotFoundException) 
        throw new NoClassDefFoundError(classNotFoundException.getMessage());
       
     catch (Exception exception) 
      XposedBridge.log(exception.toString());
     
  
  
  void writeDex(String paramString, Object paramObject) 
    try 
      paramObject = this.getDex.invoke(paramObject.getClass(), new Object[0]);
      byte[] arrayOfByte = (byte[])this.Dex_getBytes.invoke(paramObject, new Object[0]);
      if (arrayOfByte != null) 
        File file = new File(this.shared.getString("dir", "/sdcard"), paramString + arrayOfByte.length + ".dex");
        if (!file.exists())
          FIO.writeByte(arrayOfByte, file.getAbsolutePath()); 
       
      return;
     catch (InvocationTargetException paramString) 
      return;
     catch (IllegalAccessException paramString) 
      return;
     catch (IllegalArgumentException paramString) 
      return;
     
  

他会根据选中的package,然后运行目标apk的时候把dex文件缓存到/data/data/package下。然后我们可以拿到这些dex文件,通过dex2jar工具转换为jar包,然后再通过jd_gui来查看源码。

关于xposed的hook功能,之后一篇文章会介绍如何使用。

2.VirtualXposed

现在的手机很多都是没有root权限的,若是测试机倒没事,要是是自己在用的手机root了权限显得没那么安全。这里我们可以使用VirtualXposed(下载点击这里),即使不root掉权限,我们也可以拿到我们需要的dex文件.

3.开始脱壳

现在我们应该准备好了VirtualXposed、FDex2和需要脱壳的应用ShellApk,可以开始脱壳了。

3.1 安装

将准备好的上述应用都安装到手机上

3.2 VirtualXposed添加应用

  • 启动VirtualXposed,在"设置->添加应用"中,安装FDex2和脱壳应用ShellApk。

安装完后如下所示:

  • 打开Xposed Installer,在"模块"中勾选FDex2,并重启设备,这里的重启是VirtualXposed的设置中重启,是个软重启。

3.3 启动FDex2

启动VirtualXposed中的FDex2,选择要hook的目标,也就是ShellApk

3.4 启动需要脱壳的应用

启动需要脱壳的应用ShellApk,我们所需要的dex就已经缓存好了

3.5 传输

在VirtualXposed中,“设置–>高级设置–>文件管理”,安装文件管理器.Amaze文件管理器,如果没法安装可以手动安装,当然也可以安装Total Commander自定义标签为"/data/data/io.va.exposed"。

在virtual/data/user/0/com.jared.shellapk目录下选中dex文件,然后通过分享传输到电脑上

注:这里要是不能传输的话,可以试试安装qq,可以通过qq传输到电脑上。

4 查看源码

拿到了dex文件,我们就可以通过dex2jar来生成jar文件,然后通过jd-gui来查看具体的代码了(怎么从dex到jar并查看源码,这里就不分析了,可以参考这篇文章,《逆向分析反编译》

  • 逆向后的代码如下所示:

和ApkTest的源码比较,基本上一致,这里有两个方法gotoSecondActivity和showStr,下一篇文章基于此做一个hook插件。

以上是关于Android开发学习之路-脱壳反编译的主要内容,如果未能解决你的问题,请参考以下文章

Android开发学习之路-加固实践

Android开发学习之路-加固实践

常见android app加固厂商脱壳方法研究

常见android app加固厂商脱壳方法研究

利用反编译学习Android

Frida-Dexdump 脱壳工具下载使用以及相关技术介绍