[
  {
    "path": ".gitignore",
    "content": "*.iml\n.DS_Store\n.externalNativeBuild\n.gradle\n.idea\n/build\n/captures\n/local.properties\n"
  },
  {
    "path": "README.md",
    "content": "# 一个脱简单壳的Xposed模块\n\n## 用法\n\n- 搭建Xposed环境\n- 在XposedEntry.java中的targetPackages数组添加需要脱壳的包名\n- 编译本模块并安装到手机\n- 激活模块后，打开目标应用，随便操作一会儿，等待/data/data/packageName下产生dex文件，可查看logcat看进展：logcat -s Xposed\n- 把dex文件都复制到电脑上，用jadx反编译，如果有反编译失败的，先用dex2jar转成jar再用jadx反编译可解决部分失败情况\n\n## 原理\n\n在加载包的时候，匹配是否目标包名及是否加壳，如果是，就hook java.lang.ClassLoader类的loadClass方法，应用如下操作：\n\n- 获得loadClass返回的Class对象\n- 反射调用Class对象的getDex方法获得Dex对象\n- 将Dex对象提交给写文件的线程，在此过程会去除重复的Dex对象并把不同的字节集加到队列\n- 线程异步从队列中读取字节集写到文件中，避免了同步写可能导致ANR\n\n## 限制\n- 只在Android 5.1.1版本的手机上验证过，其它的版本不一定有对应的getBytes和geDex方法\n- 只验证过腾讯乐固、360加固、梆梆加固、百度加固的免费加固工具，都可以脱掉，付费版本没有用过\n\n## 参考\n参考项目：https://github.com/a813630449/dumpDex\n\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "/*\n * Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n * 2019-07-26 Oak Chen\n */\n\napply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 28\n    buildToolsVersion \"28.0.3\"\n    defaultConfig {\n        applicationId \"com.sfysoft.android.xposed.shelling\"\n        minSdkVersion 19\n        //noinspection OldTargetApi\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation 'androidx.appcompat:appcompat:1.0.2'\n    compileOnly 'de.robv.android.xposed:api:82'\n    compileOnly 'de.robv.android.xposed:api:82:sources'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xmlns:tools=\"http://schemas.android.com/tools\" package=\"com.sfysoft.android.xposed.shelling\"\n          tools:ignore=\"GoogleAppIndexingWarning\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\" tools:ignore=\"AllowBackup\">\n\n        <meta-data\n            android:name=\"xposedmodule\"\n            android:value=\"true\"/>\n        <meta-data\n            android:name=\"xposeddescription\"\n            android:value=\"@string/description\"/>\n        <meta-data\n            android:name=\"xposedminversion\"\n            android:value=\"53\"/>\n    </application>\n</manifest>\n"
  },
  {
    "path": "app/src/main/assets/xposed_init",
    "content": "com.sfysoft.android.xposed.shelling.XposedEntry\n"
  },
  {
    "path": "app/src/main/java/com/sfysoft/android/xposed/shelling/XposedEntry.java",
    "content": "/*\n * Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n * 2019-07-26 Oak Chen  Created\n */\n\npackage com.sfysoft.android.xposed.shelling;\n\nimport android.annotation.SuppressLint;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.Queue;\nimport java.util.Set;\n\nimport de.robv.android.xposed.IXposedHookLoadPackage;\nimport de.robv.android.xposed.XC_MethodHook;\nimport de.robv.android.xposed.XposedBridge;\nimport de.robv.android.xposed.XposedHelpers;\nimport de.robv.android.xposed.callbacks.XC_LoadPackage;\n\n/**\n * Xposed entry to shelling app\n *\n * @author Oak Chen\n */\npublic class XposedEntry implements IXposedHookLoadPackage {\n    private static final boolean DEBUG = false;\n    // 加固应用的初始类，对应AndroidManifests.xml里的<application android:name的值\n    // @formatter:off\n    private static final String[] PACKED_APP_ENTRIES = {\n        \"com.stub.StubApp\",                             // 360加固\n        \"s.h.e.l.l.S\",                                  // 爱加密\n        \"com.secneo.apkwrapper.ApplicationWrapper\",     // 梆梆加固\n        \"com.SecShell.SecShell.ApplicationWrapper\",     // 梆梆加固\n        \"com.secneo.apkwrapper.AW\",                     // 梆梆加固\n        \"com.tencent.StubShell.TxAppEntry\",             // 腾讯乐固\n        \"com.baidu.protect.StubApplication\"             // 百度加固\n    };\n\n    // 拟脱壳的App包名，对应AndroidManifests.xml里的<manifest package的值\n    private static final String[] targetPackages = {\n        \"com.sfysoft.shellingtest\"\n    };\n    // @formatter:on\n\n    private static void log(String text) {\n        XposedBridge.log(text);\n    }\n\n    private static void log(Throwable throwable) {\n        XposedBridge.log(throwable);\n    }\n\n    @Override\n    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {\n        String packageName = lpparam.packageName;\n        log(\"Load package: \" + packageName);\n\n        boolean found = false;\n        for (String targetPackage : targetPackages) {\n            if (packageName.equals(targetPackage)) {\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            return;\n        }\n\n        for (String application : PACKED_APP_ENTRIES) {\n            Class cls = XposedHelpers.findClassIfExists(application, lpparam.classLoader);\n            if (cls != null) {\n                log(\"Found \" + application);\n                ClassLoaderHook hook;\n                try {\n                    hook = new ClassLoaderHook(getSavingPath(packageName));\n                    XposedHelpers.findAndHookMethod(\"java.lang.ClassLoader\", lpparam.classLoader,\n                                                    \"loadClass\", String.class, boolean.class, hook);\n                } catch (NoSuchMethodException | ClassNotFoundException e) {\n                    log(e);\n                }\n                break;\n            }\n        }\n    }\n\n    @SuppressWarnings(\"SameParameterValue\")\n    @SuppressLint(\"SdCardPath\")\n    private String getSavingPath(String packageName) {\n        return \"/data/data/\" + packageName;\n    }\n\n    private static class ClassLoaderHook extends XC_MethodHook {\n        private DexOutputTask dexOutputTask;\n        private Method getDex;\n        private Method getBytes;\n\n        @SuppressLint(\"PrivateApi\")\n        ClassLoaderHook(String dexSavingPath) throws ClassNotFoundException, NoSuchMethodException {\n            // 实现限制: 已知Android 5.1.1~7.1.2 同时有下列2个方法，更高版本没有了getDex方法，不可使用\n            // libcore/dex/src/main/java/com/android/dex/Dex.java\n            getBytes = Class.forName(\"com.android.dex.Dex\").getDeclaredMethod(\"getBytes\");\n            // libcore/libart/src/main/java/java/lang/Class.java\n            // noinspection JavaReflectionMemberAccess\n            getDex = Class.forName(\"java.lang.Class\").getDeclaredMethod(\"getDex\");\n            dexOutputTask = new DexOutputTask(dexSavingPath);\n            new Thread(dexOutputTask).start();\n        }\n\n        boolean shouldSkip(String className) {\n            if (className == null) {\n                return true;\n            }\n\n            String[] skippedClassPrefixes = new String[]{\"java\", \"android\"};\n\n            for (String prefix : skippedClassPrefixes) {\n                if (className.startsWith(prefix)) {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        @Override\n        protected void afterHookedMethod(MethodHookParam param) {\n            Class cls = (Class) param.getResult();\n            if (cls == null) {\n                return;\n            }\n\n            if (shouldSkip(cls.getName())) {\n                return;\n            }\n\n            Object dex;\n            try {\n                dex = getDex.invoke(cls);\n            } catch (IllegalAccessException | InvocationTargetException e) {\n                log(e);\n                return;\n            }\n\n            if (DEBUG) {\n                log(\"loadClass \" + cls.getName() + \", Dex: \" + dex);\n            }\n\n            dexOutputTask.write(dex);\n        }\n\n        private class DexOutputTask implements Runnable {\n            // 字节码缓存，不立即写文件，避免写文件太慢导致ANR\n            private final Queue<byte[]> byteSet = new LinkedList<>();\n            // 跟踪哪些类已经解码过，避免重复写到文件中\n            private final Set<Object> dexSet = new HashSet<>();\n            // 保存线程自动关闭前的空闲时间，以毫秒计\n            private final long idleMsToQuit;\n            // dex文件保存目录\n            private String savingDirectory;\n            private Thread currentThread;\n            private long threadId;\n\n            DexOutputTask(String savingDirectory) {\n                // 默认5分钟后没有数据，就自动结束\n                this(savingDirectory, 300000);\n            }\n\n            DexOutputTask(String savingDirectory,\n                          @SuppressWarnings(\"SameParameterValue\") long idleMsToQuit) {\n                this.savingDirectory = savingDirectory;\n                this.idleMsToQuit = idleMsToQuit;\n            }\n\n            @Override\n            public void run() {\n                currentThread = Thread.currentThread();\n                threadId = currentThread.getId();\n\n                File savingDir = new File(savingDirectory);\n                if (!savingDir.exists()) {\n                    if (!savingDir.mkdirs()) {\n                        log(\"Can not mkdir \" + savingDirectory);\n                        return;\n                    }\n                }\n\n                for (int i = 0; ; ) {\n                    byte[] bytes;\n                    synchronized (byteSet) {\n                        bytes = byteSet.poll();\n                        if (bytes == null) {\n                            try {\n                                long start = System.currentTimeMillis();\n                                byteSet.wait(idleMsToQuit);\n                                // 若是超时则退出，结束线程\n                                if (System.currentTimeMillis() - start >= idleMsToQuit) {\n                                    break;\n                                } else {\n                                    // 有新的数据，返回重新读取\n                                    continue;\n                                }\n                            } catch (InterruptedException e) {\n                                continue;\n                            }\n                        }\n                    }\n\n                    i++;\n                    @SuppressLint(\"DefaultLocale\") String targetFile =\n                        savingDirectory + String.format(\"/%05d-%02d.dex\", threadId, i);\n                    log(\"Thread: \" + threadId + \", File: \" + targetFile);\n                    try (FileOutputStream fileOutputStream = new FileOutputStream(targetFile)) {\n                        fileOutputStream.write(bytes);\n                    } catch (IOException e) {\n                        log(e);\n                    }\n                }\n\n                log(\"Thread: \" + threadId + \", Dex size: \" + dexSet.size());\n                synchronized (byteSet) {\n                    byteSet.clear();\n                }\n                synchronized (dexSet) {\n                    dexSet.clear();\n                }\n                savingDirectory = null;\n            }\n\n            void write(Object dex) {\n                if (dex == null) {\n                    return;\n                }\n\n                if (currentThread == null || !currentThread.isAlive()) {\n                    log(\"Thread \" + threadId + \" is not running\");\n                    return;\n                }\n\n                // 避免重复保存同一个dex\n                synchronized (dexSet) {\n                    if (dexSet.contains(dex)) {\n                        return;\n                    }\n                    dexSet.add(dex);\n                }\n\n                byte[] bytes;\n                try {\n                    bytes = (byte[]) getBytes.invoke(dex);\n                } catch (IllegalAccessException | InvocationTargetException e) {\n                    log(e);\n                    return;\n                }\n\n                if (bytes == null) {\n                    return;\n                }\n\n                synchronized (byteSet) {\n                    byteSet.offer(bytes);\n                    byteSet.notifyAll();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<vector\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#008577\"\n        android:pathData=\"M0,0h108v108h-108z\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n        android:width=\"108dp\"\n        android:height=\"108dp\"\n        android:viewportWidth=\"108\"\n        android:viewportHeight=\"108\">\n    <path\n        android:fillType=\"evenOdd\"\n        android:pathData=\"M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"78.5885\"\n                android:endY=\"90.9159\"\n                android:startX=\"48.7653\"\n                android:startY=\"61.0927\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\"/>\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\"/>\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>\n"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#D81B60</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<resources>\n    <string name=\"app_name\">Shelling</string>\n    <string name=\"description\">Dump dex from app protected by free tools from baidu, 360, tencent, bangcle.com</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-26 Oak Chen\n  -->\n\n<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-zh-rCN/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n  ~ 2019-07-31 Oak Chen\n  -->\n\n<resources>\n    <string name=\"app_name\">脱壳</string>\n    <string name=\"description\">从加固过的应用中提取dex文件，适用于百度、360、腾讯、梆梆等提供的免费版加固工具</string>\n</resources>"
  },
  {
    "path": "build.gradle",
    "content": "/*\n * Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n * 2019-07-26 Oak Chen\n */\n\n// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        google()\n        jcenter()\n        \n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:4.2.0'\n        \n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n        \n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#\r\n# Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\r\n# 2019-07-26 Oak Chen\r\n#\r\n\r\n#Fri Jul 26 15:05:01 CST 2019\r\ndistributionBase=GRADLE_USER_HOME\r\ndistributionPath=wrapper/dists\r\nzipStoreBase=GRADLE_USER_HOME\r\nzipStorePath=wrapper/dists\r\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.7.1-all.zip\r\n"
  },
  {
    "path": "gradle.properties",
    "content": "#\n# Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n# 2019-07-26 Oak Chen\n#\n\n# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app's APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Automatically convert third-party libraries to use AndroidX\nandroid.enableJetifier=true\n\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle",
    "content": "/*\n * Copyright (c) 2019 - Oak Chen <oak@sfysoft.com>\n * 2019-07-26 Oak Chen\n */\n\ninclude ':app'\n"
  }
]