360加固一键脱壳工具2020_Android FART脱壳机流程分析

本文详细分析了Android平台上的FART脱壳工具,该工具主要针对360加固的一键脱壳技术。FART通过主动调用来实现脱壳,尤其在ART环境下,其工作流程包括获取Classloader,反射获取类,遍历DexFile,以及dump Dex和CodeItem。虽然理论上能够脱壳大多数应用,但在实践中仍可能遇到挑战,需要进一步研究和实践。
摘要由CSDN通过智能技术生成

6dbacb1a39ea2c8c64a0f6461329fd09.png

1. 前言 64f8239d6a7a8cc3d5bad5ec6cee9bfc.png

在Android平台上,程序员编写的Java代码最终将被编译成字节码在Android虚拟机上运行。自从Android进入大众的视野后,apktool,jadx等反编译工具也层出不穷,功能也越来越强大,由Java编译成的字节码在这些反编译工具面前变得不堪一击,这相当于一个人裸奔在茫茫人海,身体的各个部位被众人一览无余。一种事物的出现,也会有与之对立的事物出现。有反编译工具的出现,当然也会出现反反编译工具的出现,这种技术一般我们加固技术。APP经过加固,就相当于给那个裸奔的人穿了衣服,“衣服”在一定程度上保护了APP,使APP没那么容易被反编译。当然,有加固技术的出现,也会有反加固技术的出现,即本文要分析的脱壳技术。

Android经过多个版本的更迭,它无论在外观还是内在都有许多改变,早期的Android使用的是dalvik虚拟机,Android4.4开始加入ART虚拟机,但不默认启用。从Android5.0开始,ART取代dalvik,成为默认虚拟机。由于dalvik和ART运行机制的不同,在它们内部脱壳原理也不太相同,本文分析的是ART下的脱壳方案:FART。它的整体思路是通过主动调用的方式来实现脱壳,项目地址:https://github.com/hanbinglengyue/FART

2. 流程分析 64f8239d6a7a8cc3d5bad5ec6cee9bfc.png

FART的入口在frameworks\base\core\java\android\app\ActivityThread.java的performLaunchActivity函数中,即APP的Activity启动的时候执行fartthread

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        Log.e("ActivityThread","go into performLaunchActivity");    ActivityInfo aInfo = r.activityInfo;    if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,                Context.CONTEXT_INCLUDE_CODE);    }    ......    //开启fart线程    fartthread();    ......}

fartthread函数开启一个线程,休眠一分钟后调用fart函数

public static void fartthread() {
        new Thread(new Runnable() {
            @Override        public void run() {
                try {
                    Log.e("ActivityThread", "start sleep,wait for fartthread start......");                Thread.sleep(1 * 60 * 1000);            } catch (InterruptedException e) {
                    e.printStackTrace();            }            Log.e("ActivityThread", "sleep over and start fartthread");            fart();            Log.e("ActivityThread", "fart run over");        }    }).start();}

fart函数中,获取Classloader,反射获取一些类。反射调用dalvik.system.DexPathList的dexElements字段得到dalvik.system.DexPathList$Element类对象数组,Element类存储着dex的路径等信息。接下来通过遍历dexElements,得到每一个Element对象中的DexFile对象,再获取DexFile对象中的mCookie字段值,调用DexFile类中的String[] getClassNameList(Object cookie)函数并传入获取到mCookie,以得到dex文件中所有的类名。随后,遍历dex中的所有类名,传入loadClassAndInvoke函数。

public static void fart() {
        ClassLoader appClassloader = getClassloader();    List<Object> dexFilesArray = new ArrayList<Object>();    Field pathList_Field = (Field) getClassField(appClassloader, "dalvik.system.BaseDexClassLoader", "pathList");    Object pathList_object = getFieldOjbect("dalvik.system.BaseDexClassLoader", appClassloader, "pathList");    Object[] ElementsArray = (Object[]) getFieldOjbect("dalvik.system.DexPathList", pathList_object, "dexElements");    Field dexFile_fileField = null;    try {
            dexFile_fileField = (Field) getClassField(appClassloader, "dalvik.system.DexPathList$Element", "dexFile");    } catch (Exception e) {
            e.printStackTrace();    }    Class DexFileClazz = null;    try {
            DexFileClazz = appClassloader.loadClass("dalvik.system.DexFile");    } catch (Exception e) {
            e.printStackTrace();    }    Method getClassNameList_method = null;    Method defineClass_method = null;    Method dumpDexFile_method = null;    Method dumpMethodCode_method = null;    for (Method field : DexFileClazz.getDeclaredMethods()) {
            if (field.getName().equals("getClassNameList")) {
                getClassNameList_method = field;            getClassNameList_method.setAccessible(true);        }        if (field.getName().equals("defineClassNative")) {
                defineClass_method = field;            defineClass_method.setAccessible(true);        }        if (field.getName().equals("dumpMethodCode")) {
                dumpMethodCode_method = field;            dumpMethodCode_method.setAccessible(true);        }    }    Field mCookiefield = getClassField(appClassloader, "d
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值