[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".gitignore",
    "content": "# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Log/OS Files\n*.log\n\n# Android Studio generated files and folders\ncaptures/\n.externalNativeBuild/\n.cxx/\n*.apk\noutput.json\n\n# IntelliJ\n*.iml\n.idea/\nmisc.xml\ndeploymentTargetDropDown.xml\nrender.experimental.xml\n\n# Keystore files\n*.jks\n*.keystore\n\n# Google Services (e.g. APIs or Firebase)\ngoogle-services.json\n\n# Android Profiling\n*.hprof"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Rikka\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Auto-Il2cppDumper\nIl2CppDumper without Magisk/Zygisk, dump il2cpp data at runtime, can bypass protection, encryption and obfuscation.\n\nThis project is forked from BrianGIG [Auto-Il2cppDumper](https://github.com/BryanGIG/Auto-Il2cppDumper)\n\n# Discontined\n\nThis project is no longer maintained. Due to the increasing variety and complexity of game protection and encryption methods, I have chosen to discontinue development. There are no plans for future commits, releases, or support.\n\n# How to use\nDownload pre-compiled libs [HERE](https://github.com/AndnixSH/Auto-Il2cppDumper/releases) and follow steps below\n\nNote: Non-root methods involves modifying APK file, you may need to bypass APK integrity or signature check if it's present. I won't get into the details of bypassing anything because it is simply out of the scope\n\n## Method 1: Fake lib\nThis is a trick to load our own libunity.so or libmain.so and load game's renamed original lib librealunity.so or librealmain.so. Can't decide which lib? Try libmain.so first as it sometimes work better than libunity.so or vice versa\n\n### Root\n- Make sure you know the architecture of the game and your device before proceed\n- Use any file manager app that can access root. Go to /data/data/(package name)/lib or /data/app/(obfuscated name)/(package name-obfuscated name)/lib\n- Rename original libunity.so to librealunity.so or original libmain.so to librealmain.so\n- Put our lib file libunity.so or libmain.so to the lib folder\n  ![](Images/1.png)\n\n### Non-root\nSome games may have APK integrity and signature check. You may need to bypass it before adding Il2CppDumper\n\n- Open APK file as ZIP using Winrar. 7zip or other zip utilities\n- Rename game's libunity.so to librealunity.so or libmain.so to librealmain.so\n- Put our fake lib file libunity.so or libmain.so to the lib folder\n  ![](Images/3.png)\n- Zipalign and sign the APK file\n- Install the APK\n\n### Method 2: Lib call\nIf renaming lib doesn't work, try this method.\n\n- Decompile the game using Apktool\n- Copy libil2cppdumper.so into the lib folder. Make sure only copy same ABIs as the target app, for example if target app has only armeabi-v7a, then you should only copy armeabi-v7a\n- Search the main activity in AndroidManifest.xml. Example: com.gameloft.android.XamarinMainActivity\n\n```xml\n<activity android:configChanges=\"density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode\" android:label=\"@string/icon_label\" android:launchMode=\"singleTop\" android:multiprocess=\"false\" android:name=\"com.gameloft.android.XamarinMainActivity\" android:resizeableActivity=\"false\" android:screenOrientation=\"sensorLandscape\" android:theme=\"@style/Theme.acp.notitlebar.fullscreen\">\n    <intent-filter>\n        <action android:name=\"android.intent.action.MAIN\"/>\n        <category android:name=\"android.intent.category.LAUNCHER\"/>\n    </intent-filter>\n</activity>\n```\n\n- Locate the said main activity in the smali folder, can be \\smali_classes(number)\\com\\gameloft\\android\\XamarinMainActivity.smali if multidex). You must look through all smali classes until you found it\n\n- Insert this lib call into onCreate function below `.locals` XX\n\n```smali\n const-string v0, \"il2cppdumper\"\n \n invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\n```\n\nLike\n\n```smali\n.method protected onCreate(Landroid/os/Bundle;)V\n    .locals 2\n\n    const-string v0, \"il2cppdumper\"\n \n    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\n\n    whatever code below\n```\n\n- Re-compile, zipalign, sign the APK\n- Install the APK\n\n### Dumping\n- Run the game\n- Wait a few seconds. Let the game load into main screen\n- Once the dump is complete, it will save the dump.cs in /storage/emulated/0/Android/data/(Package name)/\n  ![](Images/2.png)\n- If there is no dump.cs, check logcat using Matlog or Android Studio. Game usually crash or freeze if dump fails\n\n### Obfuscated names\nNames can't be deobfuscated. Once they are obfuscated/renamed, it can't be reverted back to original, the game doesn't even kept any original names which makes obfuscation very useful. Instead, try to find older version without obfuscation, or debug the game using GG, frida, gdb, lldb or others. If you can't do any of these, maybe guess the functions and try one by one? :P\n\n### Bypassing protection?\nBypassing is not my thing, but if you know, feel free to make a pull request.\n\n# Usage (If you want to complie by yourself)\n\nIn config header `jni/Includes/config.h`:\n\n`UseFakeLib` is to use it as root mode\n\n`Sleep` is to delay dumping. Increase if getting issue with dumper, like if not fully dumped\n\n# Credits\n- Perfare [Zygisk-Il2CppDumper](https://github.com/Perfare/Zygisk-Il2CppDumper)\n- BrianGIG [Auto-Il2cppDumper](https://github.com/BryanGIG/Auto-Il2cppDumper)\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 36\n    buildToolsVersion \"36.1.0\"\n\n    defaultConfig {\n        applicationId \"com.il2cpp.dumper\"\n        minSdkVersion 21\n        targetSdkVersion 36\n        versionCode 1\n        versionName \"3.1\"\n        ndk {\n            abiFilters 'armeabi-v7a', 'arm64-v8a'\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    externalNativeBuild {\n        ndkBuild {\n            path \"src/main/jni/Android.mk\"\n        }\n    }\n    namespace 'com.il2cpp.dumper'\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"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\" android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n</manifest>"
  },
  {
    "path": "app/src/main/Compile.bat",
    "content": "E:\\Android-SDK\\ndk\\21.3.6528147\\ndk-build\nNDK_PROJECT_PATH=\\\nNDK_APPLICATION_MK=\\jni\\Application.mk\npause"
  },
  {
    "path": "app/src/main/java/com/il2cpp/dumper/MainActivity.java",
    "content": "package com.il2cpp.dumper;\n\nimport android.app.Activity;\nimport android.os.Bundle;\n\n\npublic class MainActivity extends Activity {\n    static {\n        System.loadLibrary(\"il2cppdumper\");\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n    }\n}\n"
  },
  {
    "path": "app/src/main/jni/Android.mk",
    "content": "LOCAL_PATH := $(call my-dir)\nMAIN_LOCAL_PATH := $(call my-dir)\ninclude $(CLEAR_VARS)\n\nLOCAL_MODULE    := il2cppdumper\n\nLOCAL_CFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w\nLOCAL_CFLAGS += -fno-rtti -fno-exceptions -fpermissive\nLOCAL_CPPFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -Werror -s -std=c++17\nLOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fms-extensions -fno-rtti -fno-exceptions -fpermissive\nLOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all, -llog\nLOCAL_ARM_MODE := arm\n\nLOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)\nLOCAL_C_INCLUDES += $(LOCAL_PATH)\nLOCAL_C_INCLUDES += $(LOCAL_PATH)/Il2Cpp/xdl/include\n\nFILE_LIST := $(wildcard $(LOCAL_PATH)/Il2Cpp/xdl/*.c)\n\nLOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)\nLOCAL_SRC_FILES += native-lib.cpp \\\n                   Il2Cpp/il2cpp_dump.cpp\n\nLOCAL_LDLIBS := -llog -landroid -lGLESv2 -ldl\ninclude $(BUILD_SHARED_LIBRARY)"
  },
  {
    "path": "app/src/main/jni/Application.mk",
    "content": "APP_ABI := all\nAPP_STL := c++_static\nAPP_OPTIM := release\nAPP_THIN_ARCHIVE := true\nAPP_PIE := true"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/il2cpp-api-functions.h",
    "content": "#ifndef DO_API_NO_RETURN\n#define DO_API_NO_RETURN(r, n, p) DO_API(r,n,p)\n#endif\n\nDO_API(int, il2cpp_init, (const char* domain_name));\nDO_API(int, il2cpp_init_utf16, (const Il2CppChar * domain_name));\nDO_API(void, il2cpp_shutdown, ());\nDO_API(void, il2cpp_set_config_dir, (const char *config_path));\nDO_API(void, il2cpp_set_data_dir, (const char *data_path));\nDO_API(void, il2cpp_set_temp_dir, (const char *temp_path));\nDO_API(void, il2cpp_set_commandline_arguments, (int argc, const char* const argv[], const char* basedir));\nDO_API(void, il2cpp_set_commandline_arguments_utf16, (int argc, const Il2CppChar * const argv[], const char* basedir));\nDO_API(void, il2cpp_set_config_utf16, (const Il2CppChar * executablePath));\nDO_API(void, il2cpp_set_config, (const char* executablePath));\n\nDO_API(void, il2cpp_set_memory_callbacks, (Il2CppMemoryCallbacks * callbacks));\nDO_API(const Il2CppImage*, il2cpp_get_corlib, ());\nDO_API(void, il2cpp_add_internal_call, (const char* name, Il2CppMethodPointer method));\nDO_API(Il2CppMethodPointer, il2cpp_resolve_icall, (const char* name));\n\nDO_API(void*, il2cpp_alloc, (size_t size));\nDO_API(void, il2cpp_free, (void* ptr));\n\n// array\nDO_API(Il2CppClass*, il2cpp_array_class_get, (Il2CppClass * element_class, uint32_t rank));\nDO_API(uint32_t, il2cpp_array_length, (Il2CppArray * array));\nDO_API(uint32_t, il2cpp_array_get_byte_length, (Il2CppArray * array));\nDO_API(Il2CppArray*, il2cpp_array_new, (Il2CppClass * elementTypeInfo, il2cpp_array_size_t length));\nDO_API(Il2CppArray*, il2cpp_array_new_specific, (Il2CppClass * arrayTypeInfo, il2cpp_array_size_t length));\nDO_API(Il2CppArray*, il2cpp_array_new_full, (Il2CppClass * array_class, il2cpp_array_size_t * lengths, il2cpp_array_size_t * lower_bounds));\nDO_API(Il2CppClass*, il2cpp_bounded_array_class_get, (Il2CppClass * element_class, uint32_t rank, bool bounded));\nDO_API(int, il2cpp_array_element_size, (const Il2CppClass * array_class));\n\n// assembly\nDO_API(const Il2CppImage*, il2cpp_assembly_get_image, (const Il2CppAssembly * assembly));\n\n// class\nDO_API(void, il2cpp_class_for_each, (void(*klassReportFunc)(Il2CppClass* klass, void* userData), void* userData));\nDO_API(const Il2CppType*, il2cpp_class_enum_basetype, (Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_generic, (const Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_inflated, (const Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_assignable_from, (Il2CppClass * klass, Il2CppClass * oklass));\nDO_API(bool, il2cpp_class_is_subclass_of, (Il2CppClass * klass, Il2CppClass * klassc, bool check_interfaces));\nDO_API(bool, il2cpp_class_has_parent, (Il2CppClass * klass, Il2CppClass * klassc));\nDO_API(Il2CppClass*, il2cpp_class_from_il2cpp_type, (const Il2CppType * type));\nDO_API(Il2CppClass*, il2cpp_class_from_name, (const Il2CppImage * image, const char* namespaze, const char *name));\nDO_API(Il2CppClass*, il2cpp_class_from_system_type, (Il2CppReflectionType * type));\nDO_API(Il2CppClass*, il2cpp_class_get_element_class, (Il2CppClass * klass));\nDO_API(const EventInfo*, il2cpp_class_get_events, (Il2CppClass * klass, void* *iter));\nDO_API(FieldInfo*, il2cpp_class_get_fields, (Il2CppClass * klass, void* *iter));\nDO_API(Il2CppClass*, il2cpp_class_get_nested_types, (Il2CppClass * klass, void* *iter));\nDO_API(Il2CppClass*, il2cpp_class_get_interfaces, (Il2CppClass * klass, void* *iter));\nDO_API(const PropertyInfo*, il2cpp_class_get_properties, (Il2CppClass * klass, void* *iter));\nDO_API(const PropertyInfo*, il2cpp_class_get_property_from_name, (Il2CppClass * klass, const char *name));\nDO_API(FieldInfo*, il2cpp_class_get_field_from_name, (Il2CppClass * klass, const char *name));\nDO_API(const MethodInfo*, il2cpp_class_get_methods, (Il2CppClass * klass, void* *iter));\nDO_API(const MethodInfo*, il2cpp_class_get_method_from_name, (Il2CppClass * klass, const char* name, int argsCount));\nDO_API(const char*, il2cpp_class_get_name, (Il2CppClass * klass));\nDO_API(void, il2cpp_type_get_name_chunked, (const Il2CppType * type, void(*chunkReportFunc)(void* data, void* userData), void* userData));\nDO_API(const char*, il2cpp_class_get_namespace, (Il2CppClass * klass));\nDO_API(Il2CppClass*, il2cpp_class_get_parent, (Il2CppClass * klass));\nDO_API(Il2CppClass*, il2cpp_class_get_declaring_type, (Il2CppClass * klass));\nDO_API(int32_t, il2cpp_class_instance_size, (Il2CppClass * klass));\nDO_API(size_t, il2cpp_class_num_fields, (const Il2CppClass * enumKlass));\nDO_API(bool, il2cpp_class_is_valuetype, (const Il2CppClass * klass));\nDO_API(int32_t, il2cpp_class_value_size, (Il2CppClass * klass, uint32_t * align));\nDO_API(bool, il2cpp_class_is_blittable, (const Il2CppClass * klass));\nDO_API(int, il2cpp_class_get_flags, (const Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_abstract, (const Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_interface, (const Il2CppClass * klass));\nDO_API(int, il2cpp_class_array_element_size, (const Il2CppClass * klass));\nDO_API(Il2CppClass*, il2cpp_class_from_type, (const Il2CppType * type));\nDO_API(const Il2CppType*, il2cpp_class_get_type, (Il2CppClass * klass));\nDO_API(uint32_t, il2cpp_class_get_type_token, (Il2CppClass * klass));\nDO_API(bool, il2cpp_class_has_attribute, (Il2CppClass * klass, Il2CppClass * attr_class));\nDO_API(bool, il2cpp_class_has_references, (Il2CppClass * klass));\nDO_API(bool, il2cpp_class_is_enum, (const Il2CppClass * klass));\nDO_API(const Il2CppImage*, il2cpp_class_get_image, (Il2CppClass * klass));\nDO_API(const char*, il2cpp_class_get_assemblyname, (const Il2CppClass * klass));\nDO_API(int, il2cpp_class_get_rank, (const Il2CppClass * klass));\nDO_API(uint32_t, il2cpp_class_get_data_size, (const Il2CppClass * klass));\nDO_API(void*, il2cpp_class_get_static_field_data, (const Il2CppClass * klass));\n\n// testing only\nDO_API(size_t, il2cpp_class_get_bitmap_size, (const Il2CppClass * klass));\nDO_API(void, il2cpp_class_get_bitmap, (Il2CppClass * klass, size_t * bitmap));\n\n// stats\nDO_API(bool, il2cpp_stats_dump_to_file, (const char *path));\nDO_API(uint64_t, il2cpp_stats_get_value, (Il2CppStat stat));\n\n// domain\nDO_API(Il2CppDomain*, il2cpp_domain_get, ());\nDO_API(const Il2CppAssembly*, il2cpp_domain_assembly_open, (Il2CppDomain * domain, const char* name));\nDO_API(const Il2CppAssembly**, il2cpp_domain_get_assemblies, (const Il2CppDomain * domain, size_t * size));\n\n// exception\nDO_API_NO_RETURN(void, il2cpp_raise_exception, (Il2CppException*));\nDO_API(Il2CppException*, il2cpp_exception_from_name_msg, (const Il2CppImage * image, const char *name_space, const char *name, const char *msg));\nDO_API(Il2CppException*, il2cpp_get_exception_argument_null, (const char *arg));\nDO_API(void, il2cpp_format_exception, (const Il2CppException * ex, char* message, int message_size));\nDO_API(void, il2cpp_format_stack_trace, (const Il2CppException * ex, char* output, int output_size));\nDO_API(void, il2cpp_unhandled_exception, (Il2CppException*));\nDO_API(void, il2cpp_native_stack_trace, (const Il2CppException * ex, uintptr_t** addresses, int* numFrames, char** imageUUID, char** imageName));\n\n// field\nDO_API(int, il2cpp_field_get_flags, (FieldInfo * field));\nDO_API(const char*, il2cpp_field_get_name, (FieldInfo * field));\nDO_API(Il2CppClass*, il2cpp_field_get_parent, (FieldInfo * field));\nDO_API(size_t, il2cpp_field_get_offset, (FieldInfo * field));\nDO_API(const Il2CppType*, il2cpp_field_get_type, (FieldInfo * field));\nDO_API(void, il2cpp_field_get_value, (Il2CppObject * obj, FieldInfo * field, void *value));\nDO_API(Il2CppObject*, il2cpp_field_get_value_object, (FieldInfo * field, Il2CppObject * obj));\nDO_API(bool, il2cpp_field_has_attribute, (FieldInfo * field, Il2CppClass * attr_class));\nDO_API(void, il2cpp_field_set_value, (Il2CppObject * obj, FieldInfo * field, void *value));\nDO_API(void, il2cpp_field_static_get_value, (FieldInfo * field, void *value));\nDO_API(void, il2cpp_field_static_set_value, (FieldInfo * field, void *value));\nDO_API(void, il2cpp_field_set_value_object, (Il2CppObject * instance, FieldInfo * field, Il2CppObject * value));\nDO_API(bool, il2cpp_field_is_literal, (FieldInfo * field));\n// gc\nDO_API(void, il2cpp_gc_collect, (int maxGenerations));\nDO_API(int32_t, il2cpp_gc_collect_a_little, ());\nDO_API(void, il2cpp_gc_start_incremental_collection , ());\nDO_API(void, il2cpp_gc_disable, ());\nDO_API(void, il2cpp_gc_enable, ());\nDO_API(bool, il2cpp_gc_is_disabled, ());\nDO_API(void, il2cpp_gc_set_mode, (Il2CppGCMode mode));\nDO_API(int64_t, il2cpp_gc_get_max_time_slice_ns, ());\nDO_API(void, il2cpp_gc_set_max_time_slice_ns, (int64_t maxTimeSlice));\nDO_API(bool, il2cpp_gc_is_incremental, ());\nDO_API(int64_t, il2cpp_gc_get_used_size, ());\nDO_API(int64_t, il2cpp_gc_get_heap_size, ());\nDO_API(void, il2cpp_gc_wbarrier_set_field, (Il2CppObject * obj, void **targetAddress, void *object));\nDO_API(bool, il2cpp_gc_has_strict_wbarriers, ());\nDO_API(void, il2cpp_gc_set_external_allocation_tracker, (void(*func)(void*, size_t, int)));\nDO_API(void, il2cpp_gc_set_external_wbarrier_tracker, (void(*func)(void**)));\nDO_API(void, il2cpp_gc_foreach_heap, (void(*func)(void* data, void* userData), void* userData));\nDO_API(void, il2cpp_stop_gc_world, ());\nDO_API(void, il2cpp_start_gc_world, ());\nDO_API(void*, il2cpp_gc_alloc_fixed, (size_t size));\nDO_API(void, il2cpp_gc_free_fixed, (void* address));\n// gchandle\nDO_API(uint32_t, il2cpp_gchandle_new, (Il2CppObject * obj, bool pinned));\nDO_API(uint32_t, il2cpp_gchandle_new_weakref, (Il2CppObject * obj, bool track_resurrection));\nDO_API(Il2CppObject*, il2cpp_gchandle_get_target , (uint32_t gchandle));\nDO_API(void, il2cpp_gchandle_free, (uint32_t gchandle));\nDO_API(void , il2cpp_gchandle_foreach_get_target, (void(*func)(void* data, void* userData), void* userData));\n\n// vm runtime info\nDO_API(uint32_t, il2cpp_object_header_size, ());\nDO_API(uint32_t, il2cpp_array_object_header_size, ());\nDO_API(uint32_t, il2cpp_offset_of_array_length_in_array_object_header, ());\nDO_API(uint32_t, il2cpp_offset_of_array_bounds_in_array_object_header, ());\nDO_API(uint32_t, il2cpp_allocation_granularity, ());\n\n// liveness\nDO_API(void*, il2cpp_unity_liveness_allocate_struct, (Il2CppClass * filter, int max_object_count, il2cpp_register_object_callback callback, void* userdata, il2cpp_liveness_reallocate_callback reallocate));\nDO_API(void, il2cpp_unity_liveness_calculation_from_root, (Il2CppObject * root, void* state));\nDO_API(void, il2cpp_unity_liveness_calculation_from_statics, (void* state));\nDO_API(void, il2cpp_unity_liveness_finalize, (void* state));\nDO_API(void, il2cpp_unity_liveness_free_struct, (void* state));\n\n// method\nDO_API(const Il2CppType*, il2cpp_method_get_return_type, (const MethodInfo * method));\nDO_API(Il2CppClass*, il2cpp_method_get_declaring_type, (const MethodInfo * method));\nDO_API(const char*, il2cpp_method_get_name, (const MethodInfo * method));\nDO_API(const MethodInfo*, il2cpp_method_get_from_reflection, (const Il2CppReflectionMethod * method));\nDO_API(Il2CppReflectionMethod*, il2cpp_method_get_object, (const MethodInfo * method, Il2CppClass * refclass));\nDO_API(bool, il2cpp_method_is_generic, (const MethodInfo * method));\nDO_API(bool, il2cpp_method_is_inflated, (const MethodInfo * method));\nDO_API(bool, il2cpp_method_is_instance, (const MethodInfo * method));\nDO_API(uint32_t, il2cpp_method_get_param_count, (const MethodInfo * method));\nDO_API(const Il2CppType*, il2cpp_method_get_param, (const MethodInfo * method, uint32_t index));\nDO_API(Il2CppClass*, il2cpp_method_get_class, (const MethodInfo * method));\nDO_API(bool, il2cpp_method_has_attribute, (const MethodInfo * method, Il2CppClass * attr_class));\nDO_API(uint32_t, il2cpp_method_get_flags, (const MethodInfo * method, uint32_t * iflags));\nDO_API(uint32_t, il2cpp_method_get_token, (const MethodInfo * method));\nDO_API(const char*, il2cpp_method_get_param_name, (const MethodInfo * method, uint32_t index));\n\n// profiler\n#if IL2CPP_ENABLE_PROFILER\n\nDO_API(void, il2cpp_profiler_install, (Il2CppProfiler * prof, Il2CppProfileFunc shutdown_callback));\nDO_API(void, il2cpp_profiler_set_events, (Il2CppProfileFlags events));\nDO_API(void, il2cpp_profiler_install_enter_leave, (Il2CppProfileMethodFunc enter, Il2CppProfileMethodFunc fleave));\nDO_API(void, il2cpp_profiler_install_allocation, (Il2CppProfileAllocFunc callback));\nDO_API(void, il2cpp_profiler_install_gc, (Il2CppProfileGCFunc callback, Il2CppProfileGCResizeFunc heap_resize_callback));\nDO_API(void, il2cpp_profiler_install_fileio, (Il2CppProfileFileIOFunc callback));\nDO_API(void, il2cpp_profiler_install_thread, (Il2CppProfileThreadFunc start, Il2CppProfileThreadFunc end));\n\n#endif\n\n// property\nDO_API(uint32_t, il2cpp_property_get_flags, (PropertyInfo * prop));\nDO_API(const MethodInfo*, il2cpp_property_get_get_method, (PropertyInfo * prop));\nDO_API(const MethodInfo*, il2cpp_property_get_set_method, (PropertyInfo * prop));\nDO_API(const char*, il2cpp_property_get_name, (PropertyInfo * prop));\nDO_API(Il2CppClass*, il2cpp_property_get_parent, (PropertyInfo * prop));\n\n// object\nDO_API(Il2CppClass*, il2cpp_object_get_class, (Il2CppObject * obj));\nDO_API(uint32_t, il2cpp_object_get_size, (Il2CppObject * obj));\nDO_API(const MethodInfo*, il2cpp_object_get_virtual_method, (Il2CppObject * obj, const MethodInfo * method));\nDO_API(Il2CppObject*, il2cpp_object_new, (const Il2CppClass * klass));\nDO_API(void*, il2cpp_object_unbox, (Il2CppObject * obj));\n\nDO_API(Il2CppObject*, il2cpp_value_box, (Il2CppClass * klass, void* data));\n\n// monitor\nDO_API(void, il2cpp_monitor_enter, (Il2CppObject * obj));\nDO_API(bool, il2cpp_monitor_try_enter, (Il2CppObject * obj, uint32_t timeout));\nDO_API(void, il2cpp_monitor_exit, (Il2CppObject * obj));\nDO_API(void, il2cpp_monitor_pulse, (Il2CppObject * obj));\nDO_API(void, il2cpp_monitor_pulse_all, (Il2CppObject * obj));\nDO_API(void, il2cpp_monitor_wait, (Il2CppObject * obj));\nDO_API(bool, il2cpp_monitor_try_wait, (Il2CppObject * obj, uint32_t timeout));\n\n// runtime\nDO_API(Il2CppObject*, il2cpp_runtime_invoke, (const MethodInfo * method, void *obj, void **params, Il2CppException **exc));\nDO_API(Il2CppObject*, il2cpp_runtime_invoke_convert_args, (const MethodInfo * method, void *obj, Il2CppObject **params, int paramCount, Il2CppException **exc));\nDO_API(void, il2cpp_runtime_class_init, (Il2CppClass * klass));\nDO_API(void, il2cpp_runtime_object_init, (Il2CppObject * obj));\n\nDO_API(void, il2cpp_runtime_object_init_exception, (Il2CppObject * obj, Il2CppException** exc));\n\nDO_API(void, il2cpp_runtime_unhandled_exception_policy_set, (Il2CppRuntimeUnhandledExceptionPolicy value));\n\n// string\nDO_API(int32_t, il2cpp_string_length, (Il2CppString * str));\nDO_API(Il2CppChar*, il2cpp_string_chars, (Il2CppString * str));\nDO_API(Il2CppString*, il2cpp_string_new, (const char* str));\nDO_API(Il2CppString*, il2cpp_string_new_len, (const char* str, uint32_t length));\nDO_API(Il2CppString*, il2cpp_string_new_utf16, (const Il2CppChar * text, int32_t len));\nDO_API(Il2CppString*, il2cpp_string_new_wrapper, (const char* str));\nDO_API(Il2CppString*, il2cpp_string_intern, (Il2CppString * str));\nDO_API(Il2CppString*, il2cpp_string_is_interned, (Il2CppString * str));\n\n// thread\nDO_API(Il2CppThread*, il2cpp_thread_current, ());\nDO_API(Il2CppThread*, il2cpp_thread_attach, (Il2CppDomain * domain));\nDO_API(void, il2cpp_thread_detach, (Il2CppThread * thread));\n\nDO_API(Il2CppThread**, il2cpp_thread_get_all_attached_threads, (size_t * size));\nDO_API(bool, il2cpp_is_vm_thread, (Il2CppThread * thread));\n\n// stacktrace\nDO_API(void, il2cpp_current_thread_walk_frame_stack, (Il2CppFrameWalkFunc func, void* user_data));\nDO_API(void, il2cpp_thread_walk_frame_stack, (Il2CppThread * thread, Il2CppFrameWalkFunc func, void* user_data));\nDO_API(bool, il2cpp_current_thread_get_top_frame, (Il2CppStackFrameInfo * frame));\nDO_API(bool, il2cpp_thread_get_top_frame, (Il2CppThread * thread, Il2CppStackFrameInfo * frame));\nDO_API(bool, il2cpp_current_thread_get_frame_at, (int32_t offset, Il2CppStackFrameInfo * frame));\nDO_API(bool, il2cpp_thread_get_frame_at, (Il2CppThread * thread, int32_t offset, Il2CppStackFrameInfo * frame));\nDO_API(int32_t, il2cpp_current_thread_get_stack_depth, ());\nDO_API(int32_t, il2cpp_thread_get_stack_depth, (Il2CppThread * thread));\nDO_API(void, il2cpp_override_stack_backtrace, (Il2CppBacktraceFunc stackBacktraceFunc));\n\n// type\nDO_API(Il2CppObject*, il2cpp_type_get_object, (const Il2CppType * type));\nDO_API(int, il2cpp_type_get_type, (const Il2CppType * type));\nDO_API(Il2CppClass*, il2cpp_type_get_class_or_element_class, (const Il2CppType * type));\nDO_API(char*, il2cpp_type_get_name, (const Il2CppType * type));\nDO_API(bool, il2cpp_type_is_byref, (const Il2CppType * type));\nDO_API(uint32_t, il2cpp_type_get_attrs, (const Il2CppType * type));\nDO_API(bool, il2cpp_type_equals, (const Il2CppType * type, const Il2CppType * otherType));\nDO_API(char*, il2cpp_type_get_assembly_qualified_name, (const Il2CppType * type));\nDO_API(bool, il2cpp_type_is_static, (const Il2CppType * type));\nDO_API(bool, il2cpp_type_is_pointer_type, (const Il2CppType * type));\n\n// image\nDO_API(const Il2CppAssembly*, il2cpp_image_get_assembly, (const Il2CppImage * image));\nDO_API(const char*, il2cpp_image_get_name, (const Il2CppImage * image));\nDO_API(const char*, il2cpp_image_get_filename, (const Il2CppImage * image));\nDO_API(const MethodInfo*, il2cpp_image_get_entry_point, (const Il2CppImage * image));\n\nDO_API(size_t, il2cpp_image_get_class_count, (const Il2CppImage * image));\nDO_API(const Il2CppClass*, il2cpp_image_get_class, (const Il2CppImage * image, size_t index));\n\n// Memory information\nDO_API(Il2CppManagedMemorySnapshot*, il2cpp_capture_memory_snapshot, ());\nDO_API(void, il2cpp_free_captured_memory_snapshot, (Il2CppManagedMemorySnapshot * snapshot));\n\nDO_API(void, il2cpp_set_find_plugin_callback, (Il2CppSetFindPlugInCallback method));\n\n// Logging\nDO_API(void, il2cpp_register_log_callback, (Il2CppLogCallback method));\n\n// Debugger\nDO_API(void, il2cpp_debugger_set_agent_options, (const char* options));\nDO_API(bool, il2cpp_is_debugger_attached, ());\nDO_API(void, il2cpp_register_debugger_agent_transport, (Il2CppDebuggerTransport * debuggerTransport));\n\n// Debug metadata\nDO_API(bool, il2cpp_debug_get_method_info, (const MethodInfo*, Il2CppMethodDebugInfo * methodDebugInfo));\n\n// TLS module\nDO_API(void, il2cpp_unity_install_unitytls_interface, (const void* unitytlsInterfaceStruct));\n\n// custom attributes\nDO_API(Il2CppCustomAttrInfo*, il2cpp_custom_attrs_from_class, (Il2CppClass * klass));\nDO_API(Il2CppCustomAttrInfo*, il2cpp_custom_attrs_from_method, (const MethodInfo * method));\n\nDO_API(Il2CppObject*, il2cpp_custom_attrs_get_attr, (Il2CppCustomAttrInfo * ainfo, Il2CppClass * attr_klass));\nDO_API(bool, il2cpp_custom_attrs_has_attr, (Il2CppCustomAttrInfo * ainfo, Il2CppClass * attr_klass));\nDO_API(Il2CppArray*,  il2cpp_custom_attrs_construct, (Il2CppCustomAttrInfo * cinfo));\n\nDO_API(void, il2cpp_custom_attrs_free, (Il2CppCustomAttrInfo * ainfo));\n\n// Il2CppClass user data for GetComponent optimization\nDO_API(void, il2cpp_class_set_userdata, (Il2CppClass * klass, void* userdata));\nDO_API(int, il2cpp_class_get_userdata_offset, ());\n\nDO_API(void, il2cpp_set_default_thread_affinity, (int64_t affinity_mask));\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/il2cpp-class.h",
    "content": "typedef uint16_t Il2CppChar;\ntypedef uintptr_t il2cpp_array_size_t;\ntypedef int32_t TypeDefinitionIndex;\ntypedef int32_t GenericParameterIndex;\ntypedef char Il2CppNativeChar;\n\ntypedef struct Il2CppMemoryCallbacks Il2CppMemoryCallbacks;\ntypedef struct Il2CppImage Il2CppImage;\ntypedef struct Il2CppClass Il2CppClass;\ntypedef struct Il2CppArrayBounds Il2CppArrayBounds;\ntypedef struct Il2CppAssembly Il2CppAssembly;\ntypedef struct Il2CppArrayType Il2CppArrayType;\ntypedef struct Il2CppGenericClass Il2CppGenericClass;\ntypedef struct Il2CppReflectionType Il2CppReflectionType;\ntypedef struct MonitorData MonitorData;\ntypedef Il2CppClass Il2CppVTable;\ntypedef struct EventInfo EventInfo;\ntypedef struct FieldInfo FieldInfo;\ntypedef struct PropertyInfo PropertyInfo;\ntypedef struct Il2CppDomain Il2CppDomain;\ntypedef struct Il2CppException Il2CppException;\ntypedef struct Il2CppObject Il2CppObject;\ntypedef struct Il2CppReflectionMethod Il2CppReflectionMethod;\ntypedef struct Il2CppString Il2CppString;\ntypedef struct Il2CppThread Il2CppThread;\ntypedef struct Il2CppStackFrameInfo Il2CppStackFrameInfo;\ntypedef struct Il2CppManagedMemorySnapshot Il2CppManagedMemorySnapshot;\ntypedef struct Il2CppDebuggerTransport Il2CppDebuggerTransport;\ntypedef struct Il2CppMethodDebugInfo Il2CppMethodDebugInfo;\ntypedef struct Il2CppCustomAttrInfo Il2CppCustomAttrInfo;\ntypedef const struct ___Il2CppMetadataTypeHandle *Il2CppMetadataTypeHandle;\ntypedef const struct ___Il2CppMetadataGenericParameterHandle *Il2CppMetadataGenericParameterHandle;\n\ntypedef void (*Il2CppMethodPointer)();\n\ntypedef void (*il2cpp_register_object_callback)(Il2CppObject **arr, int size, void *userdata);\n\ntypedef void *(*il2cpp_liveness_reallocate_callback)(void *ptr, size_t size, void *userdata);\n\ntypedef void (*Il2CppFrameWalkFunc)(const Il2CppStackFrameInfo *info, void *user_data);\n\ntypedef size_t(*Il2CppBacktraceFunc)(Il2CppMethodPointer *buffer, size_t maxSize);\n\ntypedef const Il2CppNativeChar *(*Il2CppSetFindPlugInCallback)(const Il2CppNativeChar *);\n\ntypedef void (*Il2CppLogCallback)(const char *);\n\ntypedef enum {\n    IL2CPP_UNHANDLED_POLICY_LEGACY,\n    IL2CPP_UNHANDLED_POLICY_CURRENT\n} Il2CppRuntimeUnhandledExceptionPolicy;\n\ntypedef enum {\n    IL2CPP_GC_MODE_DISABLED = 0,\n    IL2CPP_GC_MODE_ENABLED = 1,\n    IL2CPP_GC_MODE_MANUAL = 2\n} Il2CppGCMode;\n\ntypedef enum Il2CppStat {\n    IL2CPP_STAT_NEW_OBJECT_COUNT,\n    IL2CPP_STAT_INITIALIZED_CLASS_COUNT,\n    IL2CPP_STAT_METHOD_COUNT,\n    IL2CPP_STAT_CLASS_STATIC_DATA_SIZE,\n    IL2CPP_STAT_GENERIC_INSTANCE_COUNT,\n    IL2CPP_STAT_GENERIC_CLASS_COUNT,\n    IL2CPP_STAT_INFLATED_METHOD_COUNT,\n    IL2CPP_STAT_INFLATED_TYPE_COUNT,\n} Il2CppStat;\n\ntypedef enum Il2CppTypeEnum {\n    IL2CPP_TYPE_END = 0x00,\n    IL2CPP_TYPE_VOID = 0x01,\n    IL2CPP_TYPE_BOOLEAN = 0x02,\n    IL2CPP_TYPE_CHAR = 0x03,\n    IL2CPP_TYPE_I1 = 0x04,\n    IL2CPP_TYPE_U1 = 0x05,\n    IL2CPP_TYPE_I2 = 0x06,\n    IL2CPP_TYPE_U2 = 0x07,\n    IL2CPP_TYPE_I4 = 0x08,\n    IL2CPP_TYPE_U4 = 0x09,\n    IL2CPP_TYPE_I8 = 0x0a,\n    IL2CPP_TYPE_U8 = 0x0b,\n    IL2CPP_TYPE_R4 = 0x0c,\n    IL2CPP_TYPE_R8 = 0x0d,\n    IL2CPP_TYPE_STRING = 0x0e,\n    IL2CPP_TYPE_PTR = 0x0f,\n    IL2CPP_TYPE_BYREF = 0x10,\n    IL2CPP_TYPE_VALUETYPE = 0x11,\n    IL2CPP_TYPE_CLASS = 0x12,\n    IL2CPP_TYPE_VAR = 0x13,\n    IL2CPP_TYPE_ARRAY = 0x14,\n    IL2CPP_TYPE_GENERICINST = 0x15,\n    IL2CPP_TYPE_TYPEDBYREF = 0x16,\n    IL2CPP_TYPE_I = 0x18,\n    IL2CPP_TYPE_U = 0x19,\n    IL2CPP_TYPE_FNPTR = 0x1b,\n    IL2CPP_TYPE_OBJECT = 0x1c,\n    IL2CPP_TYPE_SZARRAY = 0x1d,\n    IL2CPP_TYPE_MVAR = 0x1e,\n    IL2CPP_TYPE_CMOD_REQD = 0x1f,\n    IL2CPP_TYPE_CMOD_OPT = 0x20,\n    IL2CPP_TYPE_INTERNAL = 0x21,\n    IL2CPP_TYPE_MODIFIER = 0x40,\n    IL2CPP_TYPE_SENTINEL = 0x41,\n    IL2CPP_TYPE_PINNED = 0x45,\n    IL2CPP_TYPE_ENUM = 0x55,\n    IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff\n} Il2CppTypeEnum;\n\ntypedef struct Il2CppType {\n    union {\n        void *dummy;\n        TypeDefinitionIndex klassIndex;\n        const Il2CppType *type;\n        Il2CppArrayType *array;\n        GenericParameterIndex genericParameterIndex;\n        Il2CppGenericClass *generic_class;\n    } data;\n    unsigned int attrs: 16;\n    Il2CppTypeEnum type: 8;\n    unsigned int num_mods: 6;\n    unsigned int byref: 1;\n    unsigned int pinned: 1;\n} Il2CppType;\n\ntypedef struct MethodInfo {\n    Il2CppMethodPointer methodPointer;\n} MethodInfo;\n\ntypedef struct Il2CppObject {\n    union {\n        Il2CppClass *klass;\n        Il2CppVTable *vtable;\n    };\n    MonitorData *monitor;\n} Il2CppObject;\n\ntypedef struct Il2CppArray {\n    Il2CppObject obj;\n    Il2CppArrayBounds *bounds;\n    il2cpp_array_size_t max_length;\n    void *vector[32];\n} Il2CppArray;\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/il2cpp-tabledefs.h",
    "content": "#pragma once\n\n/*\n * Field Attributes (21.1.5).\n */\n\n#define FIELD_ATTRIBUTE_FIELD_ACCESS_MASK     0x0007\n#define FIELD_ATTRIBUTE_COMPILER_CONTROLLED   0x0000\n#define FIELD_ATTRIBUTE_PRIVATE               0x0001\n#define FIELD_ATTRIBUTE_FAM_AND_ASSEM         0x0002\n#define FIELD_ATTRIBUTE_ASSEMBLY              0x0003\n#define FIELD_ATTRIBUTE_FAMILY                0x0004\n#define FIELD_ATTRIBUTE_FAM_OR_ASSEM          0x0005\n#define FIELD_ATTRIBUTE_PUBLIC                0x0006\n\n#define FIELD_ATTRIBUTE_STATIC                0x0010\n#define FIELD_ATTRIBUTE_INIT_ONLY             0x0020\n#define FIELD_ATTRIBUTE_LITERAL               0x0040\n#define FIELD_ATTRIBUTE_NOT_SERIALIZED        0x0080\n#define FIELD_ATTRIBUTE_SPECIAL_NAME          0x0200\n#define FIELD_ATTRIBUTE_PINVOKE_IMPL          0x2000\n\n/* For runtime use only */\n#define FIELD_ATTRIBUTE_RESERVED_MASK         0x9500\n#define FIELD_ATTRIBUTE_RT_SPECIAL_NAME       0x0400\n#define FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL     0x1000\n#define FIELD_ATTRIBUTE_HAS_DEFAULT           0x8000\n#define FIELD_ATTRIBUTE_HAS_FIELD_RVA         0x0100\n\n/*\n * Method Attributes (22.1.9)\n */\n\n#define METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK       0x0003\n#define METHOD_IMPL_ATTRIBUTE_IL                   0x0000\n#define METHOD_IMPL_ATTRIBUTE_NATIVE               0x0001\n#define METHOD_IMPL_ATTRIBUTE_OPTIL                0x0002\n#define METHOD_IMPL_ATTRIBUTE_RUNTIME              0x0003\n\n#define METHOD_IMPL_ATTRIBUTE_MANAGED_MASK         0x0004\n#define METHOD_IMPL_ATTRIBUTE_UNMANAGED            0x0004\n#define METHOD_IMPL_ATTRIBUTE_MANAGED              0x0000\n\n#define METHOD_IMPL_ATTRIBUTE_FORWARD_REF          0x0010\n#define METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG         0x0080\n#define METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL        0x1000\n#define METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED         0x0020\n#define METHOD_IMPL_ATTRIBUTE_NOINLINING           0x0008\n#define METHOD_IMPL_ATTRIBUTE_MAX_METHOD_IMPL_VAL  0xffff\n\n#define METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK        0x0007\n#define METHOD_ATTRIBUTE_COMPILER_CONTROLLED       0x0000\n#define METHOD_ATTRIBUTE_PRIVATE                   0x0001\n#define METHOD_ATTRIBUTE_FAM_AND_ASSEM             0x0002\n#define METHOD_ATTRIBUTE_ASSEM                     0x0003\n#define METHOD_ATTRIBUTE_FAMILY                    0x0004\n#define METHOD_ATTRIBUTE_FAM_OR_ASSEM              0x0005\n#define METHOD_ATTRIBUTE_PUBLIC                    0x0006\n\n#define METHOD_ATTRIBUTE_STATIC                    0x0010\n#define METHOD_ATTRIBUTE_FINAL                     0x0020\n#define METHOD_ATTRIBUTE_VIRTUAL                   0x0040\n#define METHOD_ATTRIBUTE_HIDE_BY_SIG               0x0080\n\n#define METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK        0x0100\n#define METHOD_ATTRIBUTE_REUSE_SLOT                0x0000\n#define METHOD_ATTRIBUTE_NEW_SLOT                  0x0100\n\n#define METHOD_ATTRIBUTE_STRICT                    0x0200\n#define METHOD_ATTRIBUTE_ABSTRACT                  0x0400\n#define METHOD_ATTRIBUTE_SPECIAL_NAME              0x0800\n\n#define METHOD_ATTRIBUTE_PINVOKE_IMPL              0x2000\n#define METHOD_ATTRIBUTE_UNMANAGED_EXPORT          0x0008\n\n/*\n * For runtime use only\n */\n#define METHOD_ATTRIBUTE_RESERVED_MASK             0xd000\n#define METHOD_ATTRIBUTE_RT_SPECIAL_NAME           0x1000\n#define METHOD_ATTRIBUTE_HAS_SECURITY              0x4000\n#define METHOD_ATTRIBUTE_REQUIRE_SEC_OBJECT        0x8000\n\n/*\n* Type Attributes (21.1.13).\n*/\n#define TYPE_ATTRIBUTE_VISIBILITY_MASK       0x00000007\n#define TYPE_ATTRIBUTE_NOT_PUBLIC            0x00000000\n#define TYPE_ATTRIBUTE_PUBLIC                0x00000001\n#define TYPE_ATTRIBUTE_NESTED_PUBLIC         0x00000002\n#define TYPE_ATTRIBUTE_NESTED_PRIVATE        0x00000003\n#define TYPE_ATTRIBUTE_NESTED_FAMILY         0x00000004\n#define TYPE_ATTRIBUTE_NESTED_ASSEMBLY       0x00000005\n#define TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM  0x00000006\n#define TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM   0x00000007\n\n#define TYPE_ATTRIBUTE_LAYOUT_MASK           0x00000018\n#define TYPE_ATTRIBUTE_AUTO_LAYOUT           0x00000000\n#define TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT     0x00000008\n#define TYPE_ATTRIBUTE_EXPLICIT_LAYOUT       0x00000010\n\n#define TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK   0x00000020\n#define TYPE_ATTRIBUTE_CLASS                 0x00000000\n#define TYPE_ATTRIBUTE_INTERFACE             0x00000020\n\n#define TYPE_ATTRIBUTE_ABSTRACT              0x00000080\n#define TYPE_ATTRIBUTE_SEALED                0x00000100\n#define TYPE_ATTRIBUTE_SPECIAL_NAME          0x00000400\n\n#define TYPE_ATTRIBUTE_IMPORT                0x00001000\n#define TYPE_ATTRIBUTE_SERIALIZABLE          0x00002000\n\n#define TYPE_ATTRIBUTE_STRING_FORMAT_MASK    0x00030000\n#define TYPE_ATTRIBUTE_ANSI_CLASS            0x00000000\n#define TYPE_ATTRIBUTE_UNICODE_CLASS         0x00010000\n#define TYPE_ATTRIBUTE_AUTO_CLASS            0x00020000\n\n#define TYPE_ATTRIBUTE_BEFORE_FIELD_INIT     0x00100000\n#define TYPE_ATTRIBUTE_FORWARDER             0x00200000\n\n#define TYPE_ATTRIBUTE_RESERVED_MASK         0x00040800\n#define TYPE_ATTRIBUTE_RT_SPECIAL_NAME       0x00000800\n#define TYPE_ATTRIBUTE_HAS_SECURITY          0x00040000\n\n/*\n* Flags for Params (22.1.12)\n*/\n#define PARAM_ATTRIBUTE_IN                 0x0001\n#define PARAM_ATTRIBUTE_OUT                0x0002\n#define PARAM_ATTRIBUTE_OPTIONAL           0x0010\n#define PARAM_ATTRIBUTE_RESERVED_MASK      0xf000\n#define PARAM_ATTRIBUTE_HAS_DEFAULT        0x1000\n#define PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL  0x2000\n#define PARAM_ATTRIBUTE_UNUSED             0xcfe0\n\n// Flags for Generic Parameters (II.23.1.7)\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_NON_VARIANT                           0x00\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_COVARIANT                             0x01\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_CONTRAVARIANT                         0x02\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_VARIANCE_MASK                         0x03\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT             0x04\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_NOT_NULLABLE_VALUE_TYPE_CONSTRAINT    0x08\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_DEFAULT_CONSTRUCTOR_CONSTRAINT        0x10\n#define IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINT_MASK               0x1C\n\n/**\n * 21.5 AssemblyRefs\n */\n#define ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG      0x00000001\n#define ASSEMBLYREF_RETARGETABLE_FLAG         0x00000100\n#define ASSEMBLYREF_ENABLEJITCOMPILE_TRACKING_FLAG 0x00008000\n#define ASSEMBLYREF_DISABLEJITCOMPILE_OPTIMIZER_FLAG 0x00004000\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/il2cpp_dump.cpp",
    "content": "//\n// Created by Perfare on 2020/7/4.\n//\n\n#include \"il2cpp_dump.h\"\n#include <dlfcn.h>\n#include <cstdlib>\n#include <cstring>\n#include <cinttypes>\n#include <string>\n#include <vector>\n#include <sstream>\n#include <fstream>\n#include <unistd.h>\n#include \"xdl.h\"\n#include \"Includes/log.h\"\n#include \"il2cpp-tabledefs.h\"\n#include \"il2cpp-class.h\"\n#include <jni.h>\n\n\n#define DO_API(r, n, p) r (*n) p\n\n#include \"il2cpp-api-functions.h\"\n\n#undef DO_API\n\nstatic uint64_t il2cpp_base = 0;\n\nconst char *GetPackageName() {\n    //https://stackoverflow.com/questions/42918762/how-to-get-app-package-name-or-applicationid-using-jni-android\n    char *application_id[256];\n    FILE *fp = fopen(\"proc/self/cmdline\", \"r\");\n    if (fp) {\n        fread(application_id, sizeof(application_id), 1, fp);\n        fclose(fp);\n    }\n    return (const char *) application_id;\n}\n\nvoid init_il2cpp_api(void *handle) {\n#define DO_API(r, n, p) n = (r (*) p)dlsym(handle, #n)\n\n// Do not use XDL yet because it doesn't support emulators\n\n/*#define DO_API(r, n, p) {                      \\\n    n = (r (*) p)xdl_sym(handle, #n, nullptr); \\\n    if(!n) {                                   \\\n        LOGW(\"api not found %s\", #n);          \\\n    }                                          \\\n}*/\n\n#include \"il2cpp-api-functions.h\"\n\n#undef DO_API\n}\n\nstd::string get_method_modifier(uint32_t flags) {\n    std::stringstream outPut;\n    auto access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;\n    switch (access) {\n        case METHOD_ATTRIBUTE_PRIVATE:\n            outPut << \"private \";\n            break;\n        case METHOD_ATTRIBUTE_PUBLIC:\n            outPut << \"public \";\n            break;\n        case METHOD_ATTRIBUTE_FAMILY:\n            outPut << \"protected \";\n            break;\n        case METHOD_ATTRIBUTE_ASSEM:\n        case METHOD_ATTRIBUTE_FAM_AND_ASSEM:\n            outPut << \"internal \";\n            break;\n        case METHOD_ATTRIBUTE_FAM_OR_ASSEM:\n            outPut << \"protected internal \";\n            break;\n    }\n    if (flags & METHOD_ATTRIBUTE_STATIC) {\n        outPut << \"static \";\n    }\n    if (flags & METHOD_ATTRIBUTE_ABSTRACT) {\n        outPut << \"abstract \";\n        if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT) {\n            outPut << \"override \";\n        }\n    } else if (flags & METHOD_ATTRIBUTE_FINAL) {\n        if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT) {\n            outPut << \"sealed override \";\n        }\n    } else if (flags & METHOD_ATTRIBUTE_VIRTUAL) {\n        if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_NEW_SLOT) {\n            outPut << \"virtual \";\n        } else {\n            outPut << \"override \";\n        }\n    }\n    if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {\n        outPut << \"extern \";\n    }\n    return outPut.str();\n}\n\nbool _il2cpp_type_is_byref(const Il2CppType *type) {\n    auto byref = type->byref;\n    if (il2cpp_type_is_byref) {\n        byref = il2cpp_type_is_byref(type);\n    }\n    return byref;\n}\n\nstd::string dump_method(Il2CppClass *klass) {\n    std::stringstream outPut;\n    outPut << \"\\n\\t// Methods\\n\";\n    void *iter = nullptr;\n    while (auto method = il2cpp_class_get_methods(klass, &iter)) {\n        //TODO attribute\n        if (method->methodPointer) {\n            outPut << \"\\t// RVA: 0x\";\n            outPut << std::hex << (uint64_t) method->methodPointer - il2cpp_base;\n            outPut << \" VA: 0x\";\n            outPut << std::hex << (uint64_t) method->methodPointer;\n        } else {\n            outPut << \"\\t// RVA: 0x VA: 0x0\";\n        }\n        /*if (method->slot != 65535) {\n        outPut << \" Slot: \" << std::dec << method->slot;\n        }*/\n        outPut << \"\\n\\t\";\n        uint32_t iflags = 0;\n        auto flags = il2cpp_method_get_flags(method, &iflags);\n        outPut << get_method_modifier(flags);\n        //TODO genericContainerIndex\n        auto return_type = il2cpp_method_get_return_type(method);\n        if (_il2cpp_type_is_byref(return_type)) {\n            outPut << \"ref \";\n        }\n        auto return_class = il2cpp_class_from_type(return_type);\n        outPut << il2cpp_class_get_name(return_class) << \" \" << il2cpp_method_get_name(method)\n               << \"(\";\n        auto param_count = il2cpp_method_get_param_count(method);\n        for (int i = 0; i < param_count; ++i) {\n            auto param = il2cpp_method_get_param(method, i);\n            auto attrs = param->attrs;\n            if (_il2cpp_type_is_byref(param)) {\n                if (attrs & PARAM_ATTRIBUTE_OUT && !(attrs & PARAM_ATTRIBUTE_IN)) {\n                    outPut << \"out \";\n                } else if (attrs & PARAM_ATTRIBUTE_IN && !(attrs & PARAM_ATTRIBUTE_OUT)) {\n                    outPut << \"in \";\n                } else {\n                    outPut << \"ref \";\n                }\n            } else {\n                if (attrs & PARAM_ATTRIBUTE_IN) {\n                    outPut << \"[In] \";\n                }\n                if (attrs & PARAM_ATTRIBUTE_OUT) {\n                    outPut << \"[Out] \";\n                }\n            }\n            auto parameter_class = il2cpp_class_from_type(param);\n            outPut << il2cpp_class_get_name(parameter_class) << \" \"\n                   << il2cpp_method_get_param_name(method, i);\n            outPut << \", \";\n        }\n        if (param_count > 0) {\n            outPut.seekp(-2, outPut.cur);\n        }\n        outPut << \") { }\\n\";\n        //TODO GenericInstMethod\n    }\n    return outPut.str();\n}\n\nstd::string dump_property(Il2CppClass *klass) {\n    std::stringstream outPut;\n    outPut << \"\\n\\t// Properties\\n\";\n    void *iter = nullptr;\n    while (auto prop_const = il2cpp_class_get_properties(klass, &iter)) {\n        //TODO attribute\n        auto prop = const_cast<PropertyInfo *>(prop_const);\n        auto get = il2cpp_property_get_get_method(prop);\n        auto set = il2cpp_property_get_set_method(prop);\n        auto prop_name = il2cpp_property_get_name(prop);\n        outPut << \"\\t\";\n        Il2CppClass *prop_class = nullptr;\n        uint32_t iflags = 0;\n        if (get) {\n            outPut << get_method_modifier(il2cpp_method_get_flags(get, &iflags));\n            prop_class = il2cpp_class_from_type(il2cpp_method_get_return_type(get));\n        } else if (set) {\n            outPut << get_method_modifier(il2cpp_method_get_flags(set, &iflags));\n            auto param = il2cpp_method_get_param(set, 0);\n            prop_class = il2cpp_class_from_type(param);\n        }\n        if (prop_class) {\n            outPut << il2cpp_class_get_name(prop_class) << \" \" << prop_name << \" { \";\n            if (get) {\n                outPut << \"get; \";\n            }\n            if (set) {\n                outPut << \"set; \";\n            }\n            outPut << \"}\\n\";\n        } else {\n            if (prop_name) {\n                outPut << \" // unknown property \" << prop_name;\n            }\n        }\n    }\n    return outPut.str();\n}\n\nstd::string dump_field(Il2CppClass *klass) {\n    std::stringstream outPut;\n    outPut << \"\\n\\t// Fields\\n\";\n    auto is_enum = il2cpp_class_is_enum(klass);\n    void *iter = nullptr;\n    while (auto field = il2cpp_class_get_fields(klass, &iter)) {\n        //TODO attribute\n        outPut << \"\\t\";\n        auto attrs = il2cpp_field_get_flags(field);\n        auto access = attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;\n        switch (access) {\n            case FIELD_ATTRIBUTE_PRIVATE:\n                outPut << \"private \";\n                break;\n            case FIELD_ATTRIBUTE_PUBLIC:\n                outPut << \"public \";\n                break;\n            case FIELD_ATTRIBUTE_FAMILY:\n                outPut << \"protected \";\n                break;\n            case FIELD_ATTRIBUTE_ASSEMBLY:\n            case FIELD_ATTRIBUTE_FAM_AND_ASSEM:\n                outPut << \"internal \";\n                break;\n            case FIELD_ATTRIBUTE_FAM_OR_ASSEM:\n                outPut << \"protected internal \";\n                break;\n        }\n        if (attrs & FIELD_ATTRIBUTE_LITERAL) {\n            outPut << \"const \";\n        } else {\n            if (attrs & FIELD_ATTRIBUTE_STATIC) {\n                outPut << \"static \";\n            }\n            if (attrs & FIELD_ATTRIBUTE_INIT_ONLY) {\n                outPut << \"readonly \";\n            }\n        }\n        auto field_type = il2cpp_field_get_type(field);\n        auto field_class = il2cpp_class_from_type(field_type);\n        outPut << il2cpp_class_get_name(field_class) << \" \" << il2cpp_field_get_name(field);\n        //TODO 获取构造函数初始化后的字段值\n        if (attrs & FIELD_ATTRIBUTE_LITERAL && is_enum) {\n            uint64_t val = 0;\n            il2cpp_field_static_get_value(field, &val);\n            outPut << \" = \" << std::dec << val;\n        }\n        outPut << \"; // 0x\" << std::hex << il2cpp_field_get_offset(field) << \"\\n\";\n    }\n    return outPut.str();\n}\n\nstd::string dump_type(const Il2CppType *type) {\n    std::stringstream outPut;\n    auto *klass = il2cpp_class_from_type(type);\n    outPut << \"\\n// Namespace: \" << il2cpp_class_get_namespace(klass) << \"\\n\";\n    auto flags = il2cpp_class_get_flags(klass);\n    if (flags & TYPE_ATTRIBUTE_SERIALIZABLE) {\n        outPut << \"[Serializable]\\n\";\n    }\n    //TODO attribute\n    auto is_valuetype = il2cpp_class_is_valuetype(klass);\n    auto is_enum = il2cpp_class_is_enum(klass);\n    auto visibility = flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;\n    switch (visibility) {\n        case TYPE_ATTRIBUTE_PUBLIC:\n        case TYPE_ATTRIBUTE_NESTED_PUBLIC:\n            outPut << \"public \";\n            break;\n        case TYPE_ATTRIBUTE_NOT_PUBLIC:\n        case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:\n        case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:\n            outPut << \"internal \";\n            break;\n        case TYPE_ATTRIBUTE_NESTED_PRIVATE:\n            outPut << \"private \";\n            break;\n        case TYPE_ATTRIBUTE_NESTED_FAMILY:\n            outPut << \"protected \";\n            break;\n        case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:\n            outPut << \"protected internal \";\n            break;\n    }\n    if (flags & TYPE_ATTRIBUTE_ABSTRACT && flags & TYPE_ATTRIBUTE_SEALED) {\n        outPut << \"static \";\n    } else if (!(flags & TYPE_ATTRIBUTE_INTERFACE) && flags & TYPE_ATTRIBUTE_ABSTRACT) {\n        outPut << \"abstract \";\n    } else if (!is_valuetype && !is_enum && flags & TYPE_ATTRIBUTE_SEALED) {\n        outPut << \"sealed \";\n    }\n    if (flags & TYPE_ATTRIBUTE_INTERFACE) {\n        outPut << \"interface \";\n    } else if (is_enum) {\n        outPut << \"enum \";\n    } else if (is_valuetype) {\n        outPut << \"struct \";\n    } else {\n        outPut << \"class \";\n    }\n    outPut << il2cpp_class_get_name(klass); //TODO genericContainerIndex\n    std::vector<std::string> extends;\n    auto parent = il2cpp_class_get_parent(klass);\n    if (!is_valuetype && !is_enum && parent) {\n        auto parent_type = il2cpp_class_get_type(parent);\n        if (parent_type->type != IL2CPP_TYPE_OBJECT) {\n            extends.emplace_back(il2cpp_class_get_name(parent));\n        }\n    }\n    void *iter = nullptr;\n    while (auto itf = il2cpp_class_get_interfaces(klass, &iter)) {\n        extends.emplace_back(il2cpp_class_get_name(itf));\n    }\n    if (!extends.empty()) {\n        outPut << \" : \" << extends[0];\n        for (int i = 1; i < extends.size(); ++i) {\n            outPut << \", \" << extends[i];\n        }\n    }\n    outPut << \"\\n{\";\n    outPut << dump_field(klass);\n    outPut << dump_property(klass);\n    outPut << dump_method(klass);\n    //TODO EventInfo\n    outPut << \"}\\n\";\n    return outPut.str();\n}\n\nvoid il2cpp_api_init(void *handle) {\n    LOGI(\"il2cpp_handle: %p\", handle);\n    init_il2cpp_api(handle);\n    if (il2cpp_domain_get_assemblies) {\n        Dl_info dlInfo;\n        if (dladdr((void *) il2cpp_domain_get_assemblies, &dlInfo)) {\n            il2cpp_base = reinterpret_cast<uint64_t>(dlInfo.dli_fbase);\n        }\n        LOGI(\"il2cpp_base: %\" PRIx64\"\", il2cpp_base);\n    } else {\n        LOGE(\"Failed to initialize il2cpp api.\");\n        return;\n    }\n    while (!il2cpp_is_vm_thread(nullptr)) {\n        LOGI(\"Waiting for il2cpp_init...\");\n        sleep(1);\n    }\n    auto domain = il2cpp_domain_get();\n    il2cpp_thread_attach(domain);\n}\n\nvoid il2cpp_dump(const char *outDir) {\n    LOGI(\"dumping...\");\n    size_t size;\n    auto domain = il2cpp_domain_get();\n    auto assemblies = il2cpp_domain_get_assemblies(domain, &size);\n    //geokar2006's bypass\n    //auto assemblies = Assembly$$GetAllAssemblies();\n    //LOGI(\"Assemblies size %d\", assemblies->size());\n\n    std::stringstream imageOutput;\n\n    /*for (int i = 0; i < assemblies->size(); ++i) {\n        auto image = il2cpp_assembly_get_image((*assemblies)[i]);*/\n    for (int i = 0; i < size; ++i) {\n        auto image = il2cpp_assembly_get_image(assemblies[i]);\n        imageOutput << \"// Image \" << i << \": \" << il2cpp_image_get_name(image) << \"\\n\";\n    }\n    std::vector<std::string> outPuts;\n    if (il2cpp_image_get_class) {\n        LOGI(\"Version greater than 2018.3\");\n        //使用il2cpp_image_get_class\n        for (int i = 0; i < size; ++i) {\n            auto image = il2cpp_assembly_get_image(assemblies[i]);\n            /*for (auto &assemblie: *assemblies) {\n                auto image = il2cpp_assembly_get_image(assemblie);*/\n            std::stringstream imageStr;\n            imageStr << \"\\n// Dll : \" << il2cpp_image_get_name(image);\n            auto classCount = il2cpp_image_get_class_count(image);\n            for (int j = 0; j < classCount; ++j) {\n                auto klass = il2cpp_image_get_class(image, j);\n                auto type = il2cpp_class_get_type(const_cast<Il2CppClass *>(klass));\n                //LOGD(\"type name : %s\", il2cpp_type_get_name(type));\n                auto outPut = imageStr.str() + dump_type(type);\n                outPuts.push_back(outPut);\n            }\n        }\n    } else {\n        LOGI(\"Version less than 2018.3\");\n        //使用反射\n        auto corlib = il2cpp_get_corlib();\n        auto assemblyClass = il2cpp_class_from_name(corlib, \"System.Reflection\", \"Assembly\");\n        auto assemblyLoad = il2cpp_class_get_method_from_name(assemblyClass, \"Load\", 1);\n        auto assemblyGetTypes = il2cpp_class_get_method_from_name(assemblyClass, \"GetTypes\", 0);\n        if (assemblyLoad && assemblyLoad->methodPointer) {\n            LOGI(\"Assembly::Load: %p\", assemblyLoad->methodPointer);\n        } else {\n            LOGI(\"miss Assembly::Load\");\n            return;\n        }\n        if (assemblyGetTypes && assemblyGetTypes->methodPointer) {\n            LOGI(\"Assembly::GetTypes: %p\", assemblyGetTypes->methodPointer);\n        } else {\n            LOGI(\"miss Assembly::GetTypes\");\n            return;\n        }\n        typedef void *(*Assembly_Load_ftn)(void *, Il2CppString *, void *);\n        typedef Il2CppArray *(*Assembly_GetTypes_ftn)(void *, void *);\n        for (int i = 0; i < size; ++i) {\n            auto image = il2cpp_assembly_get_image(assemblies[i]);\n            /*for (int i = 0; i < assemblies->size(); ++i) {\n                auto image = il2cpp_assembly_get_image((*assemblies)[i]);*/\n            std::stringstream imageStr;\n            auto image_name = il2cpp_image_get_name(image);\n            imageStr << \"\\n// Dll : \" << image_name;\n            //LOGD(\"image name : %s\", image->name);\n            auto imageName = std::string(image_name);\n            auto pos = imageName.rfind('.');\n            auto imageNameNoExt = imageName.substr(0, pos);\n            auto assemblyFileName = il2cpp_string_new(imageNameNoExt.data());\n            auto reflectionAssembly = ((Assembly_Load_ftn) assemblyLoad->methodPointer)(nullptr,\n                                                                                        assemblyFileName,\n                                                                                        nullptr);\n            auto reflectionTypes = ((Assembly_GetTypes_ftn) assemblyGetTypes->methodPointer)(\n                    reflectionAssembly, nullptr);\n            auto items = reflectionTypes->vector;\n            for (int j = 0; j < reflectionTypes->max_length; ++j) {\n                auto klass = il2cpp_class_from_system_type((Il2CppReflectionType *) items[j]);\n                auto type = il2cpp_class_get_type(klass);\n                //LOGD(\"type name : %s\", il2cpp_type_get_name(type));\n                auto outPut = imageStr.str() + dump_type(type);\n                outPuts.push_back(outPut);\n            }\n        }\n    }\n\t\n    auto outPath = std::string(outDir);\n\t\n\tLOGI(\"Save dump file to %s\", outPath.c_str());\n\t\n    std::ofstream outStream(outPath);\n    outStream << imageOutput.str();\n    auto count = outPuts.size();\n    for (int i = 0; i < count; ++i) {\n        outStream << outPuts[i];\n    }\n    outStream.close();\n\n    LOGI(\"dump done!\");\n}"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/il2cpp_dump.h",
    "content": "//\n// Created by Perfare on 2020/7/4.\n//\n\n#ifndef AUTO_IL2CPPDUMPER_IL2CPP_DUMP_H\n#define AUTO_IL2CPPDUMPER_IL2CPP_DUMP_H\n\nvoid il2cpp_api_init(void *handle);\n\nvoid il2cpp_dump(const char *outDir);\n\nconst char* GetPackageName();\n\n#endif //AUTO_IL2CPPDUMPER_IL2CPP_DUMP_H\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/include/xdl.h",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n//\n// xDL version: 2.0.0\n//\n// xDL is an enhanced implementation of the Android DL series functions.\n// For more information, documentation, and the latest version please check:\n// https://github.com/hexhacking/xDL\n//\n\n#ifndef IO_GITHUB_HEXHACKING_XDL\n#define IO_GITHUB_HEXHACKING_XDL\n\n#include <dlfcn.h>\n#include <link.h>\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct {\n  // same as Dl_info:\n  const char *dli_fname;  // Pathname of shared object that contains address.\n  void *dli_fbase;        // Address at which shared object is loaded.\n  const char *dli_sname;  // Name of nearest symbol with address lower than addr.\n  void *dli_saddr;        // Exact address of symbol named in dli_sname.\n  // added by xDL:\n  size_t dli_ssize;             // Symbol size of nearest symbol with address lower than addr.\n  const ElfW(Phdr) *dlpi_phdr;  // Pointer to array of ELF program headers for this object.\n  size_t dlpi_phnum;            // Number of items in dlpi_phdr.\n} xdl_info_t;\n\n//\n// Default value for flags in both xdl_open() and xdl_iterate_phdr().\n//\n#define XDL_DEFAULT 0x00\n\n//\n// Enhanced dlopen() / dlclose() / dlsym().\n//\n#define XDL_TRY_FORCE_LOAD    0x01\n#define XDL_ALWAYS_FORCE_LOAD 0x02\nvoid *xdl_open(const char *filename, int flags);\nvoid *xdl_close(void *handle);\nvoid *xdl_sym(void *handle, const char *symbol, size_t *symbol_size);\nvoid *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size);\n\n//\n// Enhanced dladdr().\n//\nint xdl_addr(void *addr, xdl_info_t *info, void **cache);\nvoid xdl_addr_clean(void **cache);\n\n//\n// Enhanced dl_iterate_phdr().\n//\n#define XDL_FULL_PATHNAME 0x01\nint xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags);\n\n//\n// Custom dlinfo().\n//\n#define XDL_DI_DLINFO 1  // type of info: xdl_info_t\nint xdl_info(void *handle, int request, void *info);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl.c",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n#include \"xdl.h\"\n\n#include <android/api-level.h>\n#include <elf.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <link.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/auxv.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"xdl_iterate.h\"\n#include \"xdl_linker.h\"\n#include \"xdl_lzma.h\"\n#include \"xdl_util.h\"\n\n#ifndef __LP64__\n#define XDL_LIB_PATH \"/system/lib\"\n#else\n#define XDL_LIB_PATH \"/system/lib64\"\n#endif\n\n#define XDL_DYNSYM_IS_EXPORT_SYM(shndx) (SHN_UNDEF != (shndx))\n#define XDL_SYMTAB_IS_EXPORT_SYM(shndx) \\\n  (SHN_UNDEF != (shndx) && !((shndx) >= SHN_LORESERVE && (shndx) <= SHN_HIRESERVE))\n\nextern __attribute((weak)) unsigned long int getauxval(unsigned long int);\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n\ntypedef struct xdl {\n  char *pathname;\n  uintptr_t load_bias;\n  const ElfW(Phdr) *dlpi_phdr;\n  ElfW(Half) dlpi_phnum;\n\n  struct xdl *next;     // to next xdl obj for cache in xdl_addr()\n  void *linker_handle;  // hold handle returned by xdl_linker_force_dlopen()\n\n  //\n  // (1) for searching symbols from .dynsym\n  //\n\n  bool dynsym_try_load;\n  ElfW(Sym) *dynsym;   // .dynsym\n  const char *dynstr;  // .dynstr\n\n  // .hash (SYSV hash for .dynstr)\n  struct {\n    const uint32_t *buckets;\n    uint32_t buckets_cnt;\n    const uint32_t *chains;\n    uint32_t chains_cnt;\n  } sysv_hash;\n\n  // .gnu.hash (GNU hash for .dynstr)\n  struct {\n    const uint32_t *buckets;\n    uint32_t buckets_cnt;\n    const uint32_t *chains;\n    uint32_t symoffset;\n    const ElfW(Addr) *bloom;\n    uint32_t bloom_cnt;\n    uint32_t bloom_shift;\n  } gnu_hash;\n\n  //\n  // (2) for searching symbols from .symtab\n  //\n\n  bool symtab_try_load;\n  uintptr_t base;\n\n  ElfW(Sym) *symtab;  // .symtab\n  size_t symtab_cnt;\n  char *strtab;  // .strtab\n  size_t strtab_sz;\n} xdl_t;\n\n#pragma clang diagnostic pop\n\n// load from memory\nstatic int xdl_dynsym_load(xdl_t *self) {\n  // find the dynamic segment\n  ElfW(Dyn) *dynamic = NULL;\n  for (size_t i = 0; i < self->dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(self->dlpi_phdr[i]);\n    if (PT_DYNAMIC == phdr->p_type) {\n      dynamic = (ElfW(Dyn) *)(self->load_bias + phdr->p_vaddr);\n      break;\n    }\n  }\n  if (NULL == dynamic) return -1;\n\n  // iterate the dynamic segment\n  for (ElfW(Dyn) *entry = dynamic; entry && entry->d_tag != DT_NULL; entry++) {\n    switch (entry->d_tag) {\n      case DT_SYMTAB:  //.dynsym\n        self->dynsym = (ElfW(Sym) *)(self->load_bias + entry->d_un.d_ptr);\n        break;\n      case DT_STRTAB:  //.dynstr\n        self->dynstr = (const char *)(self->load_bias + entry->d_un.d_ptr);\n        break;\n      case DT_HASH:  //.hash\n        self->sysv_hash.buckets_cnt = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[0];\n        self->sysv_hash.chains_cnt = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[1];\n        self->sysv_hash.buckets = &(((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[2]);\n        self->sysv_hash.chains = &(self->sysv_hash.buckets[self->sysv_hash.buckets_cnt]);\n        break;\n      case DT_GNU_HASH:  //.gnu.hash\n        self->gnu_hash.buckets_cnt = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[0];\n        self->gnu_hash.symoffset = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[1];\n        self->gnu_hash.bloom_cnt = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[2];\n        self->gnu_hash.bloom_shift = ((const uint32_t *)(self->load_bias + entry->d_un.d_ptr))[3];\n        self->gnu_hash.bloom = (const ElfW(Addr) *)(self->load_bias + entry->d_un.d_ptr + 16);\n        self->gnu_hash.buckets = (const uint32_t *)(&(self->gnu_hash.bloom[self->gnu_hash.bloom_cnt]));\n        self->gnu_hash.chains = (const uint32_t *)(&(self->gnu_hash.buckets[self->gnu_hash.buckets_cnt]));\n        break;\n      default:\n        break;\n    }\n  }\n\n  if (NULL == self->dynsym || NULL == self->dynstr ||\n      (0 == self->sysv_hash.buckets_cnt && 0 == self->gnu_hash.buckets_cnt)) {\n    self->dynsym = NULL;\n    self->dynstr = NULL;\n    self->sysv_hash.buckets_cnt = 0;\n    self->gnu_hash.buckets_cnt = 0;\n    return -1;\n  }\n\n  return 0;\n}\n\nstatic void *xdl_read_file_to_heap(int file_fd, size_t file_sz, size_t data_offset, size_t data_len) {\n  if (0 == data_len) return NULL;\n  if (data_offset >= file_sz) return NULL;\n  if (data_offset + data_len > file_sz) return NULL;\n\n  if (data_offset != (size_t)lseek(file_fd, (off_t)data_offset, SEEK_SET)) return NULL;\n\n  void *data = malloc(data_len);\n  if (NULL == data) return NULL;\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wgnu-statement-expression\"\n  if ((ssize_t)data_len != XDL_UTIL_TEMP_FAILURE_RETRY(read(file_fd, data, data_len)))\n#pragma clang diagnostic pop\n  {\n    free(data);\n    return NULL;\n  }\n\n  return data;\n}\n\nstatic void *xdl_read_file_to_heap_by_section(int file_fd, size_t file_sz, ElfW(Shdr) *shdr) {\n  return xdl_read_file_to_heap(file_fd, file_sz, (size_t)shdr->sh_offset, shdr->sh_size);\n}\n\nstatic void *xdl_read_memory_to_heap(void *mem, size_t mem_sz, size_t data_offset, size_t data_len) {\n  if (0 == data_len) return NULL;\n  if (data_offset >= mem_sz) return NULL;\n  if (data_offset + data_len > mem_sz) return NULL;\n\n  void *data = malloc(data_len);\n  if (NULL == data) return NULL;\n\n  memcpy(data, (void *)((uintptr_t)mem + data_offset), data_len);\n  return data;\n}\n\nstatic void *xdl_read_memory_to_heap_by_section(void *mem, size_t mem_sz, ElfW(Shdr) *shdr) {\n  return xdl_read_memory_to_heap(mem, mem_sz, (size_t)shdr->sh_offset, shdr->sh_size);\n}\n\nstatic void *xdl_get_memory(void *mem, size_t mem_sz, size_t data_offset, size_t data_len) {\n  if (0 == data_len) return NULL;\n  if (data_offset >= mem_sz) return NULL;\n  if (data_offset + data_len > mem_sz) return NULL;\n\n  return (void *)((uintptr_t)mem + data_offset);\n}\n\nstatic void *xdl_get_memory_by_section(void *mem, size_t mem_sz, ElfW(Shdr) *shdr) {\n  return xdl_get_memory(mem, mem_sz, (size_t)shdr->sh_offset, shdr->sh_size);\n}\n\n// load from disk and memory\nstatic int xdl_symtab_load_from_debugdata(xdl_t *self, int file_fd, size_t file_sz,\n                                          ElfW(Shdr) *shdr_debugdata) {\n  void *debugdata = NULL;\n  ElfW(Shdr) *shdrs = NULL;\n  int r = -1;\n\n  // get zipped .gnu_debugdata\n  uint8_t *debugdata_zip = (uint8_t *)xdl_read_file_to_heap_by_section(file_fd, file_sz, shdr_debugdata);\n  if (NULL == debugdata_zip) return -1;\n\n  // get unzipped .gnu_debugdata\n  size_t debugdata_sz;\n  if (0 != xdl_lzma_decompress(debugdata_zip, shdr_debugdata->sh_size, (uint8_t **)&debugdata, &debugdata_sz))\n    goto end;\n\n  // get ELF header\n  ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)debugdata;\n  if (0 == ehdr->e_shnum || ehdr->e_shentsize != sizeof(ElfW(Shdr))) goto end;\n\n  // get section headers\n  shdrs = (ElfW(Shdr) *)xdl_read_memory_to_heap(debugdata, debugdata_sz, (size_t)ehdr->e_shoff,\n                                                ehdr->e_shentsize * ehdr->e_shnum);\n  if (NULL == shdrs) goto end;\n\n  // get .shstrtab\n  if (SHN_UNDEF == ehdr->e_shstrndx || ehdr->e_shstrndx >= ehdr->e_shnum) goto end;\n  char *shstrtab = (char *)xdl_get_memory_by_section(debugdata, debugdata_sz, shdrs + ehdr->e_shstrndx);\n  if (NULL == shstrtab) goto end;\n\n  // find .symtab & .strtab\n  for (ElfW(Shdr) *shdr = shdrs; shdr < shdrs + ehdr->e_shnum; shdr++) {\n    char *shdr_name = shstrtab + shdr->sh_name;\n\n    if (SHT_SYMTAB == shdr->sh_type && 0 == strcmp(\".symtab\", shdr_name)) {\n      // get & check associated .strtab section\n      if (shdr->sh_link >= ehdr->e_shnum) continue;\n      ElfW(Shdr) *shdr_strtab = shdrs + shdr->sh_link;\n      if (SHT_STRTAB != shdr_strtab->sh_type) continue;\n\n      // get .symtab & .strtab\n      ElfW(Sym) *symtab = (ElfW(Sym) *)xdl_read_memory_to_heap_by_section(debugdata, debugdata_sz, shdr);\n      if (NULL == symtab) continue;\n      char *strtab = (char *)xdl_read_memory_to_heap_by_section(debugdata, debugdata_sz, shdr_strtab);\n      if (NULL == strtab) {\n        free(symtab);\n        continue;\n      }\n\n      // OK\n      self->symtab = symtab;\n      self->symtab_cnt = shdr->sh_size / shdr->sh_entsize;\n      self->strtab = strtab;\n      self->strtab_sz = shdr_strtab->sh_size;\n      r = 0;\n      break;\n    }\n  }\n\nend:\n  free(debugdata_zip);\n  if (NULL != debugdata) free(debugdata);\n  if (NULL != shdrs) free(shdrs);\n  return r;\n}\n\n// load from disk and memory\nstatic int xdl_symtab_load(xdl_t *self) {\n  if ('[' == self->pathname[0]) return -1;\n\n  int r = -1;\n  ElfW(Shdr) *shdrs = NULL;\n  char *shstrtab = NULL;\n\n  // get base address\n  uintptr_t vaddr_min = UINTPTR_MAX;\n  for (size_t i = 0; i < self->dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(self->dlpi_phdr[i]);\n    if (PT_LOAD == phdr->p_type) {\n      if (vaddr_min > phdr->p_vaddr) vaddr_min = phdr->p_vaddr;\n    }\n  }\n  if (UINTPTR_MAX == vaddr_min) return -1;\n  self->base = self->load_bias + vaddr_min;\n\n  // open file\n  int flags = O_RDONLY | O_CLOEXEC;\n  int file_fd;\n  if ('/' == self->pathname[0]) {\n    file_fd = open(self->pathname, flags);\n  } else {\n    char full_pathname[1024];\n    // try the fast method\n    snprintf(full_pathname, sizeof(full_pathname), \"%s/%s\", XDL_LIB_PATH, self->pathname);\n    file_fd = open(full_pathname, flags);\n    if (file_fd < 0) {\n      // try the slow method\n      if (0 != xdl_iterate_get_full_pathname(self->base, full_pathname, sizeof(full_pathname))) return -1;\n      file_fd = open(full_pathname, flags);\n    }\n  }\n  if (file_fd < 0) return -1;\n  struct stat st;\n  if (0 != fstat(file_fd, &st)) goto end;\n  size_t file_sz = (size_t)st.st_size;\n\n  // get ELF header\n  ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)self->base;\n  if (0 == ehdr->e_shnum || ehdr->e_shentsize != sizeof(ElfW(Shdr))) goto end;\n\n  // get section headers\n  shdrs = (ElfW(Shdr) *)xdl_read_file_to_heap(file_fd, file_sz, (size_t)ehdr->e_shoff,\n                                              ehdr->e_shentsize * ehdr->e_shnum);\n  if (NULL == shdrs) goto end;\n\n  // get .shstrtab\n  if (SHN_UNDEF == ehdr->e_shstrndx || ehdr->e_shstrndx >= ehdr->e_shnum) goto end;\n  shstrtab = (char *)xdl_read_file_to_heap_by_section(file_fd, file_sz, shdrs + ehdr->e_shstrndx);\n  if (NULL == shstrtab) goto end;\n\n  // find .symtab & .strtab\n  for (ElfW(Shdr) *shdr = shdrs; shdr < shdrs + ehdr->e_shnum; shdr++) {\n    char *shdr_name = shstrtab + shdr->sh_name;\n\n    if (SHT_SYMTAB == shdr->sh_type && 0 == strcmp(\".symtab\", shdr_name)) {\n      // get & check associated .strtab section\n      if (shdr->sh_link >= ehdr->e_shnum) continue;\n      ElfW(Shdr) *shdr_strtab = shdrs + shdr->sh_link;\n      if (SHT_STRTAB != shdr_strtab->sh_type) continue;\n\n      // get .symtab & .strtab\n      ElfW(Sym) *symtab = (ElfW(Sym) *)xdl_read_file_to_heap_by_section(file_fd, file_sz, shdr);\n      if (NULL == symtab) continue;\n      char *strtab = (char *)xdl_read_file_to_heap_by_section(file_fd, file_sz, shdr_strtab);\n      if (NULL == strtab) {\n        free(symtab);\n        continue;\n      }\n\n      // OK\n      self->symtab = symtab;\n      self->symtab_cnt = shdr->sh_size / shdr->sh_entsize;\n      self->strtab = strtab;\n      self->strtab_sz = shdr_strtab->sh_size;\n      r = 0;\n      break;\n    } else if (SHT_PROGBITS == shdr->sh_type && 0 == strcmp(\".gnu_debugdata\", shdr_name)) {\n      if (0 == xdl_symtab_load_from_debugdata(self, file_fd, file_sz, shdr)) {\n        // OK\n        r = 0;\n        break;\n      }\n    }\n  }\n\nend:\n  close(file_fd);\n  if (NULL != shdrs) free(shdrs);\n  if (NULL != shstrtab) free(shstrtab);\n  return r;\n}\n\nstatic xdl_t *xdl_find_from_auxv(unsigned long type, const char *pathname) {\n  if (NULL == getauxval) return NULL;  // API level < 18\n\n  uintptr_t val = (uintptr_t)getauxval(type);\n  if (0 == val) return NULL;\n\n  // get base\n  uintptr_t base = (AT_PHDR == type ? (val & (~0xffful)) : val);\n  if (0 != memcmp((void *)base, ELFMAG, SELFMAG)) return NULL;\n\n  // ELF info\n  ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base;\n  const ElfW(Phdr) *dlpi_phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);\n  ElfW(Half) dlpi_phnum = ehdr->e_phnum;\n\n  // get bias\n  uintptr_t min_vaddr = UINTPTR_MAX;\n  for (size_t i = 0; i < dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(dlpi_phdr[i]);\n    if (PT_LOAD == phdr->p_type) {\n      if (min_vaddr > phdr->p_vaddr) min_vaddr = phdr->p_vaddr;\n    }\n  }\n  if (UINTPTR_MAX == min_vaddr || base < min_vaddr) return NULL;\n  uintptr_t load_bias = base - min_vaddr;\n\n  // create xDL object\n  xdl_t *self;\n  if (NULL == (self = calloc(1, sizeof(xdl_t)))) return NULL;\n  if (NULL == (self->pathname = strdup(pathname))) {\n    free(self);\n    return NULL;\n  }\n  self->load_bias = load_bias;\n  self->dlpi_phdr = dlpi_phdr;\n  self->dlpi_phnum = dlpi_phnum;\n  self->dynsym_try_load = false;\n  self->symtab_try_load = false;\n  return self;\n}\n\nstatic int xdl_find_iterate_cb(struct dl_phdr_info *info, size_t size, void *arg) {\n  (void)size;\n\n  uintptr_t *pkg = (uintptr_t *)arg;\n  xdl_t **self = (xdl_t **)*pkg++;\n  const char *filename = (const char *)*pkg;\n\n  // check load_bias\n  if (0 == info->dlpi_addr || NULL == info->dlpi_name) return 0;\n\n  // check pathname\n  if ('[' == filename[0]) {\n    if (0 != strcmp(info->dlpi_name, filename)) return 0;\n  } else if ('/' == filename[0]) {\n    if ('/' == info->dlpi_name[0]) {\n      if (0 != strcmp(info->dlpi_name, filename)) return 0;\n    } else {\n      if (!xdl_util_ends_with(filename, info->dlpi_name)) return 0;\n    }\n  } else {\n    if ('/' == info->dlpi_name[0]) {\n      if (!xdl_util_ends_with(info->dlpi_name, filename)) return 0;\n    } else {\n      if (0 != strcmp(info->dlpi_name, filename)) return 0;\n    }\n  }\n\n  // found the target ELF\n  if (NULL == ((*self) = calloc(1, sizeof(xdl_t)))) return 1;  // return failed\n  if (NULL == ((*self)->pathname = strdup(info->dlpi_name))) {\n    free(*self);\n    *self = NULL;\n    return 1;  // return failed\n  }\n  (*self)->load_bias = info->dlpi_addr;\n  (*self)->dlpi_phdr = info->dlpi_phdr;\n  (*self)->dlpi_phnum = info->dlpi_phnum;\n  (*self)->dynsym_try_load = false;\n  (*self)->symtab_try_load = false;\n  return 1;  // return OK\n}\n\nstatic xdl_t *xdl_find(const char *filename) {\n  // from auxv (linker, vDSO)\n  xdl_t *self = NULL;\n  if (xdl_util_ends_with(filename, XDL_UTIL_LINKER_BASENAME))\n    self = xdl_find_from_auxv(AT_BASE, XDL_UTIL_LINKER_PATHNAME);\n  else if (xdl_util_ends_with(filename, XDL_UTIL_VDSO_BASENAME))\n    self = xdl_find_from_auxv(AT_SYSINFO_EHDR, XDL_UTIL_VDSO_BASENAME);\n\n  // from auxv (app_process)\n  const char *basename, *pathname;\n#if (defined(__arm__) || defined(__i386__)) && __ANDROID_API__ < __ANDROID_API_L__\n  if (xdl_util_get_api_level() < __ANDROID_API_L__) {\n    basename = XDL_UTIL_APP_PROCESS_BASENAME_K;\n    pathname = XDL_UTIL_APP_PROCESS_PATHNAME_K;\n  } else\n#endif\n  {\n    basename = XDL_UTIL_APP_PROCESS_BASENAME;\n    pathname = XDL_UTIL_APP_PROCESS_PATHNAME;\n  }\n  if (xdl_util_ends_with(filename, basename)) self = xdl_find_from_auxv(AT_PHDR, pathname);\n\n  if (NULL != self) return self;\n\n  // from dl_iterate_phdr\n  uintptr_t pkg[2] = {(uintptr_t)&self, (uintptr_t)filename};\n  xdl_iterate_phdr(xdl_find_iterate_cb, pkg, XDL_DEFAULT);\n  return self;\n}\n\nstatic void *xdl_open_always_force(const char *filename) {\n  // always force dlopen()\n  void *linker_handle = xdl_linker_force_dlopen(filename);\n  if (NULL == linker_handle) return NULL;\n\n  // find\n  xdl_t *self = xdl_find(filename);\n  if (NULL == self)\n    dlclose(linker_handle);\n  else\n    self->linker_handle = linker_handle;\n\n  return (void *)self;\n}\n\nstatic void *xdl_open_try_force(const char *filename) {\n  // find\n  xdl_t *self = xdl_find(filename);\n  if (NULL != self) return (void *)self;\n\n  // try force dlopen()\n  void *linker_handle = xdl_linker_force_dlopen(filename);\n  if (NULL == linker_handle) return NULL;\n\n  // find again\n  self = xdl_find(filename);\n  if (NULL == self)\n    dlclose(linker_handle);\n  else\n    self->linker_handle = linker_handle;\n\n  return (void *)self;\n}\n\nvoid *xdl_open(const char *filename, int flags) {\n  if (NULL == filename) return NULL;\n\n  if (flags & XDL_ALWAYS_FORCE_LOAD)\n    return xdl_open_always_force(filename);\n  else if (flags & XDL_TRY_FORCE_LOAD)\n    return xdl_open_try_force(filename);\n  else\n    return xdl_find(filename);\n}\n\nvoid *xdl_close(void *handle) {\n  if (NULL == handle) return NULL;\n\n  xdl_t *self = (xdl_t *)handle;\n  if (NULL != self->pathname) free(self->pathname);\n  if (NULL != self->symtab) free(self->symtab);\n  if (NULL != self->strtab) free(self->strtab);\n\n  void *linker_handle = self->linker_handle;\n  free(self);\n  return linker_handle;\n}\n\nstatic uint32_t xdl_sysv_hash(const uint8_t *name) {\n  uint32_t h = 0, g;\n\n  while (*name) {\n    h = (h << 4) + *name++;\n    g = h & 0xf0000000;\n    h ^= g;\n    h ^= g >> 24;\n  }\n  return h;\n}\n\nstatic uint32_t xdl_gnu_hash(const uint8_t *name) {\n  uint32_t h = 5381;\n\n  while (*name) {\n    h += (h << 5) + *name++;\n  }\n  return h;\n}\n\nstatic ElfW(Sym) *xdl_dynsym_find_symbol_use_sysv_hash(xdl_t *self, const char *sym_name) {\n  uint32_t hash = xdl_sysv_hash((const uint8_t *)sym_name);\n\n  for (uint32_t i = self->sysv_hash.buckets[hash % self->sysv_hash.buckets_cnt]; 0 != i;\n       i = self->sysv_hash.chains[i]) {\n    ElfW(Sym) *sym = self->dynsym + i;\n    if (0 != strcmp(self->dynstr + sym->st_name, sym_name)) continue;\n    return sym;\n  }\n\n  return NULL;\n}\n\nstatic ElfW(Sym) *xdl_dynsym_find_symbol_use_gnu_hash(xdl_t *self, const char *sym_name) {\n  uint32_t hash = xdl_gnu_hash((const uint8_t *)sym_name);\n\n  static uint32_t elfclass_bits = sizeof(ElfW(Addr)) * 8;\n  size_t word = self->gnu_hash.bloom[(hash / elfclass_bits) % self->gnu_hash.bloom_cnt];\n  size_t mask = 0 | (size_t)1 << (hash % elfclass_bits) |\n                (size_t)1 << ((hash >> self->gnu_hash.bloom_shift) % elfclass_bits);\n\n  // if at least one bit is not set, this symbol is surely missing\n  if ((word & mask) != mask) return NULL;\n\n  // ignore STN_UNDEF\n  uint32_t i = self->gnu_hash.buckets[hash % self->gnu_hash.buckets_cnt];\n  if (i < self->gnu_hash.symoffset) return NULL;\n\n  // loop through the chain\n  while (1) {\n    ElfW(Sym) *sym = self->dynsym + i;\n    uint32_t sym_hash = self->gnu_hash.chains[i - self->gnu_hash.symoffset];\n\n    if ((hash | (uint32_t)1) == (sym_hash | (uint32_t)1)) {\n      if (0 == strcmp(self->dynstr + sym->st_name, sym_name)) {\n        return sym;\n      }\n    }\n\n    // chain ends with an element with the lowest bit set to 1\n    if (sym_hash & (uint32_t)1) break;\n\n    i++;\n  }\n\n  return NULL;\n}\n\nvoid *xdl_sym(void *handle, const char *symbol, size_t *symbol_size) {\n  if (NULL == handle || NULL == symbol) return NULL;\n  if (NULL != symbol_size) *symbol_size = 0;\n\n  xdl_t *self = (xdl_t *)handle;\n\n  // load .dynsym only once\n  if (!self->dynsym_try_load) {\n    self->dynsym_try_load = true;\n    if (0 != xdl_dynsym_load(self)) return NULL;\n  }\n\n  // find symbol\n  if (NULL == self->dynsym) return NULL;\n  ElfW(Sym) *sym = NULL;\n  if (self->gnu_hash.buckets_cnt > 0) {\n    // use GNU hash (.gnu.hash -> .dynsym -> .dynstr), O(x) + O(1) + O(1)\n    sym = xdl_dynsym_find_symbol_use_gnu_hash(self, symbol);\n  }\n  if (NULL == sym && self->sysv_hash.buckets_cnt > 0) {\n    // use SYSV hash (.hash -> .dynsym -> .dynstr), O(x) + O(1) + O(1)\n    sym = xdl_dynsym_find_symbol_use_sysv_hash(self, symbol);\n  }\n  if (NULL == sym || !XDL_DYNSYM_IS_EXPORT_SYM(sym->st_shndx)) return NULL;\n\n  if (NULL != symbol_size) *symbol_size = sym->st_size;\n  return (void *)(self->load_bias + sym->st_value);\n}\n\n// clang-format off\n/*\n * For internal symbols in .symtab, LLVM may add some suffixes (for example for thinLTO).\n * The format of the suffix is: \".xxxx.[hash]\". LLVM may add multiple suffixes at once.\n * The symbol name after removing these all suffixes is called canonical name.\n *\n * Because the hash part in the suffix may change when recompiled, so here we only match\n * the canonical name.\n *\n * IN ADDITION: According to C/C++ syntax, it is illegal for a function name to contain\n * dot character('.'), either in the middle or at the end.\n *\n * samples:\n *\n * symbol name in .symtab          lookup                       is match\n * ----------------------          ----------------             --------\n * abcd                            abc                          N\n * abcd                            abcd                         Y\n * abcd.llvm.10190306339727611508  abc                          N\n * abcd.llvm.10190306339727611508  abcd                         Y\n * abcd.llvm.10190306339727611508  abcd.                        N\n * abcd.llvm.10190306339727611508  abcd.llvm                    Y\n * abcd.llvm.10190306339727611508  abcd.llvm.                   N\n * abcd.__uniq.513291356003753     abcd.__uniq.51329            N\n * abcd.__uniq.513291356003753     abcd.__uniq.513291356003753  Y\n */\n// clang-format on\nstatic inline bool xdl_dsym_is_match(const char *str, const char *sym, size_t str_len) {\n  if (__predict_false(0 == str_len)) return false;\n\n  do {\n    if (*str != *sym) return __predict_false('.' == *str && '\\0' == *sym);\n    str++;\n    sym++;\n    if ('\\0' == *str) break;\n  } while (0 != --str_len);\n\n  return true;\n}\n\nvoid *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size) {\n  if (NULL == handle || NULL == symbol) return NULL;\n  if (NULL != symbol_size) *symbol_size = 0;\n\n  xdl_t *self = (xdl_t *)handle;\n\n  // load .symtab only once\n  if (!self->symtab_try_load) {\n    self->symtab_try_load = true;\n    if (0 != xdl_symtab_load(self)) return NULL;\n  }\n\n  // find symbol\n  if (NULL == self->symtab) return NULL;\n  for (size_t i = 0; i < self->symtab_cnt; i++) {\n    ElfW(Sym) *sym = self->symtab + i;\n\n    if (!XDL_SYMTAB_IS_EXPORT_SYM(sym->st_shndx)) continue;\n    // if (0 != strncmp(self->strtab + sym->st_name, symbol, self->strtab_sz - sym->st_name)) continue;\n    if (!xdl_dsym_is_match(self->strtab + sym->st_name, symbol, self->strtab_sz - sym->st_name)) continue;\n\n    if (NULL != symbol_size) *symbol_size = sym->st_size;\n    return (void *)(self->load_bias + sym->st_value);\n  }\n\n  return NULL;\n}\n\nstatic bool xdl_elf_is_match(uintptr_t load_bias, const ElfW(Phdr) *dlpi_phdr, ElfW(Half) dlpi_phnum,\n                             uintptr_t addr) {\n  if (addr < load_bias) return false;\n\n  uintptr_t vaddr = addr - load_bias;\n  for (size_t i = 0; i < dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(dlpi_phdr[i]);\n    if (PT_LOAD != phdr->p_type) continue;\n\n    if (phdr->p_vaddr <= vaddr && vaddr < phdr->p_vaddr + phdr->p_memsz) return true;\n  }\n\n  return false;\n}\n\nstatic int xdl_open_by_addr_iterate_cb(struct dl_phdr_info *info, size_t size, void *arg) {\n  (void)size;\n\n  uintptr_t *pkg = (uintptr_t *)arg;\n  xdl_t **self = (xdl_t **)*pkg++;\n  uintptr_t addr = *pkg;\n\n  if (xdl_elf_is_match(info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum, addr)) {\n    // found the target ELF\n    if (NULL == ((*self) = calloc(1, sizeof(xdl_t)))) return 1;  // failed\n    if (NULL == ((*self)->pathname = strdup(info->dlpi_name))) {\n      free(*self);\n      *self = NULL;\n      return 1;  // failed\n    }\n    (*self)->load_bias = info->dlpi_addr;\n    (*self)->dlpi_phdr = info->dlpi_phdr;\n    (*self)->dlpi_phnum = info->dlpi_phnum;\n    (*self)->dynsym_try_load = false;\n    (*self)->symtab_try_load = false;\n    return 1;  // OK\n  }\n\n  return 0;  // mismatch\n}\n\nstatic void *xdl_open_by_addr(void *addr) {\n  if (NULL == addr) return NULL;\n\n  xdl_t *self = NULL;\n  uintptr_t pkg[2] = {(uintptr_t)&self, (uintptr_t)addr};\n  xdl_iterate_phdr(xdl_open_by_addr_iterate_cb, pkg, XDL_DEFAULT);\n\n  return (void *)self;\n}\n\nstatic bool xdl_sym_is_match(ElfW(Sym) *sym, uintptr_t offset, bool is_symtab) {\n  if (is_symtab) {\n    if (!XDL_SYMTAB_IS_EXPORT_SYM(sym->st_shndx)) false;\n  } else {\n    if (!XDL_DYNSYM_IS_EXPORT_SYM(sym->st_shndx)) false;\n  }\n\n  return ELF_ST_TYPE(sym->st_info) != STT_TLS && offset >= sym->st_value &&\n         offset < sym->st_value + sym->st_size;\n}\n\nstatic ElfW(Sym) *xdl_sym_by_addr(void *handle, void *addr) {\n  xdl_t *self = (xdl_t *)handle;\n\n  // load .dynsym only once\n  if (!self->dynsym_try_load) {\n    self->dynsym_try_load = true;\n    if (0 != xdl_dynsym_load(self)) return NULL;\n  }\n\n  // find symbol\n  if (NULL == self->dynsym) return NULL;\n  uintptr_t offset = (uintptr_t)addr - self->load_bias;\n  if (self->gnu_hash.buckets_cnt > 0) {\n    const uint32_t *chains_all = self->gnu_hash.chains - self->gnu_hash.symoffset;\n    for (size_t i = 0; i < self->gnu_hash.buckets_cnt; i++) {\n      uint32_t n = self->gnu_hash.buckets[i];\n      if (n < self->gnu_hash.symoffset) continue;\n      do {\n        ElfW(Sym) *sym = self->dynsym + n;\n        if (xdl_sym_is_match(sym, offset, false)) return sym;\n      } while ((chains_all[n++] & 1) == 0);\n    }\n  } else if (self->sysv_hash.chains_cnt > 0) {\n    for (size_t i = 0; i < self->sysv_hash.chains_cnt; i++) {\n      ElfW(Sym) *sym = self->dynsym + i;\n      if (xdl_sym_is_match(sym, offset, false)) return sym;\n    }\n  }\n\n  return NULL;\n}\n\nstatic ElfW(Sym) *xdl_dsym_by_addr(void *handle, void *addr) {\n  xdl_t *self = (xdl_t *)handle;\n\n  // load .symtab only once\n  if (!self->symtab_try_load) {\n    self->symtab_try_load = true;\n    if (0 != xdl_symtab_load(self)) return NULL;\n  }\n\n  // find symbol\n  if (NULL == self->symtab) return NULL;\n  uintptr_t offset = (uintptr_t)addr - self->load_bias;\n  for (size_t i = 0; i < self->symtab_cnt; i++) {\n    ElfW(Sym) *sym = self->symtab + i;\n    if (xdl_sym_is_match(sym, offset, true)) return sym;\n  }\n\n  return NULL;\n}\n\nint xdl_addr(void *addr, xdl_info_t *info, void **cache) {\n  if (NULL == addr || NULL == info || NULL == cache) return 0;\n\n  memset(info, 0, sizeof(Dl_info));\n\n  // find handle from cache\n  xdl_t *handle = NULL;\n  for (handle = *((xdl_t **)cache); NULL != handle; handle = handle->next)\n    if (xdl_elf_is_match(handle->load_bias, handle->dlpi_phdr, handle->dlpi_phnum, (uintptr_t)addr)) break;\n\n  // create new handle, save handle to cache\n  if (NULL == handle) {\n    handle = (xdl_t *)xdl_open_by_addr(addr);\n    if (NULL == handle) return 0;\n    handle->next = *(xdl_t **)cache;\n    *(xdl_t **)cache = handle;\n  }\n\n  // we have at least: load_bias, pathname, dlpi_phdr, dlpi_phnum\n  info->dli_fbase = (void *)handle->load_bias;\n  info->dli_fname = handle->pathname;\n  info->dli_sname = NULL;\n  info->dli_saddr = 0;\n  info->dli_ssize = 0;\n  info->dlpi_phdr = handle->dlpi_phdr;\n  info->dlpi_phnum = (size_t)handle->dlpi_phnum;\n\n  // keep looking for: symbol name, symbol offset, symbol size\n  ElfW(Sym) *sym;\n  if (NULL != (sym = xdl_sym_by_addr((void *)handle, addr))) {\n    info->dli_sname = handle->dynstr + sym->st_name;\n    info->dli_saddr = (void *)(handle->load_bias + sym->st_value);\n    info->dli_ssize = sym->st_size;\n  } else if (NULL != (sym = xdl_dsym_by_addr((void *)handle, addr))) {\n    info->dli_sname = handle->strtab + sym->st_name;\n    info->dli_saddr = (void *)(handle->load_bias + sym->st_value);\n    info->dli_ssize = sym->st_size;\n  }\n\n  return 1;\n}\n\nvoid xdl_addr_clean(void **cache) {\n  if (NULL == cache) return;\n\n  xdl_t *handle = *((xdl_t **)cache);\n  while (NULL != handle) {\n    xdl_t *tmp = handle;\n    handle = handle->next;\n    xdl_close(tmp);\n  }\n  *cache = NULL;\n}\n\nint xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags) {\n  if (NULL == callback) return 0;\n\n  return xdl_iterate_phdr_impl(callback, data, flags);\n}\n\nint xdl_info(void *handle, int request, void *info) {\n  if (NULL == handle || XDL_DI_DLINFO != request || NULL == info) return -1;\n\n  xdl_t *self = (xdl_t *)handle;\n  xdl_info_t *dlinfo = (xdl_info_t *)info;\n\n  dlinfo->dli_fbase = (void *)self->load_bias;\n  dlinfo->dli_fname = self->pathname;\n  dlinfo->dli_sname = NULL;\n  dlinfo->dli_saddr = 0;\n  dlinfo->dli_ssize = 0;\n  dlinfo->dlpi_phdr = self->dlpi_phdr;\n  dlinfo->dlpi_phnum = (size_t)self->dlpi_phnum;\n  return 0;\n}\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl.map.txt",
    "content": "{\n    global:\n        xdl_open;\n        xdl_close;\n        xdl_sym;\n        xdl_dsym;\n        xdl_addr;\n        xdl_addr_clean;\n        xdl_iterate_phdr;\n        xdl_info;\n\n    local:\n        *;\n};\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_iterate.c",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n#include \"xdl_iterate.h\"\n\n#include <android/api-level.h>\n#include <ctype.h>\n#include <dlfcn.h>\n#include <elf.h>\n#include <inttypes.h>\n#include <link.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/auxv.h>\n\n#include \"xdl.h\"\n#include \"xdl_linker.h\"\n#include \"xdl_util.h\"\n\n/*\n * =========================================================================================================\n * API-LEVEL  ANDROID-VERSION  SOLUTION\n * =========================================================================================================\n * 16         4.1              /proc/self/maps\n * 17         4.2              /proc/self/maps\n * 18         4.3              /proc/self/maps\n * 19         4.4              /proc/self/maps\n * 20         4.4W             /proc/self/maps\n * ---------------------------------------------------------------------------------------------------------\n * 21         5.0              dl_iterate_phdr() + __dl__ZL10g_dl_mutex + linker/linker64 from getauxval(3)\n * 22         5.1              dl_iterate_phdr() + __dl__ZL10g_dl_mutex + linker/linker64 from getauxval(3)\n * ---------------------------------------------------------------------------------------------------------\n * 23         >= 6.0           dl_iterate_phdr() + linker/linker64 from getauxval(3)\n * =========================================================================================================\n */\n\nextern __attribute((weak)) int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *);\nextern __attribute((weak)) unsigned long int getauxval(unsigned long int);\n\nstatic uintptr_t xdl_iterate_get_min_vaddr(struct dl_phdr_info *info) {\n  uintptr_t min_vaddr = UINTPTR_MAX;\n  for (size_t i = 0; i < info->dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(info->dlpi_phdr[i]);\n    if (PT_LOAD == phdr->p_type) {\n      if (min_vaddr > phdr->p_vaddr) min_vaddr = phdr->p_vaddr;\n    }\n  }\n  return min_vaddr;\n}\n\nstatic int xdl_iterate_open_or_rewind_maps(FILE **maps) {\n  if (NULL == *maps) {\n    *maps = fopen(\"/proc/self/maps\", \"r\");\n    if (NULL == *maps) return -1;\n  } else\n    rewind(*maps);\n\n  return 0;\n}\n\nstatic int xdl_iterate_get_pathname_from_maps(uintptr_t base, char *buf, size_t buf_len, FILE **maps) {\n  // open or rewind maps-file\n  if (0 != xdl_iterate_open_or_rewind_maps(maps)) return -1;  // failed\n\n  char line[1024];\n  while (fgets(line, sizeof(line), *maps)) {\n    // check base address\n    uintptr_t start, end;\n    if (2 != sscanf(line, \"%\" SCNxPTR \"-%\" SCNxPTR \" r\", &start, &end)) continue;\n    if (base < start) break;  // failed\n    if (base >= end) continue;\n\n    // get pathname\n    char *pathname = strchr(line, '/');\n    if (NULL == pathname) break;  // failed\n    xdl_util_trim_ending(pathname);\n\n    // found it\n    strlcpy(buf, pathname, buf_len);\n    return 0;  // OK\n  }\n\n  return -1;  // failed\n}\n\nstatic int xdl_iterate_by_linker_cb(struct dl_phdr_info *info, size_t size, void *arg) {\n  uintptr_t *pkg = (uintptr_t *)arg;\n  xdl_iterate_phdr_cb_t cb = (xdl_iterate_phdr_cb_t)*pkg++;\n  void *cb_arg = (void *)*pkg++;\n  FILE **maps = (FILE **)*pkg++;\n  uintptr_t linker_load_bias = *pkg++;\n  int flags = (int)*pkg;\n\n  // ignore invalid ELF\n  if (0 == info->dlpi_addr || NULL == info->dlpi_name || '\\0' == info->dlpi_name[0]) return 0;\n\n  // ignore linker if we have returned it already\n  if (linker_load_bias == info->dlpi_addr) return 0;\n\n  struct dl_phdr_info info_fixed;\n  info_fixed.dlpi_addr = info->dlpi_addr;\n  info_fixed.dlpi_name = info->dlpi_name;\n  info_fixed.dlpi_phdr = info->dlpi_phdr;\n  info_fixed.dlpi_phnum = info->dlpi_phnum;\n  info = &info_fixed;\n\n  // fix dlpi_phdr & dlpi_phnum (from memory)\n  if (NULL == info->dlpi_phdr || 0 == info->dlpi_phnum) {\n    ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)info->dlpi_addr;\n    info->dlpi_phdr = (ElfW(Phdr) *)(info->dlpi_addr + ehdr->e_phoff);\n    info->dlpi_phnum = ehdr->e_phnum;\n  }\n\n  // fix dlpi_name (from /proc/self/maps)\n  if ('/' != info->dlpi_name[0] && '[' != info->dlpi_name[0] && (0 != (flags & XDL_FULL_PATHNAME))) {\n    // get base address\n    uintptr_t min_vaddr = xdl_iterate_get_min_vaddr(info);\n    if (UINTPTR_MAX == min_vaddr) return 0;  // ignore this ELF\n    uintptr_t base = (uintptr_t)(info->dlpi_addr + min_vaddr);\n\n    char buf[1024];\n    if (0 != xdl_iterate_get_pathname_from_maps(base, buf, sizeof(buf), maps)) return 0;  // ignore this ELF\n\n    info->dlpi_name = (const char *)buf;\n  }\n\n  // callback\n  return cb(info, size, cb_arg);\n}\n\nstatic uintptr_t xdl_iterate_get_linker_base(void) {\n  if (NULL == getauxval) return 0;\n\n  uintptr_t base = (uintptr_t)getauxval(AT_BASE);\n  if (0 == base) return 0;\n  if (0 != memcmp((void *)base, ELFMAG, SELFMAG)) return 0;\n\n  return base;\n}\n\nstatic int xdl_iterate_do_callback(xdl_iterate_phdr_cb_t cb, void *cb_arg, uintptr_t base,\n                                   const char *pathname, uintptr_t *load_bias) {\n  ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base;\n\n  struct dl_phdr_info info;\n  info.dlpi_name = pathname;\n  info.dlpi_phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);\n  info.dlpi_phnum = ehdr->e_phnum;\n\n  // get load bias\n  uintptr_t min_vaddr = xdl_iterate_get_min_vaddr(&info);\n  if (UINTPTR_MAX == min_vaddr) return 0;  // ignore invalid ELF\n  info.dlpi_addr = (ElfW(Addr))(base - min_vaddr);\n  if (NULL != load_bias) *load_bias = info.dlpi_addr;\n\n  return cb(&info, sizeof(struct dl_phdr_info), cb_arg);\n}\n\nstatic int xdl_iterate_by_linker(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags) {\n  if (NULL == dl_iterate_phdr) return 0;\n\n  int api_level = xdl_util_get_api_level();\n  FILE *maps = NULL;\n  int r;\n\n  // dl_iterate_phdr(3) does NOT contain linker/linker64 when Android version < 8.1 (API level 27).\n  // Here we always try to get linker base address from auxv.\n  uintptr_t linker_load_bias = 0;\n  uintptr_t linker_base = xdl_iterate_get_linker_base();\n  if (0 != linker_base) {\n    if (0 !=\n        (r = xdl_iterate_do_callback(cb, cb_arg, linker_base, XDL_UTIL_LINKER_PATHNAME, &linker_load_bias)))\n      return r;\n  }\n\n  // for other ELF\n  uintptr_t pkg[5] = {(uintptr_t)cb, (uintptr_t)cb_arg, (uintptr_t)&maps, linker_load_bias, (uintptr_t)flags};\n  if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) xdl_linker_lock();\n  r = dl_iterate_phdr(xdl_iterate_by_linker_cb, pkg);\n  if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) xdl_linker_unlock();\n\n  if (NULL != maps) fclose(maps);\n  return r;\n}\n\n#if (defined(__arm__) || defined(__i386__)) && __ANDROID_API__ < __ANDROID_API_L__\nstatic int xdl_iterate_by_maps(xdl_iterate_phdr_cb_t cb, void *cb_arg) {\n  FILE *maps = fopen(\"/proc/self/maps\", \"r\");\n  if (NULL == maps) return 0;\n\n  int r = 0;\n  char buf1[1024], buf2[1024];\n  char *line = buf1;\n  uintptr_t prev_base = 0;\n  bool try_next_line = false;\n\n  while (fgets(line, sizeof(buf1), maps)) {\n    // Try to find an ELF which loaded by linker.\n    uintptr_t base, offset;\n    char exec;\n    if (3 != sscanf(line, \"%\" SCNxPTR \"-%*\" SCNxPTR \" r%*c%cp %\" SCNxPTR \" \", &base, &exec, &offset))\n      goto clean;\n\n    if ('-' == exec && 0 == offset) {\n      // r--p\n      prev_base = base;\n      line = (line == buf1 ? buf2 : buf1);\n      try_next_line = true;\n      continue;\n    } else if (exec == 'x') {\n      // r-xp\n      char *pathname = NULL;\n      if (try_next_line && 0 != offset) {\n        char *prev = (line == buf1 ? buf2 : buf1);\n        char *prev_pathname = strchr(prev, '/');\n        if (NULL == prev_pathname) goto clean;\n\n        pathname = strchr(line, '/');\n        if (NULL == pathname) goto clean;\n\n        xdl_util_trim_ending(prev_pathname);\n        xdl_util_trim_ending(pathname);\n        if (0 != strcmp(prev_pathname, pathname)) goto clean;\n\n        // we found the line with r-xp in the next line\n        base = prev_base;\n        offset = 0;\n      }\n\n      if (0 != offset) goto clean;\n\n      // get pathname\n      if (NULL == pathname) {\n        pathname = strchr(line, '/');\n        if (NULL == pathname) goto clean;\n        xdl_util_trim_ending(pathname);\n      }\n\n      if (0 != memcmp((void *)base, ELFMAG, SELFMAG)) goto clean;\n      ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base;\n      struct dl_phdr_info info;\n      info.dlpi_name = pathname;\n      info.dlpi_phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);\n      info.dlpi_phnum = ehdr->e_phnum;\n\n      // callback\n      if (0 != (r = xdl_iterate_do_callback(cb, cb_arg, base, pathname, NULL))) break;\n    }\n\n  clean:\n    try_next_line = false;\n  }\n\n  fclose(maps);\n  return r;\n}\n#endif\n\nint xdl_iterate_phdr_impl(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags) {\n  // iterate by /proc/self/maps in Android 4.x (Android 4.x only supports arm32 and x86)\n#if (defined(__arm__) || defined(__i386__)) && __ANDROID_API__ < __ANDROID_API_L__\n  if (xdl_util_get_api_level() < __ANDROID_API_L__) return xdl_iterate_by_maps(cb, cb_arg);\n#endif\n\n  // iterate by dl_iterate_phdr()\n  return xdl_iterate_by_linker(cb, cb_arg, flags);\n}\n\nint xdl_iterate_get_full_pathname(uintptr_t base, char *buf, size_t buf_len) {\n  FILE *maps = NULL;\n  int r = xdl_iterate_get_pathname_from_maps(base, buf, buf_len, &maps);\n  if (NULL != maps) fclose(maps);\n  return r;\n}\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_iterate.h",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n#ifndef IO_GITHUB_HEXHACKING_XDL_ITERATE\n#define IO_GITHUB_HEXHACKING_XDL_ITERATE\n\n#include <link.h>\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef int (*xdl_iterate_phdr_cb_t)(struct dl_phdr_info *info, size_t size, void *arg);\nint xdl_iterate_phdr_impl(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags);\n\nint xdl_iterate_get_full_pathname(uintptr_t base, char *buf, size_t buf_len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_linker.c",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2021-02-21.\n\n#include \"xdl_linker.h\"\n\n#include <dlfcn.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdio.h>\n\n#include \"xdl.h\"\n#include \"xdl_iterate.h\"\n#include \"xdl_util.h\"\n\n#define XDL_LINKER_SYM_MUTEX           \"__dl__ZL10g_dl_mutex\"\n#define XDL_LINKER_SYM_DLOPEN_EXT_N    \"__dl__ZL10dlopen_extPKciPK17android_dlextinfoPv\"\n#define XDL_LINKER_SYM_DO_DLOPEN_N     \"__dl__Z9do_dlopenPKciPK17android_dlextinfoPv\"\n#define XDL_LINKER_SYM_DLOPEN_O        \"__dl__Z8__dlopenPKciPKv\"\n#define XDL_LINKER_SYM_LOADER_DLOPEN_P \"__loader_dlopen\"\n\ntypedef void *(*xdl_linker_dlopen_n_t)(const char *, int, const void *, void *);\ntypedef void *(*xdl_linker_dlopen_o_t)(const char *, int, const void *);\n\nstatic pthread_mutex_t *xdl_linker_mutex = NULL;\nstatic void *xdl_linker_dlopen = NULL;\n\nstatic void *xdl_linker_caller_addr[] = {\n    NULL,  // default\n    NULL,  // art\n    NULL   // vendor\n};\n\n#ifndef __LP64__\n#define XDL_LINKER_LIB \"lib\"\n#else\n#define XDL_LINKER_LIB \"lib64\"\n#endif\nstatic const char *xdl_linker_vendor_path[] = {\n    // order is important\n    \"/vendor/\" XDL_LINKER_LIB \"/egl/\",     \"/vendor/\" XDL_LINKER_LIB \"/hw/\",\n    \"/vendor/\" XDL_LINKER_LIB \"/\",         \"/odm/\" XDL_LINKER_LIB \"/\",\n    \"/vendor/\" XDL_LINKER_LIB \"/vndk-sp/\", \"/odm/\" XDL_LINKER_LIB \"/vndk-sp/\"};\n\nstatic void xdl_linker_init_symbols_impl(void) {\n  // find linker from: /proc/self/maps (API level < 18) or getauxval (API level >= 18)\n  void *handle = xdl_open(XDL_UTIL_LINKER_BASENAME, XDL_DEFAULT);\n  if (NULL == handle) return;\n\n  int api_level = xdl_util_get_api_level();\n  if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) {\n    // == Android 5.x\n    xdl_linker_mutex = (pthread_mutex_t *)xdl_dsym(handle, XDL_LINKER_SYM_MUTEX, NULL);\n  } else if (__ANDROID_API_N__ == api_level || __ANDROID_API_N_MR1__ == api_level) {\n    // == Android 7.x\n    xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DLOPEN_EXT_N, NULL);\n    if (NULL == xdl_linker_dlopen) {\n      xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DO_DLOPEN_N, NULL);\n      xdl_linker_mutex = (pthread_mutex_t *)xdl_dsym(handle, XDL_LINKER_SYM_MUTEX, NULL);\n    }\n  } else if (__ANDROID_API_O__ == api_level || __ANDROID_API_O_MR1__ == api_level) {\n    // == Android 8.x\n    xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DLOPEN_O, NULL);\n  } else if (api_level >= __ANDROID_API_P__) {\n    // >= Android 9.0\n    xdl_linker_dlopen = xdl_sym(handle, XDL_LINKER_SYM_LOADER_DLOPEN_P, NULL);\n  }\n\n  xdl_close(handle);\n}\n\nstatic void xdl_linker_init_symbols(void) {\n  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\n  static bool inited = false;\n  if (!inited) {\n    pthread_mutex_lock(&lock);\n    if (!inited) {\n      xdl_linker_init_symbols_impl();\n      inited = true;\n    }\n    pthread_mutex_unlock(&lock);\n  }\n}\n\nvoid xdl_linker_lock(void) {\n  xdl_linker_init_symbols();\n\n  if (NULL != xdl_linker_mutex) pthread_mutex_lock(xdl_linker_mutex);\n}\n\nvoid xdl_linker_unlock(void) {\n  if (NULL != xdl_linker_mutex) pthread_mutex_unlock(xdl_linker_mutex);\n}\n\nstatic void *xdl_linker_get_caller_addr(struct dl_phdr_info *info) {\n  for (size_t i = 0; i < info->dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &(info->dlpi_phdr[i]);\n    if (PT_LOAD == phdr->p_type) {\n      return (void *)(info->dlpi_addr + phdr->p_vaddr);\n    }\n  }\n  return NULL;\n}\n\nstatic int xdl_linker_get_caller_addr_cb(struct dl_phdr_info *info, size_t size, void *arg) {\n  (void)size;\n\n  size_t *vendor_match = (size_t *)arg;\n\n  if (0 == info->dlpi_addr || NULL == info->dlpi_name) return 0;  // continue\n\n  if (NULL == xdl_linker_caller_addr[0] && xdl_util_ends_with(info->dlpi_name, \"/libc.so\"))\n    xdl_linker_caller_addr[0] = xdl_linker_get_caller_addr(info);\n\n  if (NULL == xdl_linker_caller_addr[1] && xdl_util_ends_with(info->dlpi_name, \"/libart.so\"))\n    xdl_linker_caller_addr[1] = xdl_linker_get_caller_addr(info);\n\n  if (0 != *vendor_match) {\n    for (size_t i = 0; i < *vendor_match; i++) {\n      if (xdl_util_starts_with(info->dlpi_name, xdl_linker_vendor_path[i])) {\n        void *caller_addr = xdl_linker_get_caller_addr(info);\n        if (NULL != caller_addr) {\n          xdl_linker_caller_addr[2] = caller_addr;\n          *vendor_match = i;\n        }\n      }\n    }\n  }\n\n  if (NULL != xdl_linker_caller_addr[0] && NULL != xdl_linker_caller_addr[1] && 0 == *vendor_match) {\n    return 1;  // finish\n  } else {\n    return 0;  // continue\n  }\n}\n\nstatic void xdl_linker_init_caller_addr_impl(void) {\n  size_t vendor_match = sizeof(xdl_linker_vendor_path) / sizeof(xdl_linker_vendor_path[0]);\n  xdl_iterate_phdr_impl(xdl_linker_get_caller_addr_cb, &vendor_match, XDL_DEFAULT);\n}\n\nstatic void xdl_linker_init_caller_addr(void) {\n  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\n  static bool inited = false;\n  if (!inited) {\n    pthread_mutex_lock(&lock);\n    if (!inited) {\n      xdl_linker_init_caller_addr_impl();\n      inited = true;\n    }\n    pthread_mutex_unlock(&lock);\n  }\n}\n\nvoid *xdl_linker_force_dlopen(const char *filename) {\n  int api_level = xdl_util_get_api_level();\n\n  if (api_level <= __ANDROID_API_M__) {\n    // <= Android 6.0\n    return dlopen(filename, RTLD_NOW);\n  } else {\n    xdl_linker_init_symbols();\n    if (NULL == xdl_linker_dlopen) return NULL;\n    xdl_linker_init_caller_addr();\n\n    void *handle = NULL;\n    if (__ANDROID_API_N__ == api_level || __ANDROID_API_N_MR1__ == api_level) {\n      // == Android 7.x\n      xdl_linker_lock();\n      for (size_t i = 0; i < sizeof(xdl_linker_caller_addr) / sizeof(xdl_linker_caller_addr[0]); i++) {\n        if (NULL != xdl_linker_caller_addr[i]) {\n          handle =\n              ((xdl_linker_dlopen_n_t)xdl_linker_dlopen)(filename, RTLD_NOW, NULL, xdl_linker_caller_addr[i]);\n          if (NULL != handle) break;\n        }\n      }\n      xdl_linker_unlock();\n    } else {\n      // >= Android 8.0\n      for (size_t i = 0; i < sizeof(xdl_linker_caller_addr) / sizeof(xdl_linker_caller_addr[0]); i++) {\n        if (NULL != xdl_linker_caller_addr[i]) {\n          handle = ((xdl_linker_dlopen_o_t)xdl_linker_dlopen)(filename, RTLD_NOW, xdl_linker_caller_addr[i]);\n          if (NULL != handle) break;\n        }\n      }\n    }\n    return handle;\n  }\n}\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_linker.h",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2021-02-21.\n\n#ifndef IO_GITHUB_HEXHACKING_XDL_LINKER\n#define IO_GITHUB_HEXHACKING_XDL_LINKER\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid xdl_linker_lock(void);\nvoid xdl_linker_unlock(void);\n\nvoid *xdl_linker_force_dlopen(const char *filename);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_lzma.c",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-11-08.\n\n#include \"xdl_lzma.h\"\n\n#include <ctype.h>\n#include <inttypes.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"xdl.h\"\n#include \"xdl_util.h\"\n\n// LZMA library pathname & symbol names\n#ifndef __LP64__\n#define XDL_LZMA_PATHNAME \"/system/lib/liblzma.so\"\n#else\n#define XDL_LZMA_PATHNAME \"/system/lib64/liblzma.so\"\n#endif\n#define XDL_LZMA_SYM_CRCGEN     \"CrcGenerateTable\"\n#define XDL_LZMA_SYM_CRC64GEN   \"Crc64GenerateTable\"\n#define XDL_LZMA_SYM_CONSTRUCT  \"XzUnpacker_Construct\"\n#define XDL_LZMA_SYM_ISFINISHED \"XzUnpacker_IsStreamWasFinished\"\n#define XDL_LZMA_SYM_FREE       \"XzUnpacker_Free\"\n#define XDL_LZMA_SYM_CODE       \"XzUnpacker_Code\"\n\n// LZMA data type definition\n#define SZ_OK 0\ntypedef struct ISzAlloc ISzAlloc;\ntypedef const ISzAlloc *ISzAllocPtr;\nstruct ISzAlloc {\n  void *(*Alloc)(ISzAllocPtr p, size_t size);\n  void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */\n};\ntypedef enum {\n  CODER_STATUS_NOT_SPECIFIED,      /* use main error code instead */\n  CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */\n  CODER_STATUS_NOT_FINISHED,       /* stream was not finished */\n  CODER_STATUS_NEEDS_MORE_INPUT    /* you must provide more input bytes */\n} ECoderStatus;\ntypedef enum {\n  CODER_FINISH_ANY, /* finish at any point */\n  CODER_FINISH_END  /* block must be finished at the end */\n} ECoderFinishMode;\n\n// LZMA function type definition\ntypedef void (*xdl_lzma_crcgen_t)(void);\ntypedef void (*xdl_lzma_crc64gen_t)(void);\ntypedef void (*xdl_lzma_construct_t)(void *, ISzAllocPtr);\ntypedef int (*xdl_lzma_isfinished_t)(const void *);\ntypedef void (*xdl_lzma_free_t)(void *);\ntypedef int (*xdl_lzma_code_t)(void *, uint8_t *, size_t *, const uint8_t *, size_t *, ECoderFinishMode,\n                               ECoderStatus *);\ntypedef int (*xdl_lzma_code_q_t)(void *, uint8_t *, size_t *, const uint8_t *, size_t *, int,\n                                 ECoderFinishMode, ECoderStatus *);\n\n// LZMA function pointor\nstatic xdl_lzma_construct_t xdl_lzma_construct = NULL;\nstatic xdl_lzma_isfinished_t xdl_lzma_isfinished = NULL;\nstatic xdl_lzma_free_t xdl_lzma_free = NULL;\nstatic void *xdl_lzma_code = NULL;\n\n// LZMA init\nstatic void xdl_lzma_init() {\n  void *lzma = xdl_open(XDL_LZMA_PATHNAME, XDL_TRY_FORCE_LOAD);\n  if (NULL == lzma) return;\n\n  xdl_lzma_crcgen_t crcgen = NULL;\n  xdl_lzma_crc64gen_t crc64gen = NULL;\n  if (NULL == (crcgen = (xdl_lzma_crcgen_t)xdl_sym(lzma, XDL_LZMA_SYM_CRCGEN, NULL))) goto end;\n  if (NULL == (crc64gen = (xdl_lzma_crc64gen_t)xdl_sym(lzma, XDL_LZMA_SYM_CRC64GEN, NULL))) goto end;\n  if (NULL == (xdl_lzma_construct = (xdl_lzma_construct_t)xdl_sym(lzma, XDL_LZMA_SYM_CONSTRUCT, NULL)))\n    goto end;\n  if (NULL == (xdl_lzma_isfinished = (xdl_lzma_isfinished_t)xdl_sym(lzma, XDL_LZMA_SYM_ISFINISHED, NULL)))\n    goto end;\n  if (NULL == (xdl_lzma_free = (xdl_lzma_free_t)xdl_sym(lzma, XDL_LZMA_SYM_FREE, NULL))) goto end;\n  if (NULL == (xdl_lzma_code = xdl_sym(lzma, XDL_LZMA_SYM_CODE, NULL))) goto end;\n  crcgen();\n  crc64gen();\n\nend:\n  xdl_close(lzma);\n}\n\n// LZMA internal alloc / free\nstatic void *xdl_lzma_internal_alloc(ISzAllocPtr p, size_t size) {\n  (void)p;\n  return malloc(size);\n}\nstatic void xdl_lzma_internal_free(ISzAllocPtr p, void *address) {\n  (void)p;\n  free(address);\n}\n\nint xdl_lzma_decompress(uint8_t *src, size_t src_size, uint8_t **dst, size_t *dst_size) {\n  size_t src_offset = 0;\n  size_t dst_offset = 0;\n  size_t src_remaining;\n  size_t dst_remaining;\n  ISzAlloc alloc = {.Alloc = xdl_lzma_internal_alloc, .Free = xdl_lzma_internal_free};\n  long long state[4096 / sizeof(long long)];  // must be enough, 8-bit aligned\n  ECoderStatus status;\n  int api_level = xdl_util_get_api_level();\n\n  // init and check\n  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\n  static bool inited = false;\n  if (!inited) {\n    pthread_mutex_lock(&lock);\n    if (!inited) {\n      xdl_lzma_init();\n      inited = true;\n    }\n    pthread_mutex_unlock(&lock);\n  }\n  if (NULL == xdl_lzma_code) return -1;\n\n  xdl_lzma_construct(&state, &alloc);\n\n  *dst_size = 2 * src_size;\n  *dst = NULL;\n  do {\n    *dst_size *= 2;\n    if (NULL == (*dst = realloc(*dst, *dst_size))) {\n      xdl_lzma_free(&state);\n      return -1;\n    }\n\n    src_remaining = src_size - src_offset;\n    dst_remaining = *dst_size - dst_offset;\n\n    int result;\n    if (api_level >= __ANDROID_API_Q__) {\n      xdl_lzma_code_q_t lzma_code_q = (xdl_lzma_code_q_t)xdl_lzma_code;\n      result = lzma_code_q(&state, *dst + dst_offset, &dst_remaining, src + src_offset, &src_remaining, 1,\n                           CODER_FINISH_ANY, &status);\n    } else {\n      xdl_lzma_code_t lzma_code = (xdl_lzma_code_t)xdl_lzma_code;\n      result = lzma_code(&state, *dst + dst_offset, &dst_remaining, src + src_offset, &src_remaining,\n                         CODER_FINISH_ANY, &status);\n    }\n    if (SZ_OK != result) {\n      free(*dst);\n      xdl_lzma_free(&state);\n      return -1;\n    }\n\n    src_offset += src_remaining;\n    dst_offset += dst_remaining;\n  } while (status == CODER_STATUS_NOT_FINISHED);\n\n  xdl_lzma_free(&state);\n\n  if (!xdl_lzma_isfinished(&state)) {\n    free(*dst);\n    return -1;\n  }\n\n  *dst_size = dst_offset;\n  *dst = realloc(*dst, *dst_size);\n  return 0;\n}\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_lzma.h",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-11-08.\n\n#ifndef IO_GITHUB_HEXHACKING_XDL_LZMA\n#define IO_GITHUB_HEXHACKING_XDL_LZMA\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint xdl_lzma_decompress(uint8_t *src, size_t src_size, uint8_t **dst, size_t *dst_size);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_util.c",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n#include \"xdl_util.h\"\n\n#include <android/api-level.h>\n#include <ctype.h>\n#include <inttypes.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\nbool xdl_util_starts_with(const char *str, const char *start) {\n  while (*str && *str == *start) {\n    str++;\n    start++;\n  }\n\n  return '\\0' == *start;\n}\n\nbool xdl_util_ends_with(const char *str, const char *ending) {\n  size_t str_len = strlen(str);\n  size_t ending_len = strlen(ending);\n\n  if (ending_len > str_len) return false;\n\n  return 0 == strcmp(str + (str_len - ending_len), ending);\n}\n\nsize_t xdl_util_trim_ending(char *start) {\n  char *end = start + strlen(start);\n  while (start < end && isspace((int)(*(end - 1)))) {\n    end--;\n    *end = '\\0';\n  }\n  return (size_t)(end - start);\n}\n\nstatic int xdl_util_get_api_level_from_build_prop(void) {\n  char buf[128];\n  int api_level = -1;\n\n  FILE *fp = fopen(\"/system/build.prop\", \"r\");\n  if (NULL == fp) goto end;\n\n  while (fgets(buf, sizeof(buf), fp)) {\n    if (xdl_util_starts_with(buf, \"ro.build.version.sdk=\")) {\n      api_level = atoi(buf + 21);\n      break;\n    }\n  }\n  fclose(fp);\n\nend:\n  return (api_level > 0) ? api_level : -1;\n}\n\nint xdl_util_get_api_level(void) {\n  static int xdl_util_api_level = -1;\n\n  if (xdl_util_api_level < 0) {\n    int api_level = android_get_device_api_level();\n    if (api_level < 0)\n      api_level = xdl_util_get_api_level_from_build_prop();  // compatible with unusual models\n    if (api_level < __ANDROID_API_J__) api_level = __ANDROID_API_J__;\n\n    __atomic_store_n(&xdl_util_api_level, api_level, __ATOMIC_SEQ_CST);\n  }\n\n  return xdl_util_api_level;\n}\n"
  },
  {
    "path": "app/src/main/jni/Il2Cpp/xdl/xdl_util.h",
    "content": "// Copyright (c) 2020-2023 HexHacking Team\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n// Created by caikelun on 2020-10-04.\n\n#ifndef IO_GITHUB_HEXHACKING_XDL_UTIL\n#define IO_GITHUB_HEXHACKING_XDL_UTIL\n\n#include <errno.h>\n#include <stdbool.h>\n#include <stddef.h>\n\n#ifndef __LP64__\n#define XDL_UTIL_LINKER_BASENAME        \"linker\"\n#define XDL_UTIL_LINKER_PATHNAME        \"/system/bin/linker\"\n#define XDL_UTIL_APP_PROCESS_BASENAME   \"app_process32\"\n#define XDL_UTIL_APP_PROCESS_PATHNAME   \"/system/bin/app_process32\"\n#define XDL_UTIL_APP_PROCESS_BASENAME_K \"app_process\"\n#define XDL_UTIL_APP_PROCESS_PATHNAME_K \"/system/bin/app_process\"\n#else\n#define XDL_UTIL_LINKER_BASENAME      \"linker64\"\n#define XDL_UTIL_LINKER_PATHNAME      \"/system/bin/linker64\"\n#define XDL_UTIL_APP_PROCESS_BASENAME \"app_process64\"\n#define XDL_UTIL_APP_PROCESS_PATHNAME \"/system/bin/app_process64\"\n#endif\n#define XDL_UTIL_VDSO_BASENAME \"[vdso]\"\n\n#define XDL_UTIL_TEMP_FAILURE_RETRY(exp)   \\\n  ({                                       \\\n    __typeof__(exp) _rc;                   \\\n    do {                                   \\\n      errno = 0;                           \\\n      _rc = (exp);                         \\\n    } while (_rc == -1 && errno == EINTR); \\\n    _rc;                                   \\\n  })\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nbool xdl_util_starts_with(const char *str, const char *start);\nbool xdl_util_ends_with(const char *str, const char *ending);\n\nsize_t xdl_util_trim_ending(char *start);\n\nint xdl_util_get_api_level(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "app/src/main/jni/Includes/config.h",
    "content": "//\n// Created by Perfare on 2020/7/4.\n//\n\n#ifndef AUTO_IL2CPPDUMPER_CONFIG_H\n#define AUTO_IL2CPPDUMPER_CONFIG_H\n\n// Try increase sleep time if having issues with the game. Decrease sleep time if anti-cheat triggering earlier\n#define Sleep 2\n\n// Uncomment for fake lib mode\n// It is to load our fake libmain.so or libunity.so and load game's real librealmain.so or librealunity.so\n#define UseFakeLib\n\n#endif //AUTO_IL2CPPDUMPER_CONFIG_H\n"
  },
  {
    "path": "app/src/main/jni/Includes/log.h",
    "content": "//\n// Created by Perfare on 2020/7/4.\n//\n\n#ifndef RIRU_IL2CPPDUMPER_LOG_H\n#define RIRU_IL2CPPDUMPER_LOG_H\n\n#include <android/log.h>\n\n#define LOG_TAG \"Il2CppDumper\"\n#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)\n#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)\n#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)\n#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)\n\n#endif //RIRU_IL2CPPDUMPER_LOG_H\n"
  },
  {
    "path": "app/src/main/jni/native-lib.cpp",
    "content": "#include <jni.h>\n#include <string>\n#include <thread>\n#include <dlfcn.h>\n#include <unistd.h>\n#include <sys/system_properties.h>\n#include \"Il2Cpp/il2cpp_dump.h\"\n#include \"Includes/config.h\"\n#include \"Includes/log.h\"\n\nbool isLibraryLoaded(const char *libraryName) {\n    char line[512] = {0};\n    FILE *fp = fopen(\"/proc/self/maps\", \"rt\");\n    if (fp != nullptr) {\n        while (fgets(line, sizeof(line), fp)) {\n            if (strstr(line, libraryName)) {\n                return true;\n            }\n        }\n        fclose(fp);\n    }\n    return false;\n}\n\n#define libTarget \"libil2cpp.so\"\n\nvoid dump_thread() {\n    LOGI(\"Lib loaded\");\n    do {\n        sleep(1);\n    } while (!isLibraryLoaded(libTarget));\n\n    //Waiting libil2cpp.so fully loaded.\n    LOGI(\"Waiting in %d...\", Sleep);\n    sleep(Sleep);\n\n    auto il2cpp_handle = dlopen(libTarget, 4);\n    LOGI(\"Start dumping\");\n\n    auto androidDataPath = std::string(\"/storage/emulated/0/Android/data/\").append(\n            GetPackageName()).append(\"/\").append(GetPackageName()).append(\"-dump.cs\");\n\n    il2cpp_api_init(il2cpp_handle);\n    il2cpp_dump(androidDataPath.c_str());\n}\n\n//The idea from first Il2Cpp Dumper called PokemonGoDumper\n//https://github.com/Jumboperson/PokemonGoDumper/blob/master/main.c#L569\n\nvoid *pLibRealUnity = 0;\n\ntypedef jint(JNICALL *CallJNI_OnLoad_t)(JavaVM *vm, void *reserved);\n\ntypedef void(JNICALL *CallJNI_OnUnload_t)(JavaVM *vm, void *reserved);\n\nCallJNI_OnLoad_t RealJNIOnLoad = 0;\nCallJNI_OnUnload_t RealJNIOnUnload = 0;\n\n#ifdef UseFakeLib\n\nJNIEXPORT jint JNICALL CallJNIOL(JavaVM *vm, void *reserved) {\n    LOGI(\"OnLoad called\");\n\n    std::thread(dump_thread).detach();\n\n    if (!pLibRealUnity)\n        pLibRealUnity = dlopen(\"librealmain.so\", RTLD_NOW);\n    if (!pLibRealUnity)\n        pLibRealUnity = dlopen(\"librealunity.so\", RTLD_NOW);\n    if (!RealJNIOnLoad)\n        RealJNIOnLoad = reinterpret_cast<CallJNI_OnLoad_t>(dlsym(pLibRealUnity, \"JNI_OnLoad\"));\n    return RealJNIOnLoad(vm, reserved);\n}\n\nJNIEXPORT void JNICALL CallJNIUL(JavaVM *vm, void *reserved) {\n    LOGI(\"OnUnload called\");\n\n    if (!pLibRealUnity)\n        pLibRealUnity = dlopen(\"librealmain.so\", RTLD_NOW);\n    if (!pLibRealUnity)\n        pLibRealUnity = dlopen(\"librealunity.so\", RTLD_NOW);\n    if (!RealJNIOnUnload)\n        RealJNIOnUnload = reinterpret_cast<CallJNI_OnUnload_t>(dlsym(pLibRealUnity,\n                                                                     \"JNI_OnUnload\"));\n    RealJNIOnUnload(vm, reserved);\n}\n\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {\n    LOGI(\"Initialize JNI\");\n\n    return CallJNIOL(vm, reserved);\n}\n\nJNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {\n    LOGI(\"Unload JNI\");\n\n    CallJNIUL(vm, reserved);\n}\n\n#else\n\n__attribute__((constructor))\nvoid lib_main() {\n    // Create a new thread so it does not block the main thread, means the game would not freeze\n    std::thread(dump_thread).detach();\n}\n#endif\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector 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=\"#3DDC84\"\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": "<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 android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\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=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"/>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"white\">#FFFFFFFF</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Auto-Il2cppDumper</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"@android:style/Theme.Material\">\n        <!-- Customize your theme here. -->\n        <item name=\"android:background\">#202020</item>\n    </style>\n</resources>"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nbuildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:8.13.1'\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        mavenCentral()\n    }\n}\n\ntasks.register('clean', Delete) {\n    delete rootProject.buildDir\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.13-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# 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=-Xmx2048m -Dfile.encoding=UTF-8\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# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\nandroid.defaults.buildfeatures.buildconfig=true\nandroid.nonTransitiveRClass=false\nandroid.nonFinalResIds=false"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd \"${APP_HOME:-./}\" > /dev/null && pwd -P ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\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    if ! command -v java >/dev/null 2>&1\n    then\n        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.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\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='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n\n@if \"%DEBUG%\"==\"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\n@rem This is normally unused\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif %ERRORLEVEL% equ 0 goto execute\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif %ERRORLEVEL% equ 0 goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nset EXIT_CODE=%ERRORLEVEL%\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\nexit /b %EXIT_CODE%\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\nrootProject.name = \"Auto-Il2cppDumper\""
  }
]