{"id":25870516,"url":"https://github.com/LuckyPray/DexKit","last_synced_at":"2025-03-02T06:02:23.606Z","repository":{"id":53816946,"uuid":"518027951","full_name":"LuckyPray/DexKit","owner":"LuckyPray","description":"An easy-to-use, high-performance dex deobfuscation library.","archived":false,"fork":false,"pushed_at":"2024-12-19T05:07:35.000Z","size":2729,"stargazers_count":483,"open_issues_count":5,"forks_count":60,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-12-19T05:28:23.576Z","etag":null,"topics":["deobfuscation","dex","high-performance","library","native-module","xposed"],"latest_commit_sha":null,"homepage":"https://luckypray.org/DexKit/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LuckyPray.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-26T11:12:01.000Z","updated_at":"2024-12-19T05:04:52.000Z","dependencies_parsed_at":"2023-10-16T19:24:34.247Z","dependency_job_id":"606a9575-2511-47a4-ac07-d246fa5c2a02","html_url":"https://github.com/LuckyPray/DexKit","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LuckyPray%2FDexKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LuckyPray%2FDexKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LuckyPray%2FDexKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LuckyPray%2FDexKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LuckyPray","download_url":"https://codeload.github.com/LuckyPray/DexKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241465097,"owners_count":19967243,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deobfuscation","dex","high-performance","library","native-module","xposed"],"created_at":"2025-03-02T06:01:56.015Z","updated_at":"2025-03-02T06:02:23.573Z","avatar_url":"https://github.com/LuckyPray.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003ch1\u003e DexKit \u003c/h1\u003e\n\n[![license](https://img.shields.io/github/license/LuckyPray/DexKit.svg)](https://www.gnu.org/licenses/lgpl-3.0.html)\n[![Maven Central](https://img.shields.io/maven-central/v/org.luckypray/dexkit.svg?label=Maven%20Central)](https://central.sonatype.com/search?q=dexkit\u0026namespace=org.luckypray)\n[![Telegram](https://img.shields.io/badge/discussion%20dev-Telegram-blue.svg?logo=telegram)](https://t.me/LuckyPray_DexKit)\n\nEnglish | [简体中文](https://github.com/LuckyPray/DexKit/blob/master/README_zh.md)\n\n\u003c/div\u003e\n\nA high-performance runtime parsing library for dex implemented in C++, used for lookup of obfuscated classes,\nmethods, or properties.\n\n---\n\n# DexKit 2.0\n\nCurrently 2.0 has been officially released, please refer to Release Notes for related improvements.\n\n## Supported APIs\n\nBasic Features:\n\n- [x] Multi-condition class search\n- [x] Multi-condition method search\n- [x] Multi-condition field search\n- [x] Provides multiple metadata APIs to obtain field/method/class related data\n\n⭐️ Distinctive Features (Recommended):\n\n- [x] Batch search of classes using strings\n- [x] Batch search of methods using strings\n\n\u003e Note: Optimizations have been implemented for string search scenarios, significantly enhancing \n\u003e search speed. Increasing query groups will not lead to a linear increase in time consumption.\n\n### Documentation\n\n- [Click here](https://luckypray.org/DexKit/en/) to go to the documentation page to view more detailed tutorials.\n\n### Dependencies\n\nAdd `dexkit` dependency in `build.gradle`. \n\n```gradle\nrepositories {\n    mavenCentral()\n}\ndependencies {\n    // replace \u003cversion\u003e with your desired version, e.g. `2.0.0`\n    implementation 'org.luckypray:dexkit:\u003cversion\u003e'\n}\n```\n\n\u003e **Note**\n\u003e Starting with **DexKit 2.0**, the new ArtifactId has been changed from `DexKit` to `dexkit`.\n\nDexKit current version: [![Maven Central](https://img.shields.io/maven-central/v/org.luckypray/dexkit.svg?label=Maven%20Central)](https://central.sonatype.com/search?q=dexkit\u0026namespace=org.luckypray)\n\n## Usage Example\n\nHere's a simple usage example.\n\nSuppose this class is what we want to obtain, with most of its names obfuscated and changing in each version.\n\n\u003e Sample app:\n\n\n```java\npackage org.luckypray.dexkit.demo;\n\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.TextView;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.appcompat.widget.h;\nimport java.util.Random;\nimport org.luckypray.dexkit.demo.annotations.Router;\n\n@Router(path = \"/play\")\npublic class PlayActivity extends AppCompatActivity {\n    private static final String TAG = \"PlayActivity\";\n    private TextView a;\n    private Handler b;\n\n    public void d(View view) {\n        Handler handler;\n        int i;\n        Log.d(\"PlayActivity\", \"onClick: rollButton\");\n        float nextFloat = new Random().nextFloat();\n        if (nextFloat \u003c 0.01d) {\n            handler = this.b;\n            i = -1;\n        } else if (nextFloat \u003c 0.987f) {\n            handler = this.b;\n            i = 0;\n        } else {\n            handler = this.b;\n            i = 114514;\n        }\n        handler.sendEmptyMessage(i);\n    }\n\n    public void e(boolean z) {\n        int i;\n        if (!z) {\n            i = RandomUtil.a();\n        } else {\n            i = 6;\n        }\n        String a = h.a(\"You rolled a \", i);\n        this.a.setText(a);\n        Log.d(\"PlayActivity\", \"rollDice: \" + a);\n    }\n\n    protected void onCreate(Bundle bundle) {\n        super/*androidx.fragment.app.FragmentActivity*/.onCreate(bundle);\n        setContentView(0x7f0b001d);\n        Log.d(\"PlayActivity\", \"onCreate\");\n        HandlerThread handlerThread = new HandlerThread(\"PlayActivity\");\n        handlerThread.start();\n        this.b = new PlayActivity$1(this, handlerThread.getLooper());\n        this.a = (TextView) findViewById(0x7f080134);\n        ((Button) findViewById(0x7f08013a)).setOnClickListener(new a(this));\n    }\n}\n```\n\nAt this point, to obtain this class, you can use the following code:\n\n\u003e This is just an example, in actual usage, there's no need for such an extensive set of matching \n\u003e conditions. Choose and use as needed to avoid unnecessary complexity in matching due to an \n\u003e excessive number of conditions.\n\n\u003cdetails\u003e\u003csummary\u003eJava Example\u003c/summary\u003e\n\u003cp\u003e\n\n```java\npublic class MainHook implements IXposedHookLoadPackage {\n    \n    static {\n        System.loadLibrary(\"dexkit\");\n    }\n    \n    private ClassLoader hostClassLoader;\n    \n    @Override\n    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) {\n        String packageName = loadPackageParam.packageName;\n        String apkPath = loadPackageParam.appInfo.sourceDir;\n        if (!packageName.equals(\"org.luckypray.dexkit.demo\")) {\n            return;\n        }\n        this.hostClassLoader = loadPackageParam.classLoader;\n        // DexKit creation is a time-consuming operation, please do not create the object repeatedly. \n        // If you need to use it globally, please manage the life cycle yourself and ensure \n        // that the .close() method is called when not needed to prevent memory leaks.\n        // Here we use `try-with-resources` to automatically close the DexKitBridge instance.\n        try (DexKitBridge bridge = DexKitBridge.create(apkPath)) {\n            findPlayActivity(bridge);\n            // Other use cases\n        }\n    }\n    \n    private void findPlayActivity(DexKitBridge bridge) {\n        ClassData classData = bridge.findClass(FindClass.create()\n            // Search within the specified package name range\n            .searchPackages(\"org.luckypray.dexkit.demo\")\n            // Exclude the specified package name range\n            .excludePackages(\"org.luckypray.dexkit.demo.annotations\")\n            .matcher(ClassMatcher.create()\n                // ClassMatcher Matcher for classes\n                .className(\"org.luckypray.dexkit.demo.PlayActivity\")\n                // FieldsMatcher Matcher for fields in a class\n                .fields(FieldsMatcher.create()\n                    // Add a matcher for the field\n                    .add(FieldMatcher.create()\n                        // Specify the modifiers of the field\n                        .modifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)\n                        // Specify the type of the field\n                        .type(\"java.lang.String\")\n                        // Specify the name of the field\n                        .name(\"TAG\")\n                    )\n                    // Add a matcher for the field of the specified type\n                    .addForType(\"android.widget.TextView\")\n                    .addForType(\"android.os.Handler\")\n                    // Specify the number of fields in the class\n                    .count(3)\n                )\n                // MethodsMatcher Matcher for methods in a class\n                .methods(MethodsMatcher.create()\n                    // Add a matcher for the method\n                    .methods(List.of(\n                        MethodMatcher.create()\n                            // Specify the modifiers of the method\n                            .modifiers(Modifier.PROTECTED)\n                            // Specify the name of the method\n                            .name(\"onCreate\")\n                            // Specify the return type of the method\n                            .returnType(\"void\")\n                            // Specify the parameter type of the method\n                            .paramTypes(\"android.os.Bundle\")\n                            // Specify the strings used by the method\n                            .usingStrings(\"onCreate\"),\n                        MethodMatcher.create()\n                            .paramTypes(\"android.view.View\")\n                            // Specify the numbers used in the method, the type is Byte, Short, Int, Long, Float, Double\n                            .usingNumbers(0.01, -1, 0.987, 0, 114514),\n                        MethodMatcher.create()\n                            .modifiers(Modifier.PUBLIC)\n                            .paramTypes(\"boolean\")\n                            // Specify the method invoke the methods list\n                            .invokeMethods(MethodsMatcher.create()\n                                .add(MethodMatcher.create()\n                                    .modifiers(Modifier.PUBLIC | Modifier.STATIC)\n                                    .returnType(\"int\")\n                                    // be invoke method using strings\n                                    .usingStrings(List.of(\"getRandomDice: \"), StringMatchType.Equals)\n                                )\n                                // Only need to contain the call to the above method\n                                .matchType(MatchType.Contains)\n                            )\n                    ))\n                    // Specify the number of methods in the class, a minimum of 1, and a maximum of 10\n                    .count(1, 10)\n                )\n                // AnnotationsMatcher Matcher for annotations in a class\n                .annotations(AnnotationsMatcher.create()\n                    // Add a matcher for the annotation\n                    .add(AnnotationMatcher.create()\n                        // Specify the type of the annotation\n                        .type(\"org.luckypray.dexkit.demo.annotations.Router\")\n                        // The annotation needs to contain the specified element\n                        .addElement(AnnotationElementMatcher.create()\n                            // Specify the name of the element\n                            .name(\"path\")\n                            // Specify the value of the element\n                            .stringValue(\"/play\")\n                        )\n                    )\n                )\n                // Strings used by all methods in the class\n                .usingStrings(\"PlayActivity\", \"onClick\", \"onCreate\")\n            )\n        ).singleOrThrow(() -\u003e new IllegalStateException(\"The returned result is not unique\"));\n        // Print the found class: org.luckypray.dexkit.demo.PlayActivity\n        System.out.println(classData.getName());\n        // Get the corresponding class instance\n        Class\u003c?\u003e clazz = classData.getInstance(loadPackageParam.classLoader);\n    }\n}\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n\u003cdetails open\u003e\u003csummary\u003eKotlin Example\u003c/summary\u003e\n\u003cp\u003e\n\n```kotlin\nclass MainHook : IXposedHookLoadPackage {\n    \n    companion object {\n        init {\n            System.loadLibrary(\"dexkit\")\n        }\n    }\n\n    private lateinit var hostClassLoader: ClassLoader\n\n    override fun handleLoadPackage(loadPackageParam: XC_LoadPackage.LoadPackageParam) {\n        val packageName = loadPackageParam.packageName\n        val apkPath = loadPackageParam.appInfo.sourceDir\n        if (!packageName.equals(\"org.luckypray.dexkit.demo\")) {\n            return\n        }\n        this.hostClassLoader = loadPackageParam.classLoader\n        // DexKit creation is a time-consuming operation, please do not create the object repeatedly. \n        // If you need to use it globally, please manage the life cycle yourself and ensure \n        // that the .close() method is called when not needed to prevent memory leaks.\n        // Here we use `Closable.use` to automatically close the DexKitBridge instance.\n        DexKitBridge.create(apkPath).use { bridge -\u003e\n            findPlayActivity(bridge)\n            // Other use cases\n        }\n    }\n\n    private fun findPlayActivity(bridge: DexKitBridge) {\n        val classData = bridge.findClass {\n            // Search within the specified package name range\n            searchPackages(\"org.luckypray.dexkit.demo\")\n            // Exclude the specified package name range\n            excludePackages(\"org.luckypray.dexkit.demo.annotations\")\n            // ClassMatcher Matcher for classes\n            matcher {\n                // FieldsMatcher Matcher for fields in a class\n                fields {\n                    // Add a matcher for the field\n                    add {\n                        // Specify the modifiers of the field\n                        modifiers = Modifier.PRIVATE or Modifier.STATIC or Modifier.FINAL\n                        // Specify the type of the field\n                        type = \"java.lang.String\"\n                        // Specify the name of the field\n                        name = \"TAG\"\n                    }\n                    // Add a matcher for the field of the specified type\n                    addForType(\"android.widget.TextView\")\n                    addForType(\"android.os.Handler\")\n                    // Specify the number of fields in the class\n                    count = 3\n                }\n                // MethodsMatcher Matcher for methods in a class\n                methods {\n                    // Add a matcher for the method\n                    add {\n                        // Specify the modifiers of the method\n                        modifiers = Modifier.PROTECTED\n                        // Specify the name of the method\n                        name = \"onCreate\"\n                        // Specify the return type of the method\n                        returnType = \"void\"\n                        // Specify the parameter types of the method, if the parameter types are uncertain,\n                        // use null, and this method will implicitly declare the number of parameters\n                        paramTypes(\"android.os.Bundle\")\n                        // Specify the strings used in the method\n                        usingStrings(\"onCreate\")\n                    }\n                    add {\n                        paramTypes(\"android.view.View\")\n                        // Specify the numbers used in the method, the type is Byte, Short, Int, Long, Float, Double\n                        usingNumbers(0.01, -1, 0.987, 0, 114514)\n                    }\n                    add {\n                        paramTypes(\"boolean\")\n                        // Specify the methods called in the method list\n                        invokeMethods {\n                            add {\n                                modifiers = Modifier.PUBLIC or Modifier.STATIC\n                                returnType = \"int\"\n                                // Specify the strings used in the method called in the method,\n                                usingStrings(listOf(\"getRandomDice: \"), StringMatchType.Equals)\n                            }\n                            // Only need to contain the call to the above method\n                            matchType = MatchType.Contains\n                        }\n                    }\n                    count(1..10)\n                }\n                // AnnotationsMatcher Matcher for annotations in a class\n                annotations {\n                    // Add a matcher for the annotation\n                    add {\n                        // Specify the type of the annotation\n                        type = \"org.luckypray.dexkit.demo.annotations.Router\"\n                        // The annotation needs to contain the specified element\n                        addElement {\n                            // Specify the name of the element\n                            name = \"path\"\n                            // Specify the value of the element\n                            stringValue(\"/play\")\n                        }\n                    }\n                }\n                // Strings used by all methods in the class\n                usingStrings(\"PlayActivity\", \"onClick\", \"onCreate\")\n            }\n        }.singleOrNull() ?: error(\"The returned result is not unique\")\n        // Print the found class: org.luckypray.dexkit.demo.PlayActivity\n        println(classData.name)\n        // Get the corresponding class instance\n        val clazz = classData.getInstance(loadPackageParam.classLoader)\n    }\n}\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n## Third-Party Open Source References\n\n- [slicer](https://cs.android.com/android/platform/superproject/+/main:tools/dexter/slicer/)\n- [ThreadPool](https://github.com/progschj/ThreadPool)\n- [parallel-hashmap](https://github.com/greg7mdp/parallel-hashmap)\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=luckypray/dexkit\u0026type=Date)](https://star-history.com/#luckypray/dexkit\u0026Date)\n\n## License\n\n[LGPL-3.0](https://www.gnu.org/licenses/lgpl-3.0.html) © LuckyPray\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLuckyPray%2FDexKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLuckyPray%2FDexKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLuckyPray%2FDexKit/lists"}