├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ └── com │ │ └── android │ │ └── support │ │ ├── CrashHandler.java │ │ ├── Launcher.java │ │ ├── Main.java │ │ ├── MainActivity.java │ │ ├── Menu.java │ │ └── Preferences.java │ ├── jni │ ├── And64InlineHook │ │ ├── And64InlineHook.cpp │ │ ├── And64InlineHook.hpp │ │ ├── LICENSE │ │ └── README.md │ ├── Android.mk │ ├── Application.mk │ ├── ByNameModding │ │ ├── BNM.cpp │ │ ├── BNM.hpp │ │ ├── BNM_data │ │ │ ├── BasicStructs.h │ │ │ ├── BasicStructs │ │ │ │ ├── Color.h │ │ │ │ ├── Quaternion.h │ │ │ │ ├── Ray.h │ │ │ │ ├── RaycastHit.h │ │ │ │ ├── Rect.h │ │ │ │ ├── Vector2.h │ │ │ │ └── Vector3.h │ │ │ ├── Il2CppHeaders │ │ │ │ ├── 2017.1.h │ │ │ │ ├── 2017.4.h │ │ │ │ ├── 2018.1.h │ │ │ │ ├── 2018.2.h │ │ │ │ ├── 2018.4.h │ │ │ │ ├── 2019.2.h │ │ │ │ ├── 2019.3.h │ │ │ │ ├── 2019.4.h │ │ │ │ ├── 2020.1.h │ │ │ │ ├── 2020.3.h │ │ │ │ ├── 2021.1.h │ │ │ │ ├── 2021.2.h │ │ │ │ └── 2021.3.h │ │ │ ├── utf8.h │ │ │ └── utf8 │ │ │ │ ├── checked.h │ │ │ │ ├── core.h │ │ │ │ ├── cpp11.h │ │ │ │ ├── cpp17.h │ │ │ │ └── unchecked.h │ │ └── BNM_settings.hpp │ ├── Includes │ │ ├── Dobby │ │ │ └── dobby.h │ │ ├── Logger.h │ │ ├── Macros.h │ │ ├── Utils.h │ │ └── obfuscate.h │ ├── KittyMemory │ │ ├── KittyMemory.cpp │ │ ├── KittyMemory.h │ │ ├── KittyUtils.cpp │ │ ├── KittyUtils.h │ │ ├── MemoryBackup.cpp │ │ ├── MemoryBackup.h │ │ ├── MemoryPatch.cpp │ │ └── MemoryPatch.h │ ├── Main.cpp │ ├── Menu │ │ ├── Menu.h │ │ ├── Setup.h │ │ └── get_device_api_level_inlines.h │ ├── Substrate │ │ ├── Buffer.hpp │ │ ├── CydiaSubstrate.h │ │ ├── SubstrateARM.hpp │ │ ├── SubstrateDebug.cpp │ │ ├── SubstrateDebug.hpp │ │ ├── SubstrateHook.cpp │ │ ├── SubstrateHook.h │ │ ├── SubstrateLog.hpp │ │ ├── SubstratePosixMemory.cpp │ │ ├── SubstrateX86.hpp │ │ ├── SymbolFinder.cpp │ │ ├── SymbolFinder.h │ │ ├── hde64.c │ │ ├── hde64.h │ │ └── table64.h │ └── libs │ │ ├── arm64-v8a │ │ └── libdobby.a │ │ ├── armeabi-v7a │ │ └── libdobby.a │ │ ├── x86 │ │ └── libdobby.a │ │ └── x86_64 │ │ └── libdobby.a │ └── res │ ├── drawable │ └── ic_launcher_foreground.xml │ ├── layout │ └── activity_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── ic_launcher_background.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | .idea/* 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | 87 | # Android Profiling 88 | *.hprof -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-Mod-Menu-BNM 2 | Unity(il2cpp) Game Mod Auto-Update template 3 | 4 | Added bnm and dobby to the lgl template 5 | 6 | # Build and Installation 7 | Android Studio is required: https://developer.android.com/studio
8 | 9 | # Credits 10 | geokar2006 - https://github.com/geokar2006/ByNameModding
11 | LGLTeam - https://github.com/LGLTeam/Android-Mod-Menu
12 | jmpews - https://github.com/jmpews/Dobby
13 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | defaultConfig { 6 | applicationId "com.android.support" 7 | minSdkVersion 19 8 | targetSdkVersion 30 9 | versionCode 1 10 | versionName "3.2" 11 | ndk { 12 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86' 13 | } 14 | signingConfig signingConfigs.debug 15 | } 16 | buildTypes { 17 | release { 18 | shrinkResources false 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | debug { 23 | shrinkResources false 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | externalNativeBuild { 29 | ndkBuild { 30 | path file('src/main/jni/Android.mk') 31 | } 32 | } 33 | } 34 | 35 | //dependencies must be placed below 'android' brackets to get it work on AIDE 36 | dependencies { 37 | implementation fileTree(dir: 'libs', include: ['*.jar']) 38 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | #-dontobfuscate 23 | -keepclassmembers class ** { 24 | public static void Start (***); 25 | } 26 | -keep public class com.android.support.MainActivity 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/android/support/CrashHandler.java: -------------------------------------------------------------------------------- 1 | //Credit: Raunak Mods - https://t.me/raunakmods786 2 | 3 | package com.android.support; 4 | 5 | import android.app.Activity; 6 | import android.app.AlertDialog; 7 | import android.app.Application; 8 | import android.content.ActivityNotFoundException; 9 | import android.content.ClipData; 10 | import android.content.ClipboardManager; 11 | import android.content.Context; 12 | import android.content.DialogInterface; 13 | import android.content.Intent; 14 | import android.content.pm.PackageInfo; 15 | import android.content.pm.PackageManager; 16 | import android.content.res.Resources; 17 | import android.os.Build; 18 | import android.os.Bundle; 19 | import android.text.Html; 20 | import android.text.InputFilter; 21 | import android.text.InputType; 22 | import android.text.TextUtils; 23 | import android.text.method.DigitsKeyListener; 24 | import android.util.Log; 25 | import android.view.Menu; 26 | import android.view.MenuItem; 27 | import android.view.View; 28 | import android.view.ViewGroup; 29 | import android.view.inputmethod.InputMethodManager; 30 | import android.widget.EditText; 31 | import android.widget.HorizontalScrollView; 32 | import android.widget.LinearLayout; 33 | import android.widget.ScrollView; 34 | import android.widget.TextView; 35 | import android.widget.Toast; 36 | 37 | import java.io.File; 38 | import java.io.FileOutputStream; 39 | import java.io.IOException; 40 | import java.io.PrintWriter; 41 | import java.io.StringWriter; 42 | import java.lang.Thread.UncaughtExceptionHandler; 43 | import java.text.SimpleDateFormat; 44 | import java.util.Date; 45 | 46 | public final class CrashHandler { 47 | 48 | public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler(); 49 | 50 | public static void init(final Context app, final boolean overlayRequired) { 51 | Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 52 | 53 | @Override 54 | public void uncaughtException(Thread thread, Throwable throwable) { 55 | Log.e("AppCrash", "Error just lunched "); 56 | try { 57 | tryUncaughtException(thread, throwable); 58 | } catch (Throwable e) { 59 | e.printStackTrace(); 60 | if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) 61 | DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable); 62 | else 63 | System.exit(2); 64 | } 65 | } 66 | 67 | private void tryUncaughtException(Thread thread, Throwable throwable) { 68 | Log.e("AppCrash", "Try saving log"); 69 | 70 | final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss").format(new Date()); 71 | String fileName = "mod_menu_crash_" + time + ".txt"; 72 | String dirName; 73 | 74 | if (Build.VERSION.SDK_INT >= 30) { //Android R. AIDE didn't support Build.VERSION_CODES.R 75 | dirName = "/storage/emulated/0/Documents/"; 76 | } else { 77 | dirName = String.valueOf(app.getExternalFilesDir(null)); 78 | } 79 | 80 | File crashFile = new File(dirName, fileName); 81 | 82 | String versionName = "unknown"; 83 | long versionCode = 0; 84 | try { 85 | PackageInfo packageInfo = app.getPackageManager().getPackageInfo(app.getPackageName(), 0); 86 | versionName = packageInfo.versionName; 87 | versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() 88 | : packageInfo.versionCode; 89 | } catch (PackageManager.NameNotFoundException ignored) { 90 | } 91 | 92 | String fullStackTrace; 93 | { 94 | StringWriter sw = new StringWriter(); 95 | PrintWriter pw = new PrintWriter(sw); 96 | throwable.printStackTrace(pw); 97 | fullStackTrace = sw.toString(); 98 | pw.close(); 99 | } 100 | 101 | StringBuilder devInfo = new StringBuilder(); 102 | devInfo.append("************* Crash Head ****************\n"); 103 | devInfo.append("Time Of Crash : ").append(time).append("\n"); 104 | devInfo.append("Device Manufacturer: ").append(Build.MANUFACTURER).append("\n"); 105 | devInfo.append("Device Model : ").append(Build.MODEL).append("\n"); 106 | devInfo.append("Android Version : ").append(Build.VERSION.RELEASE).append("\n"); 107 | devInfo.append("Android SDK : ").append(Build.VERSION.SDK_INT).append("\n"); 108 | devInfo.append("App VersionName : ").append(versionName).append("\n"); 109 | devInfo.append("App VersionCode : ").append(versionCode).append("\n"); 110 | devInfo.append("************* Crash Head ****************\n"); 111 | devInfo.append("\n").append(fullStackTrace); 112 | 113 | String errorLog = devInfo.toString(); 114 | 115 | try { 116 | writeFile(crashFile, errorLog); 117 | } catch (IOException ignored) { 118 | } 119 | 120 | Toast.makeText(app, "Game has crashed unexpectedly", Toast.LENGTH_LONG).show(); 121 | Toast.makeText(app, "Log saved to: " + String.valueOf(crashFile).replace("/storage/emulated/0/", ""), Toast.LENGTH_LONG).show(); 122 | 123 | Log.e("AppCrash", "Done"); 124 | 125 | System.exit(2); 126 | } 127 | 128 | private void writeFile(File file, String content) throws IOException { 129 | File parentFile = file.getParentFile(); 130 | if (parentFile != null && !parentFile.exists()) { 131 | parentFile.mkdirs(); 132 | } 133 | file.createNewFile(); 134 | FileOutputStream fos = new FileOutputStream(file); 135 | fos.write(content.getBytes()); 136 | try { 137 | fos.close(); 138 | } catch (IOException e) { 139 | } 140 | } 141 | }); 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/support/Launcher.java: -------------------------------------------------------------------------------- 1 | package com.android.support; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.Service; 5 | import android.content.Intent; 6 | import android.os.Handler; 7 | import android.os.IBinder; 8 | import android.view.View; 9 | 10 | public class Launcher extends Service { 11 | 12 | Menu menu; 13 | 14 | //When this Class is called the code in this function will be executed 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | 19 | menu = new Menu(this); 20 | menu.SetWindowManagerWindowService(); 21 | menu.ShowMenu(); 22 | 23 | //Create a handler for this Class 24 | final Handler handler = new Handler(); 25 | handler.post(new Runnable() { 26 | public void run() { 27 | Thread(); 28 | handler.postDelayed(this, 1000); 29 | } 30 | }); 31 | } 32 | 33 | @Override 34 | public IBinder onBind(Intent intent) { 35 | return null; 36 | } 37 | 38 | //Check if we are still in the game. If now our menu and menu button will dissapear 39 | private boolean isNotInGame() { 40 | ActivityManager.RunningAppProcessInfo runningAppProcessInfo = new ActivityManager.RunningAppProcessInfo(); 41 | ActivityManager.getMyMemoryState(runningAppProcessInfo); 42 | return runningAppProcessInfo.importance != 100; 43 | } 44 | 45 | private void Thread() { 46 | if (isNotInGame()) { 47 | menu.setVisibility(View.INVISIBLE); 48 | } else { 49 | menu.setVisibility(View.VISIBLE); 50 | } 51 | } 52 | 53 | //Destroy our View 54 | public void onDestroy() { 55 | super.onDestroy(); 56 | menu.onDestroy(); 57 | } 58 | 59 | //Same as above so it wont crash in the background and therefore use alot of Battery life 60 | public void onTaskRemoved(Intent intent) { 61 | super.onTaskRemoved(intent); 62 | try { 63 | Thread.sleep(100); 64 | } catch (InterruptedException e) { 65 | e.printStackTrace(); 66 | } 67 | stopSelf(); 68 | } 69 | 70 | //Override our Start Command so the Service doesnt try to recreate itself when the App is closed 71 | public int onStartCommand(Intent intent, int i, int i2) { 72 | return Service.START_NOT_STICKY; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/support/Main.java: -------------------------------------------------------------------------------- 1 | package com.android.support; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.os.Handler; 9 | import android.provider.Settings; 10 | import android.widget.Toast; 11 | 12 | public class Main { 13 | 14 | //Load lib 15 | static { 16 | // When you change the lib name, change also on Android.mk file 17 | // Both must have same name 18 | System.loadLibrary("MyLibName"); 19 | } 20 | 21 | private static native void CheckOverlayPermission(Context context); 22 | 23 | public static void StartWithoutPermission(Context context) { 24 | CrashHandler.init(context, true); 25 | if (context instanceof Activity) { 26 | //Check if context is an Activity. 27 | Menu menu = new Menu(context); 28 | menu.SetWindowManagerActivity(); 29 | menu.ShowMenu(); 30 | } else { 31 | //Anything else, ask for permission 32 | CheckOverlayPermission(context); 33 | } 34 | } 35 | 36 | public static void Start(Context context) { 37 | CrashHandler.init(context, false); 38 | 39 | CheckOverlayPermission(context); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/support/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.support; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | public class MainActivity extends Activity { 9 | 10 | //Only if you have changed MainActivity to yours and you wanna call game's activity. 11 | public String GameActivity = "com.unity3d.player.UnityPlayerActivity"; 12 | public boolean hasLaunched = false; 13 | 14 | //To call onCreate, please refer to README.md 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | /*Thread.setDefaultUncaughtExceptionHandler( 19 | new Thread.UncaughtExceptionHandler() { 20 | @Override 21 | public void uncaughtException(Thread thread, Throwable e) { 22 | Log.e("AppCrash", "Error just lunched "); 23 | } 24 | });*/ 25 | 26 | 27 | //To launch game activity 28 | if (!hasLaunched) { 29 | try { 30 | //Start service 31 | hasLaunched = true; 32 | //Launch mod menu. 33 | MainActivity.this.startActivity(new Intent(MainActivity.this, Class.forName(MainActivity.this.GameActivity))); 34 | Main.Start(this); 35 | return; 36 | } catch (ClassNotFoundException e) { 37 | Log.e("Mod_menu", "Error. Game's main activity does not exist"); 38 | //Uncomment this if you are following METHOD 2 to launch menu 39 | //Toast.makeText(MainActivity.this, "Error. Game's main activity does not exist", Toast.LENGTH_LONG).show(); 40 | } 41 | } 42 | 43 | //Launch mod menu. 44 | // Main.StartWithoutPermission(this); 45 | Main.Start(this); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/jni/And64InlineHook/And64InlineHook.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @date : 2018/04/18 3 | * @author : Rprop (r_prop@outlook.com) 4 | * https://github.com/Rprop/And64InlineHook 5 | */ 6 | /* 7 | MIT License 8 | 9 | Copyright (c) 2018 Rprop (r_prop@outlook.com) 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | #pragma once 30 | #define A64_MAX_BACKUPS 256 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | void A64HookFunction(void *const symbol, void *const replace, void **result); 37 | void *A64HookFunctionV(void *const symbol, void *const replace, void *const rwx, const uintptr_t rwx_size); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif -------------------------------------------------------------------------------- /app/src/main/jni/And64InlineHook/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 RLib 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/src/main/jni/And64InlineHook/README.md: -------------------------------------------------------------------------------- 1 | # And64InlineHook 2 | Lightweight ARMv8-A(ARM64, AArch64, Little-Endian) Inline Hook Library for Android C/C++ 3 | 4 | # References 5 | [Arm Compiler armasm User Guide](http://infocenter.arm.com/help/topic/com.arm.doc.100069_0610_00_en/pge1427898258836.html) 6 | [Procedure Call Standard for the Arm® 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst) 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | LOCAL_MODULE := libdobby 4 | LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libdobby.a 5 | #For Non-Aide Users: LOCAL_SRC_FILES := $(LOCAL_PATH)/libraries/$(TARGET_ARCH_ABI)/libdobby.a 6 | 7 | include $(PREBUILT_STATIC_LIBRARY) 8 | include $(CLEAR_VARS) 9 | 10 | # Here is the name of your lib. 11 | # When you change the lib name, change also on System.loadLibrary("") under OnCreate method on StaticActivity.java 12 | # Both must have same name 13 | LOCAL_MODULE := MyLibName 14 | 15 | # -std=c++17 is required to support AIDE app with NDK 16 | LOCAL_CFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -fpermissive -fexceptions 17 | LOCAL_CPPFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -Werror -std=c++17 18 | LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fpermissive -Wall -fexceptions 19 | LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all,-llog 20 | LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 21 | LOCAL_ARM_MODE := arm 22 | LOCAL_STATIC_LIBRARIES := libdobby 23 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 24 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/Includes/Dobby 25 | 26 | # Here you add the cpp file to compile 27 | LOCAL_SRC_FILES := Main.cpp \ 28 | Substrate/hde64.c \ 29 | Substrate/SubstrateDebug.cpp \ 30 | Substrate/SubstrateHook.cpp \ 31 | Substrate/SubstratePosixMemory.cpp \ 32 | Substrate/SymbolFinder.cpp \ 33 | KittyMemory/KittyMemory.cpp \ 34 | KittyMemory/MemoryPatch.cpp \ 35 | KittyMemory/MemoryBackup.cpp \ 36 | KittyMemory/KittyUtils.cpp \ 37 | And64InlineHook/And64InlineHook.cpp \ 38 | ByNameModding/BNM.cpp \ 39 | 40 | include $(BUILD_SHARED_LIBRARY) 41 | -------------------------------------------------------------------------------- /app/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | # To AIDE Users: If you are using 32-bit/ARMv7 phone, please remove arm64-v8a 2 | APP_ABI := armeabi-v7a arm64-v8a x86 3 | # APP_PLATFORM := android-18 #APP_PLATFORM does not need to be set. It will automatically defaulting 4 | APP_STL := c++_static 5 | APP_OPTIM := release 6 | APP_THIN_ARCHIVE := true 7 | APP_PIE := true 8 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "BasicStructs/Color.h" 3 | #include "BasicStructs/Quaternion.h" 4 | #include "BasicStructs/Ray.h" 5 | #include "BasicStructs/RaycastHit.h" 6 | #include "BasicStructs/Rect.h" 7 | #include "BasicStructs/Vector2.h" 8 | #include "BasicStructs/Vector3.h" -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/Color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | struct Color { 4 | union { 5 | struct { float r, b, g, a; }; 6 | float data[4]; 7 | }; 8 | inline Color() { SetColor(0, 0, 0, 255); } 9 | inline Color(float r, float g, float b) { SetColor(r, g, b, 255); } 10 | inline Color(float r, float g, float b, float a) { SetColor(r, g, b, a); } 11 | [[maybe_unused]] inline static Color Black(float a = 255) { return Color(0, 0, 0, a); } 12 | [[maybe_unused]] inline static Color Red(float a = 255) { return Color(255, 0, 0, a); } 13 | [[maybe_unused]] inline static Color Green(float a = 255) { return Color(0, 255, 0, a); } 14 | [[maybe_unused]] inline static Color Blue(float a = 255) { return Color(0, 0, 255, a); } 15 | [[maybe_unused]] inline static Color White(float a = 255) { return Color(255, 255, 255, a); } 16 | [[maybe_unused]] inline static Color Orange(float a = 255) { return Color(255, 153, 0, a); } 17 | [[maybe_unused]] inline static Color Yellow(float a = 255) { return Color(255, 255, 0, a); } 18 | [[maybe_unused]] inline static Color Cyan(float a = 255) { return Color(0, 255, 255, a); } 19 | [[maybe_unused]] inline static Color Magenta(float a = 255) { return Color(255, 0, 255, a); } 20 | [[maybe_unused]] inline static Color MonoBlack(float a = 1){ return Color(0, 0, 0, a); } 21 | [[maybe_unused]] inline static Color MonoRed(float a = 1){ return Color(1, 0, 0, a); } 22 | [[maybe_unused]] inline static Color MonoGreen(float a = 1){ return Color(0, 1, 0, a); } 23 | [[maybe_unused]] inline static Color MonoBlue(float a = 1){ return Color(0, 0, 1, a); } 24 | [[maybe_unused]] inline static Color MonoWhite(float a = 1){ return Color(1, 1, 1, a); } 25 | [[maybe_unused]] inline static Color MonoOrange(float a = 1){ return Color(1, 0.55, 0, a); } 26 | [[maybe_unused]] inline static Color MonoYellow(float a = 1){ return Color(1, 1, 0, a); } 27 | [[maybe_unused]] inline static Color MonoCyan(float a = 1){ return Color(0, 1, 1, a); } 28 | [[maybe_unused]] inline static Color MonoMagenta(float a = 1){ return Color(1, 0, 1, a); } 29 | [[maybe_unused]] inline static Color random(float a = 255) { 30 | float r = static_cast(rand()) / static_cast(255); 31 | float g = static_cast(rand()) / static_cast(255); 32 | float b = static_cast(rand()) / static_cast(255); 33 | return Color(r, g, b, a); 34 | } 35 | inline void SetColor(float r1, float g1, float b1, float a1 = 255) { 36 | r = r1; 37 | g = g1; 38 | b = b1; 39 | a = a1; 40 | } 41 | inline std::string str() { return OBFUSCATES_BNM("r: ") + std::to_string(r) + OBFUSCATES_BNM(", g: ") + std::to_string(g) + OBFUSCATES_BNM(", b: ") + std::to_string(b) + OBFUSCATES_BNM(", a: ") + std::to_string(a); } 42 | }; -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/Ray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Vector3.h" 3 | struct Ray { 4 | Vector3 m_Origin, m_Direction; 5 | std::string str() { return OBFUSCATES_BNM("m_Origin: ") + m_Origin.str() + OBFUSCATES_BNM(", m_Direction: ") + m_Direction.str(); } 6 | }; -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/RaycastHit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Vector3.h" 3 | #include "Vector2.h" 4 | struct RaycastHit { 5 | Vector3 Point{}, Normal{}; 6 | unsigned int FaceID{}; 7 | float Distance{}; 8 | Vector2 UV{}; 9 | #if UNITY_VER > 174 10 | int m_Collider{}; 11 | #else 12 | void *m_Collider{}; 13 | #endif 14 | void *get_Collider() const; 15 | std::string str() { return OBFUSCATES_BNM("Point: ") + Point.str() + OBFUSCATES_BNM(", Normal: ") + Normal.str() + OBFUSCATES_BNM(", FaceID: ") + std::to_string(FaceID) + OBFUSCATES_BNM(", Distance: ") + std::to_string(Distance) + OBFUSCATES_BNM(", UV: ") + UV.str() + OBFUSCATES_BNM(", m_Collider: ") + std::to_string((DWORD)m_Collider); } 16 | }; -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/Rect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct Rect { 3 | union { 4 | struct { float x, y, w, h; }; 5 | float data[4]; 6 | }; 7 | Rect(): x(0), y(0), w(0), h(0) {} 8 | Rect(float x1, float y1, float w1, float h1): x(x1), y(y1), w(w1), h(h1) {} 9 | std::string str() { return OBFUSCATES_BNM("x: ") + std::to_string(x) + OBFUSCATES_BNM(", y: ") + std::to_string(y) + OBFUSCATES_BNM(", w: ") + std::to_string(w) + OBFUSCATES_BNM(", h: ") + std::to_string(h); } 10 | }; -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/Vector2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct Vector2 { 3 | union { 4 | struct { float x, y; }; 5 | float data[2]; 6 | }; 7 | inline Vector2() : x(0), y(0) {}; 8 | inline Vector2(float x, float y) : x(x), y(y) {}; 9 | [[maybe_unused]] inline static Vector2 Down() { return Vector2(0, -1); } 10 | [[maybe_unused]] inline static Vector2 Left() { return Vector2(-1, 0); } 11 | [[maybe_unused]] inline static Vector2 One() { return Vector2(1, 1); } 12 | [[maybe_unused]] inline static Vector2 Right() { return Vector2(1, 0); } 13 | [[maybe_unused]] inline static Vector2 Up() { return Vector2(0, 1); } 14 | inline static Vector2 Zero() { return Vector2(0, 0); } 15 | inline static float Angle(Vector2, Vector2); 16 | [[maybe_unused]] inline static Vector2 ClampMagnitude(Vector2, float); 17 | [[maybe_unused]] inline static float Component(Vector2, Vector2); 18 | [[maybe_unused]] inline static float Distance(Vector2, Vector2); 19 | inline static float Dot(Vector2, Vector2); 20 | [[maybe_unused]] inline static Vector2 FromPolar(float, float); 21 | [[maybe_unused]] inline static Vector2 Lerp(Vector2, Vector2, float) ; 22 | inline static Vector2 LerpUnclamped(Vector2, Vector2, float); 23 | inline static float Magnitude(Vector2); 24 | [[maybe_unused]] inline static Vector2 Max(Vector2, Vector2); 25 | [[maybe_unused]] inline static Vector2 Min(Vector2, Vector2); 26 | [[maybe_unused]] inline static Vector2 MoveTowards(Vector2, Vector2, float); 27 | inline static Vector2 Normalize(Vector2); 28 | [[maybe_unused]] inline static void OrthoNormalize(Vector2 &, Vector2 &); 29 | inline static Vector2 Project(Vector2, Vector2); 30 | [[maybe_unused]] inline static Vector2 Reflect(Vector2, Vector2); 31 | inline static Vector2 Reject(Vector2, Vector2); 32 | [[maybe_unused]] inline static Vector2 RotateTowards(Vector2, Vector2, float, float); 33 | [[maybe_unused]] inline static Vector2 Scale(Vector2, Vector2); 34 | [[maybe_unused]] inline static Vector2 Slerp(Vector2, Vector2, float); 35 | inline static Vector2 SlerpUnclamped(Vector2, Vector2, float); 36 | inline static float SqrMagnitude(Vector2); 37 | [[maybe_unused]] inline static void ToPolar(Vector2, float &, float &); 38 | inline float magnitude() { return Magnitude(*this); } 39 | inline float sqrMagnitude() { return SqrMagnitude(*this); } 40 | inline Vector2 normalized() { return Normalize(*this); } 41 | inline std::string str() { return std::to_string(x) + OBFUSCATES_BNM(", ") + std::to_string(y); } 42 | inline Vector2& operator+=(float rhs) { x += rhs; y += rhs; return *this; } 43 | inline Vector2& operator-=(float rhs) { x -= rhs; y -= rhs; return *this; } 44 | inline Vector2& operator*=(float rhs) { x *= rhs; y *= rhs; return *this; } 45 | inline Vector2& operator/=(float rhs) { x /= rhs; y /= rhs; return *this; } 46 | inline Vector2& operator+=(Vector2 rhs) { x += rhs.x; y += rhs.y; return *this; } 47 | inline Vector2& operator-=(Vector2 rhs) { x -= rhs.x; y -= rhs.y; return *this; } 48 | }; 49 | 50 | inline Vector2 operator+(Vector2 lhs, const float rhs) { return Vector2(lhs.x + rhs, lhs.y + rhs); } 51 | inline Vector2 operator-(Vector2 lhs, const float rhs) { return Vector2(lhs.x - rhs, lhs.y - rhs); } 52 | inline Vector2 operator*(Vector2 lhs, const float rhs) { return Vector2(lhs.x * rhs, lhs.y * rhs); } 53 | inline Vector2 operator/(Vector2 lhs, const float rhs) { return Vector2(lhs.x / rhs, lhs.y / rhs); } 54 | inline Vector2 operator+(const float lhs, Vector2 rhs) { return Vector2(lhs + rhs.x, lhs + rhs.y); } 55 | inline Vector2 operator-(const float lhs, Vector2 rhs) { return Vector2(lhs - rhs.x, lhs - rhs.y); } 56 | inline Vector2 operator*(const float lhs, Vector2 rhs) { return Vector2(lhs * rhs.x, lhs * rhs.y); } 57 | inline Vector2 operator/(const float lhs, Vector2 rhs) { return Vector2(lhs / rhs.x, lhs / rhs.y); } 58 | inline Vector2 operator+(Vector2 lhs, const Vector2 rhs) { return Vector2(lhs.x + rhs.x, lhs.y + rhs.y); } 59 | inline Vector2 operator-(Vector2 lhs, const Vector2 rhs) { return Vector2(lhs.x - rhs.x, lhs.y - rhs.y); } 60 | inline Vector2 operator*(Vector2 lhs, const Vector2 rhs) { return Vector2(lhs.x * rhs.x, lhs.y * rhs.y); } 61 | inline Vector2 operator/(Vector2 lhs, const Vector2 rhs) { return Vector2(lhs.x / rhs.x, lhs.y / rhs.y); } 62 | inline bool operator==(const Vector2 lhs, const Vector2 rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } 63 | inline bool operator!=(const Vector2 lhs, const Vector2 rhs) { return lhs.x != rhs.x && lhs.y != rhs.y; } 64 | inline Vector2 operator-(Vector2 v) {return v * -1;} 65 | 66 | float Vector2::Angle(Vector2 a, Vector2 b) { 67 | float v = Dot(a, b) / (a.magnitude() * b.magnitude()); 68 | v = fmax(v, -1.0); 69 | v = fmin(v, 1.0); 70 | return acos(v); 71 | } 72 | 73 | [[maybe_unused]] Vector2 Vector2::ClampMagnitude(Vector2 vector, float maxLength) { 74 | float length = vector.magnitude(); 75 | if (length > maxLength) vector *= maxLength / length; 76 | return vector; 77 | } 78 | 79 | [[maybe_unused]] float Vector2::Component(Vector2 a, Vector2 b) { 80 | return Dot(a, b) / b.magnitude(); 81 | } 82 | 83 | [[maybe_unused]] float Vector2::Distance(Vector2 a, Vector2 b) { 84 | return (a - b).magnitude(); 85 | } 86 | 87 | float Vector2::Dot(Vector2 lhs, Vector2 rhs) { 88 | return lhs.x * rhs.x + lhs.y * rhs.y; 89 | } 90 | 91 | [[maybe_unused]] Vector2 Vector2::FromPolar(float rad, float theta) { 92 | Vector2 v; 93 | v.x = rad * cos(theta); 94 | v.y = rad * sin(theta); 95 | return v; 96 | } 97 | 98 | [[maybe_unused]] Vector2 Vector2::Lerp(Vector2 a, Vector2 b, float t) { 99 | if (t < 0) return a; 100 | else if (t > 1) return b; 101 | return LerpUnclamped(a, b, t); 102 | } 103 | 104 | Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, float t) { 105 | return (b - a) * t + a; 106 | } 107 | 108 | float Vector2::Magnitude(Vector2 v) { 109 | return sqrt(v.sqrMagnitude()); 110 | } 111 | 112 | [[maybe_unused]] Vector2 Vector2::Max(Vector2 a, Vector2 b) { 113 | float x = a.x > b.x ? a.x : b.x; 114 | float y = a.y > b.y ? a.y : b.y; 115 | return Vector2(x, y); 116 | } 117 | 118 | [[maybe_unused]] Vector2 Vector2::Min(Vector2 a, Vector2 b) { 119 | float x = a.x > b.x ? b.x : a.x; 120 | float y = a.y > b.y ? b.y : a.y; 121 | return Vector2(x, y); 122 | } 123 | 124 | [[maybe_unused]] Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta) { 125 | Vector2 d = target - current; 126 | float m = d.magnitude(); 127 | if (m < maxDistanceDelta || m == 0) return target; 128 | return current + (d * maxDistanceDelta / m); 129 | } 130 | 131 | Vector2 Vector2::Normalize(Vector2 v) { 132 | float mag = v.magnitude(); 133 | if (mag == 0) return Vector2::Zero(); 134 | return v / mag; 135 | } 136 | 137 | [[maybe_unused]] void Vector2::OrthoNormalize(Vector2 &normal, Vector2 &tangent) { 138 | normal = normal.normalized(); 139 | tangent = Reject(tangent, normal); 140 | tangent = tangent.normalized(); 141 | } 142 | 143 | Vector2 Vector2::Project(Vector2 a, Vector2 b) { 144 | float m = b.magnitude(); 145 | return Dot(a, b) / (m * m) * b; 146 | } 147 | 148 | [[maybe_unused]] Vector2 Vector2::Reflect(Vector2 vector, Vector2 planeNormal) { 149 | return vector - 2 * Project(vector, planeNormal); 150 | } 151 | 152 | Vector2 Vector2::Reject(Vector2 a, Vector2 b) { 153 | return a - Project(a, b); 154 | } 155 | 156 | [[maybe_unused]] Vector2 Vector2::RotateTowards(Vector2 current, Vector2 target, float maxRadiansDelta, float maxMagnitudeDelta) { 157 | float magCur = current.magnitude(); 158 | float magTar = target.magnitude(); 159 | float newMag = magCur + maxMagnitudeDelta * ((magTar > magCur) - (magCur > magTar)); 160 | newMag = fmin(newMag, fmax(magCur, magTar)); 161 | newMag = fmax(newMag, fmin(magCur, magTar)); 162 | float totalAngle = Angle(current, target) - maxRadiansDelta; 163 | if (totalAngle <= 0) return target.normalized() * newMag; 164 | else if (totalAngle >= M_PI) return -target.normalized() * newMag; 165 | float axis = current.x * target.y - current.y * target.x; 166 | axis = axis / fabs(axis); 167 | if (!(1 - fabs(axis) < 0.00001)) axis = 1; 168 | current = current.normalized(); 169 | Vector2 newVector = current * cos(maxRadiansDelta) + Vector2(-current.y, current.x) * sin(maxRadiansDelta) * axis; 170 | return newVector * newMag; 171 | } 172 | 173 | [[maybe_unused]] Vector2 Vector2::Scale(Vector2 a, Vector2 b) { 174 | return Vector2(a.x * b.x, a.y * b.y); 175 | } 176 | 177 | [[maybe_unused]] Vector2 Vector2::Slerp(Vector2 a, Vector2 b, float t) { 178 | if (t < 0) return a; 179 | else if (t > 1) return b; 180 | return SlerpUnclamped(a, b, t); 181 | } 182 | 183 | Vector2 Vector2::SlerpUnclamped(Vector2 a, Vector2 b, float t) { 184 | float magA = a.magnitude(); 185 | float magB = b.magnitude(); 186 | a /= magA; 187 | b /= magB; 188 | float dot = Dot(a, b); 189 | dot = fmax(dot, -1.0); 190 | dot = fmin(dot, 1.0); 191 | float theta = acos(dot) * t; 192 | Vector2 relativeVec = (b - a * dot).normalized(); 193 | Vector2 newVec = a * cos(theta) + relativeVec * sin(theta); 194 | return newVec * (magA + (magB - magA) * t); 195 | } 196 | 197 | float Vector2::SqrMagnitude(Vector2 v) { 198 | return v.x * v.x + v.y * v.y; 199 | } 200 | 201 | [[maybe_unused]] void Vector2::ToPolar(Vector2 vector, float &rad, float &theta) { 202 | rad = vector.magnitude(); 203 | theta = atan2(vector.y, vector.x); 204 | } -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/BasicStructs/Vector3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct Quaternion; 3 | struct Vector3 { 4 | union { 5 | struct { float x, y, z; }; 6 | float data[3]; 7 | }; 8 | inline Vector3() : x(0), y(0), z(0) {}; 9 | inline Vector3(float x, float y, float z) : x(x), y(y), z(z) {}; 10 | [[maybe_unused]] inline static Vector3 Back() { return Vector3(0, 0, -1); }; 11 | [[maybe_unused]] inline static Vector3 Down() { return Vector3(0, -1, 0); }; 12 | [[maybe_unused]] inline static Vector3 Forward() { return Vector3(0, 0, 1); }; 13 | [[maybe_unused]] inline static Vector3 Left() { return Vector3(-1, 0, 0); }; 14 | [[maybe_unused]] inline static Vector3 Right() { return Vector3(1, 0, 0); }; 15 | [[maybe_unused]] inline static Vector3 Up() { return Vector3(0, 1, 0); } 16 | [[maybe_unused]] inline static Vector3 Zero() { return Vector3(0, 0, 0); } 17 | [[maybe_unused]] inline static Vector3 One() { return Vector3(1, 1, 1); } 18 | inline static float Angle(Vector3 from, Vector3 to); 19 | inline static float Dot(Vector3, Vector3); 20 | [[maybe_unused]] inline static Vector3 ClampMagnitude(Vector3, float); 21 | [[maybe_unused]] inline static float Component(Vector3, Vector3); 22 | inline static Vector3 Cross(Vector3, Vector3); 23 | [[maybe_unused]] inline static float Distance(Vector3, Vector3); 24 | [[maybe_unused]] inline static Vector3 FromSpherical(float, float, float); 25 | [[maybe_unused]] inline static Vector3 Lerp(Vector3, Vector3, float); 26 | inline static Vector3 LerpUnclamped(Vector3, Vector3, float); 27 | [[maybe_unused]] inline static Vector3 Max(Vector3, Vector3); 28 | [[maybe_unused]] inline static Vector3 Min(Vector3, Vector3); 29 | [[maybe_unused]] inline static Vector3 MoveTowards(Vector3, Vector3, float); 30 | inline static Vector3 Orthogonal(Vector3); 31 | [[maybe_unused]] inline static Vector3 RotateTowards(Vector3, Vector3, float, float); 32 | [[maybe_unused]] inline static Vector3 Scale(Vector3, Vector3); 33 | [[maybe_unused]] inline static Vector3 Slerp(Vector3, Vector3, float); 34 | inline static Vector3 SlerpUnclamped(Vector3, Vector3, float); 35 | [[maybe_unused]] inline static void ToSpherical(Vector3 vector, float &, float &, float &); 36 | inline static float Magnitude(Vector3); 37 | inline static float SqrMagnitude(Vector3); 38 | inline static Vector3 Normalize(Vector3); 39 | inline static Vector3 NormalizeEuler(Vector3); 40 | inline static float NormalizeAngle(float f); 41 | [[maybe_unused]] inline static Vector3 FromString(std::string); 42 | inline Vector3 orthogonal() { return Orthogonal(*this); } 43 | inline float magnitude() { return Magnitude(*this); } 44 | inline float sqrMagnitude() { return SqrMagnitude(*this); } 45 | inline Vector3 normalized() { return Normalize(*this); } 46 | [[maybe_unused]] inline Vector3 normalizedEuler() { return NormalizeEuler(*this); } 47 | inline std::string str() { return std::to_string(x) + OBFUSCATES_BNM(", ") + std::to_string(y) + OBFUSCATES_BNM(", ") + std::to_string(z); } 48 | inline const Vector3& operator+=(float v) { x+=v; y+=v; y+=v; return *this; }; 49 | inline const Vector3& operator-=(float v) { x-=v; y-=v; y-=v; return *this; }; 50 | inline const Vector3& operator*=(float v) { x*=v; y*=v; z*=v; return *this; }; 51 | inline const Vector3& operator/=(float v) { x/=v; y/=v; z/=v; return *this; }; 52 | inline const Vector3& operator+=(Vector3 v) { x+=v.x; y+=v.y; z+=v.z; return *this; }; 53 | inline const Vector3& operator-=(Vector3 v) { x-=v.x; y-=v.y; z-=v.z; return *this; }; 54 | inline const Vector3& operator*=(Vector3 v) { x*=v.x; y*=v.y; z*=v.z; return *this; }; 55 | inline Vector3& operator/=(Vector3 v) { x/=v.x; y/=v.y; z/=v.z; return *this; }; 56 | }; 57 | inline Vector3 operator+(Vector3 lhs, const float rhs) { return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs); } 58 | inline Vector3 operator-(Vector3 lhs, const float rhs) { return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs); } 59 | inline Vector3 operator*(Vector3 lhs, const float rhs) { return Vector3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); } 60 | inline Vector3 operator/(Vector3 lhs, const float rhs) { return Vector3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); } 61 | inline Vector3 operator+(const float lhs, Vector3 rhs) { return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z); } 62 | inline Vector3 operator-(const float lhs, Vector3 rhs) { return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z); } 63 | inline Vector3 operator*(const float lhs, Vector3 rhs) { return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } 64 | inline Vector3 operator/(const float lhs, Vector3 rhs) { return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z); } 65 | inline Vector3 operator+(Vector3 lhs, const Vector3 rhs) { return Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); } 66 | inline Vector3 operator-(Vector3 lhs, const Vector3 rhs) { return Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } 67 | inline Vector3 operator*(Vector3 lhs, const Vector3 rhs) { return Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } 68 | inline Vector3 operator/(Vector3 lhs, const Vector3 rhs) { return Vector3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); } 69 | inline bool operator==(const Vector3 lhs, const Vector3 rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; } 70 | inline bool operator!=(const Vector3 lhs, const Vector3 rhs) { return lhs.x != rhs.x && lhs.y != rhs.y && lhs.z != rhs.z; } 71 | inline Vector3 operator-(Vector3 v) {return v * -1;} 72 | 73 | float Vector3::Angle(Vector3 from, Vector3 to) { 74 | float v = Dot(from, to) / (from.magnitude() * to.magnitude()); 75 | v = fmax(v, -1.0); 76 | v = fmin(v, 1.0); 77 | return acos(v); 78 | } 79 | 80 | float Vector3::Dot(Vector3 lhs, Vector3 rhs) { 81 | return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; 82 | } 83 | [[maybe_unused]] Vector3 Vector3::ClampMagnitude(Vector3 vector, float maxLength) { 84 | float length = vector.magnitude(); 85 | if (length > maxLength) vector *= maxLength / length; 86 | return vector; 87 | } 88 | 89 | [[maybe_unused]] float Vector3::Component(Vector3 a, Vector3 b) { 90 | return Dot(a, b) / b.magnitude(); 91 | } 92 | 93 | Vector3 Vector3::Cross(Vector3 lhs, Vector3 rhs) { 94 | float x = lhs.y * rhs.z - lhs.z * rhs.y; 95 | float y = lhs.z * rhs.x - lhs.x * rhs.z; 96 | float z = lhs.x * rhs.y - lhs.y * rhs.x; 97 | return Vector3(x, y, z); 98 | } 99 | 100 | [[maybe_unused]] float Vector3::Distance(Vector3 a, Vector3 b) { 101 | return (a - b).magnitude(); 102 | } 103 | 104 | [[maybe_unused]] Vector3 Vector3::FromSpherical(float rad, float theta, float phi) { 105 | Vector3 v; 106 | v.x = rad * sin(theta) * cos(phi); 107 | v.y = rad * sin(theta) * sin(phi); 108 | v.z = rad * cos(theta); 109 | return v; 110 | } 111 | 112 | [[maybe_unused]] Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t) { 113 | if (t < 0) return a; 114 | else if (t > 1) return b; 115 | return LerpUnclamped(a, b, t); 116 | } 117 | 118 | Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t) { 119 | return (b - a) * t + a; 120 | } 121 | 122 | [[maybe_unused]] Vector3 Vector3::Max(Vector3 a, Vector3 b) { 123 | float x = a.x > b.x ? a.x : b.x; 124 | float y = a.y > b.y ? a.y : b.y; 125 | float z = a.z > b.z ? a.z : b.z; 126 | return Vector3(x, y, z); 127 | } 128 | 129 | [[maybe_unused]] Vector3 Vector3::Min(Vector3 a, Vector3 b) { 130 | float x = a.x > b.x ? b.x : a.x; 131 | float y = a.y > b.y ? b.y : a.y; 132 | float z = a.z > b.z ? b.z : a.z; 133 | return Vector3(x, y, z); 134 | } 135 | 136 | [[maybe_unused]] Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta) { 137 | Vector3 d = target - current; 138 | float m = d.magnitude(); 139 | if (m < maxDistanceDelta || m == 0) 140 | return target; 141 | return current + (d * maxDistanceDelta / m); 142 | } 143 | 144 | Vector3 Vector3::Orthogonal(Vector3 v) { 145 | return v.z < v.x ? Vector3(v.y, -v.x, 0) : Vector3(0, -v.z, v.y); 146 | } 147 | 148 | [[maybe_unused]] Vector3 Vector3::RotateTowards(Vector3 current, Vector3 target, float maxRadiansDelta, float maxMagnitudeDelta) { 149 | float magCur = current.magnitude(); 150 | float magTar = target.magnitude(); 151 | float newMag = magCur + maxMagnitudeDelta * ((magTar > magCur) - (magCur > magTar)); 152 | newMag = fmin(newMag, fmax(magCur, magTar)); 153 | newMag = fmax(newMag, fmin(magCur, magTar)); 154 | float totalAngle = Angle(current, target) - maxRadiansDelta; 155 | if (totalAngle <= 0) return Normalize(target) * newMag; 156 | else if (totalAngle >= M_PI) return -target.normalized() * newMag; 157 | Vector3 axis = Cross(current, target); 158 | float magAxis = axis.magnitude(); 159 | if (magAxis == 0) axis = Cross(current, current + Vector3(3.95, 5.32, -4.24)).normalized(); 160 | else axis /= magAxis; 161 | current = current.normalized(); 162 | Vector3 newVector = current * cos(maxRadiansDelta) + Cross(axis, current) * sin(maxRadiansDelta); 163 | return newVector * newMag; 164 | } 165 | 166 | [[maybe_unused]] Vector3 Vector3::Scale(Vector3 a, Vector3 b) { 167 | return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); 168 | } 169 | 170 | [[maybe_unused]] Vector3 Vector3::Slerp(Vector3 a, Vector3 b, float t) { 171 | if (t < 0) return a; 172 | else if (t > 1) return b; 173 | return SlerpUnclamped(a, b, t); 174 | } 175 | 176 | Vector3 Vector3::SlerpUnclamped(Vector3 a, Vector3 b, float t) { 177 | float magA = a.magnitude(); 178 | float magB = b.magnitude(); 179 | a /= magA; 180 | b /= magB; 181 | float dot = Dot(a, b); 182 | dot = fmax(dot, -1.0); 183 | dot = fmin(dot, 1.0); 184 | float theta = acos(dot) * t; 185 | Vector3 relativeVec = Normalize(b - a * dot); 186 | Vector3 newVec = a * cos(theta) + relativeVec * sin(theta); 187 | return newVec * (magA + (magB - magA) * t); 188 | } 189 | 190 | [[maybe_unused]] void Vector3::ToSpherical(Vector3 vector, float &rad, float &theta, float &phi) { 191 | rad = vector.magnitude(); 192 | float v = vector.z / rad; 193 | v = fmax(v, -1.0); 194 | v = fmin(v, 1.0); 195 | theta = acos(v); 196 | phi = atan2(vector.y, vector.x); 197 | } 198 | 199 | float Vector3::Magnitude(Vector3 v) { 200 | return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 201 | } 202 | 203 | float Vector3::SqrMagnitude(Vector3 v) { 204 | return v.x * v.x + v.y * v.y + v.z * v.z; 205 | } 206 | 207 | Vector3 Vector3::Normalize(Vector3 v) { 208 | float mag = v.magnitude(); 209 | if (mag == 0) return Vector3::Zero(); 210 | return v / mag; 211 | } 212 | 213 | float Vector3::NormalizeAngle(float f) { 214 | while (f > 360) f -= 360; 215 | while (f < 0) f += 360; 216 | return f; 217 | } 218 | 219 | Vector3 Vector3::NormalizeEuler(Vector3 vec) { 220 | vec.x = NormalizeAngle(vec.x); 221 | vec.y = NormalizeAngle(vec.y); 222 | vec.z = NormalizeAngle(vec.z); 223 | return vec; 224 | } 225 | 226 | [[maybe_unused]] Vector3 Vector3::FromString(std::string str) { 227 | std::vector commands; 228 | std::string buffer = ""; 229 | for (int i = 0; i < str.size(); i++) { 230 | bool no = true; 231 | if (str[i] == 'f') no = false; 232 | if (str[i] != ',') buffer += str[i]; 233 | else if (no) { 234 | commands.push_back(buffer); 235 | buffer = ""; 236 | } 237 | } 238 | if (buffer != "") commands.push_back(buffer); 239 | return Vector3(std::atof(commands[0].c_str()), std::atof(commands[1].c_str()), std::atof(commands[2].c_str())); 240 | } -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/utf8.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | #pragma once 27 | 28 | #include "utf8/checked.h" 29 | #include "utf8/unchecked.h" 30 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/utf8/core.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | #pragma once 27 | #include 28 | 29 | // Determine the C++ standard version. 30 | // If the user defines UTF_CPP_CPLUSPLUS, use that. 31 | // Otherwise, trust the unreliable predefined macro __cplusplus 32 | 33 | #if !defined UTF_CPP_CPLUSPLUS 34 | #define UTF_CPP_CPLUSPLUS __cplusplus 35 | #endif 36 | 37 | #if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later 38 | #define UTF_CPP_OVERRIDE override 39 | #define UTF_CPP_NOEXCEPT noexcept 40 | #else // C++ 98/03 41 | #define UTF_CPP_OVERRIDE 42 | #define UTF_CPP_NOEXCEPT throw() 43 | #endif // C++ 11 or later 44 | 45 | 46 | namespace utf8 47 | { 48 | // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers 49 | // You may need to change them to match your system. 50 | // These typedefs have the same names as ones from cstdint, or boost/cstdint 51 | typedef unsigned char uint8_t; 52 | typedef unsigned short uint16_t; 53 | typedef unsigned int uint32_t; 54 | 55 | // Helper code - not intended to be directly called by the library users. May be changed at any time 56 | namespace internal 57 | { 58 | // Unicode constants 59 | // Leading (high) surrogates: 0xd800 - 0xdbff 60 | // Trailing (low) surrogates: 0xdc00 - 0xdfff 61 | const uint16_t LEAD_SURROGATE_MIN = 0xd800u; 62 | const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; 63 | const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; 64 | const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; 65 | const uint16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10) 66 | const uint32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN 67 | 68 | // Maximum valid value for a Unicode code point 69 | const uint32_t CODE_POINT_MAX = 0x0010ffffu; 70 | 71 | template 72 | inline uint8_t mask8(octet_type oc) 73 | { 74 | return static_cast(0xff & oc); 75 | } 76 | template 77 | inline uint16_t mask16(u16_type oc) 78 | { 79 | return static_cast(0xffff & oc); 80 | } 81 | template 82 | inline bool is_trail(octet_type oc) 83 | { 84 | return ((utf8::internal::mask8(oc) >> 6) == 0x2); 85 | } 86 | 87 | template 88 | inline bool is_lead_surrogate(u16 cp) 89 | { 90 | return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); 91 | } 92 | 93 | template 94 | inline bool is_trail_surrogate(u16 cp) 95 | { 96 | return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); 97 | } 98 | 99 | template 100 | inline bool is_surrogate(u16 cp) 101 | { 102 | return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); 103 | } 104 | 105 | template 106 | inline bool is_code_point_valid(u32 cp) 107 | { 108 | return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); 109 | } 110 | 111 | template 112 | inline typename std::iterator_traits::difference_type 113 | sequence_length(octet_iterator lead_it) 114 | { 115 | uint8_t lead = utf8::internal::mask8(*lead_it); 116 | if (lead < 0x80) 117 | return 1; 118 | else if ((lead >> 5) == 0x6) 119 | return 2; 120 | else if ((lead >> 4) == 0xe) 121 | return 3; 122 | else if ((lead >> 3) == 0x1e) 123 | return 4; 124 | else 125 | return 0; 126 | } 127 | 128 | template 129 | inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) 130 | { 131 | if (cp < 0x80) { 132 | if (length != 1) 133 | return true; 134 | } 135 | else if (cp < 0x800) { 136 | if (length != 2) 137 | return true; 138 | } 139 | else if (cp < 0x10000) { 140 | if (length != 3) 141 | return true; 142 | } 143 | 144 | return false; 145 | } 146 | 147 | enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; 148 | 149 | /// Helper for get_sequence_x 150 | template 151 | utf_error increase_safely(octet_iterator& it, octet_iterator end) 152 | { 153 | if (++it == end) 154 | return NOT_ENOUGH_ROOM; 155 | 156 | if (!utf8::internal::is_trail(*it)) 157 | return INCOMPLETE_SEQUENCE; 158 | 159 | return UTF8_OK; 160 | } 161 | 162 | #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} 163 | 164 | /// get_sequence_x functions decode utf-8 sequences of the length x 165 | template 166 | utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) 167 | { 168 | if (it == end) 169 | return NOT_ENOUGH_ROOM; 170 | 171 | code_point = utf8::internal::mask8(*it); 172 | 173 | return UTF8_OK; 174 | } 175 | 176 | template 177 | utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) 178 | { 179 | if (it == end) 180 | return NOT_ENOUGH_ROOM; 181 | 182 | code_point = utf8::internal::mask8(*it); 183 | 184 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 185 | 186 | code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); 187 | 188 | return UTF8_OK; 189 | } 190 | 191 | template 192 | utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) 193 | { 194 | if (it == end) 195 | return NOT_ENOUGH_ROOM; 196 | 197 | code_point = utf8::internal::mask8(*it); 198 | 199 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 200 | 201 | code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); 202 | 203 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 204 | 205 | code_point += (*it) & 0x3f; 206 | 207 | return UTF8_OK; 208 | } 209 | 210 | template 211 | utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) 212 | { 213 | if (it == end) 214 | return NOT_ENOUGH_ROOM; 215 | 216 | code_point = utf8::internal::mask8(*it); 217 | 218 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 219 | 220 | code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); 221 | 222 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 223 | 224 | code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; 225 | 226 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) 227 | 228 | code_point += (*it) & 0x3f; 229 | 230 | return UTF8_OK; 231 | } 232 | 233 | #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR 234 | 235 | template 236 | utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) 237 | { 238 | if (it == end) 239 | return NOT_ENOUGH_ROOM; 240 | 241 | // Save the original value of it so we can go back in case of failure 242 | // Of course, it does not make much sense with i.e. stream iterators 243 | octet_iterator original_it = it; 244 | 245 | uint32_t cp = 0; 246 | // Determine the sequence length based on the lead octet 247 | typedef typename std::iterator_traits::difference_type octet_difference_type; 248 | const octet_difference_type length = utf8::internal::sequence_length(it); 249 | 250 | // Get trail octets and calculate the code point 251 | utf_error err = UTF8_OK; 252 | switch (length) { 253 | case 0: 254 | return INVALID_LEAD; 255 | case 1: 256 | err = utf8::internal::get_sequence_1(it, end, cp); 257 | break; 258 | case 2: 259 | err = utf8::internal::get_sequence_2(it, end, cp); 260 | break; 261 | case 3: 262 | err = utf8::internal::get_sequence_3(it, end, cp); 263 | break; 264 | case 4: 265 | err = utf8::internal::get_sequence_4(it, end, cp); 266 | break; 267 | } 268 | 269 | if (err == UTF8_OK) { 270 | // Decoding succeeded. Now, security checks... 271 | if (utf8::internal::is_code_point_valid(cp)) { 272 | if (!utf8::internal::is_overlong_sequence(cp, length)){ 273 | // Passed! Return here. 274 | code_point = cp; 275 | ++it; 276 | return UTF8_OK; 277 | } 278 | else 279 | err = OVERLONG_SEQUENCE; 280 | } 281 | else 282 | err = INVALID_CODE_POINT; 283 | } 284 | 285 | // Failure branch - restore the original value of the iterator 286 | it = original_it; 287 | return err; 288 | } 289 | 290 | template 291 | inline utf_error validate_next(octet_iterator& it, octet_iterator end) { 292 | uint32_t ignored; 293 | return utf8::internal::validate_next(it, end, ignored); 294 | } 295 | 296 | } // namespace internal 297 | 298 | /// The library API - functions intended to be called by the users 299 | 300 | // Byte order mark 301 | const uint8_t bom[] = {0xef, 0xbb, 0xbf}; 302 | 303 | template 304 | octet_iterator find_invalid(octet_iterator start, octet_iterator end) 305 | { 306 | octet_iterator result = start; 307 | while (result != end) { 308 | utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); 309 | if (err_code != internal::UTF8_OK) 310 | return result; 311 | } 312 | return result; 313 | } 314 | 315 | template 316 | inline bool is_valid(octet_iterator start, octet_iterator end) 317 | { 318 | return (utf8::find_invalid(start, end) == end); 319 | } 320 | 321 | template 322 | inline bool starts_with_bom (octet_iterator it, octet_iterator end) 323 | { 324 | return ( 325 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && 326 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && 327 | ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) 328 | ); 329 | } 330 | } // namespace utf8 331 | 332 | 333 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/utf8/cpp11.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | #include "checked.h" 29 | #include 30 | 31 | namespace utf8 32 | { 33 | 34 | inline void append(char32_t cp, std::string& s) 35 | { 36 | append(uint32_t(cp), std::back_inserter(s)); 37 | } 38 | 39 | inline std::string utf16to8(const std::u16string& s) 40 | { 41 | std::string result; 42 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); 43 | return result; 44 | } 45 | 46 | inline std::u16string utf8to16(const std::string& s) 47 | { 48 | std::u16string result; 49 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); 50 | return result; 51 | } 52 | 53 | inline std::string utf32to8(const std::u32string& s) 54 | { 55 | std::string result; 56 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); 57 | return result; 58 | } 59 | 60 | inline std::u32string utf8to32(const std::string& s) 61 | { 62 | std::u32string result; 63 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); 64 | return result; 65 | } 66 | 67 | inline std::size_t find_invalid(const std::string& s) 68 | { 69 | std::string::const_iterator invalid = find_invalid(s.begin(), s.end()); 70 | return (invalid == s.end()) ? std::string::npos : (invalid - s.begin()); 71 | } 72 | 73 | inline bool is_valid(const std::string& s) 74 | { 75 | return is_valid(s.begin(), s.end()); 76 | } 77 | 78 | inline std::string replace_invalid(const std::string& s, char32_t replacement) 79 | { 80 | std::string result; 81 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); 82 | return result; 83 | } 84 | 85 | inline std::string replace_invalid(const std::string& s) 86 | { 87 | std::string result; 88 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); 89 | return result; 90 | } 91 | 92 | inline bool starts_with_bom(const std::string& s) 93 | { 94 | return starts_with_bom(s.begin(), s.end()); 95 | } 96 | 97 | } // namespace utf8 98 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/utf8/cpp17.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | #include "checked.h" 29 | #include 30 | 31 | namespace utf8 32 | { 33 | 34 | inline void append(char32_t cp, std::string& s) 35 | { 36 | append(uint32_t(cp), std::back_inserter(s)); 37 | } 38 | 39 | inline std::string utf16to8(std::u16string_view s) 40 | { 41 | std::string result; 42 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); 43 | return result; 44 | } 45 | 46 | inline std::u16string utf8to16(std::string_view s) 47 | { 48 | std::u16string result; 49 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); 50 | return result; 51 | } 52 | 53 | inline std::string utf32to8(std::u32string_view s) 54 | { 55 | std::string result; 56 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); 57 | return result; 58 | } 59 | 60 | inline std::u32string utf8to32(std::string_view s) 61 | { 62 | std::u32string result; 63 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); 64 | return result; 65 | } 66 | 67 | inline std::size_t find_invalid(std::string_view s) 68 | { 69 | std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end()); 70 | return (invalid == s.end()) ? std::string_view::npos : (invalid - s.begin()); 71 | } 72 | 73 | inline bool is_valid(std::string_view s) 74 | { 75 | return is_valid(s.begin(), s.end()); 76 | } 77 | 78 | inline std::string replace_invalid(std::string_view s, char32_t replacement) 79 | { 80 | std::string result; 81 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); 82 | return result; 83 | } 84 | 85 | inline std::string replace_invalid(std::string_view s) 86 | { 87 | std::string result; 88 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); 89 | return result; 90 | } 91 | 92 | inline bool starts_with_bom(std::string_view s) 93 | { 94 | return starts_with_bom(s.begin(), s.end()); 95 | } 96 | 97 | } // namespace utf8 98 | 99 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_data/utf8/unchecked.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | #pragma once 27 | #include "core.h" 28 | 29 | namespace utf8 30 | { 31 | namespace unchecked 32 | { 33 | template 34 | octet_iterator append(uint32_t cp, octet_iterator result) 35 | { 36 | if (cp < 0x80) // one octet 37 | *(result++) = static_cast(cp); 38 | else if (cp < 0x800) { // two octets 39 | *(result++) = static_cast((cp >> 6) | 0xc0); 40 | *(result++) = static_cast((cp & 0x3f) | 0x80); 41 | } 42 | else if (cp < 0x10000) { // three octets 43 | *(result++) = static_cast((cp >> 12) | 0xe0); 44 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); 45 | *(result++) = static_cast((cp & 0x3f) | 0x80); 46 | } 47 | else { // four octets 48 | *(result++) = static_cast((cp >> 18) | 0xf0); 49 | *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); 50 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); 51 | *(result++) = static_cast((cp & 0x3f) | 0x80); 52 | } 53 | return result; 54 | } 55 | 56 | template 57 | output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) 58 | { 59 | while (start != end) { 60 | octet_iterator sequence_start = start; 61 | internal::utf_error err_code = utf8::internal::validate_next(start, end); 62 | switch (err_code) { 63 | case internal::UTF8_OK : 64 | for (octet_iterator it = sequence_start; it != start; ++it) 65 | *out++ = *it; 66 | break; 67 | case internal::NOT_ENOUGH_ROOM: 68 | out = utf8::unchecked::append (replacement, out); 69 | start = end; 70 | break; 71 | case internal::INVALID_LEAD: 72 | out = utf8::unchecked::append (replacement, out); 73 | ++start; 74 | break; 75 | case internal::INCOMPLETE_SEQUENCE: 76 | case internal::OVERLONG_SEQUENCE: 77 | case internal::INVALID_CODE_POINT: 78 | out = utf8::unchecked::append (replacement, out); 79 | ++start; 80 | // just one replacement mark for the sequence 81 | while (start != end && utf8::internal::is_trail(*start)) 82 | ++start; 83 | break; 84 | } 85 | } 86 | return out; 87 | } 88 | 89 | template 90 | inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) 91 | { 92 | static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); 93 | return utf8::unchecked::replace_invalid(start, end, out, replacement_marker); 94 | } 95 | 96 | template 97 | uint32_t next(octet_iterator& it) 98 | { 99 | uint32_t cp = utf8::internal::mask8(*it); 100 | typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); 101 | switch (length) { 102 | case 1: 103 | break; 104 | case 2: 105 | it++; 106 | cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); 107 | break; 108 | case 3: 109 | ++it; 110 | cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); 111 | ++it; 112 | cp += (*it) & 0x3f; 113 | break; 114 | case 4: 115 | ++it; 116 | cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); 117 | ++it; 118 | cp += (utf8::internal::mask8(*it) << 6) & 0xfff; 119 | ++it; 120 | cp += (*it) & 0x3f; 121 | break; 122 | } 123 | ++it; 124 | return cp; 125 | } 126 | 127 | template 128 | uint32_t peek_next(octet_iterator it) 129 | { 130 | return utf8::unchecked::next(it); 131 | } 132 | 133 | template 134 | uint32_t prior(octet_iterator& it) 135 | { 136 | while (utf8::internal::is_trail(*(--it))) ; 137 | octet_iterator temp = it; 138 | return utf8::unchecked::next(temp); 139 | } 140 | 141 | template 142 | void advance (octet_iterator& it, distance_type n) 143 | { 144 | const distance_type zero(0); 145 | if (n < zero) { 146 | // backward 147 | for (distance_type i = n; i < zero; ++i) 148 | utf8::unchecked::prior(it); 149 | } else { 150 | // forward 151 | for (distance_type i = zero; i < n; ++i) 152 | utf8::unchecked::next(it); 153 | } 154 | } 155 | 156 | template 157 | typename std::iterator_traits::difference_type 158 | distance (octet_iterator first, octet_iterator last) 159 | { 160 | typename std::iterator_traits::difference_type dist; 161 | for (dist = 0; first < last; ++dist) 162 | utf8::unchecked::next(first); 163 | return dist; 164 | } 165 | 166 | template 167 | octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) 168 | { 169 | while (start != end) { 170 | uint32_t cp = utf8::internal::mask16(*start++); 171 | // Take care of surrogate pairs first 172 | if (utf8::internal::is_lead_surrogate(cp)) { 173 | uint32_t trail_surrogate = utf8::internal::mask16(*start++); 174 | cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; 175 | } 176 | result = utf8::unchecked::append(cp, result); 177 | } 178 | return result; 179 | } 180 | 181 | template 182 | u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) 183 | { 184 | while (start < end) { 185 | uint32_t cp = utf8::unchecked::next(start); 186 | if (cp > 0xffff) { //make a surrogate pair 187 | *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); 188 | *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); 189 | } 190 | else 191 | *result++ = static_cast(cp); 192 | } 193 | return result; 194 | } 195 | 196 | template 197 | octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) 198 | { 199 | while (start != end) 200 | result = utf8::unchecked::append(*(start++), result); 201 | 202 | return result; 203 | } 204 | 205 | template 206 | u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) 207 | { 208 | while (start < end) 209 | (*result++) = utf8::unchecked::next(start); 210 | 211 | return result; 212 | } 213 | 214 | // The iterator class 215 | template 216 | class iterator { 217 | octet_iterator it; 218 | public: 219 | typedef uint32_t value_type; 220 | typedef uint32_t* pointer; 221 | typedef uint32_t& reference; 222 | typedef std::ptrdiff_t difference_type; 223 | typedef std::bidirectional_iterator_tag iterator_category; 224 | iterator () {} 225 | explicit iterator (const octet_iterator& octet_it): it(octet_it) {} 226 | // the default "big three" are OK 227 | octet_iterator base () const { return it; } 228 | uint32_t operator * () const 229 | { 230 | octet_iterator temp = it; 231 | return utf8::unchecked::next(temp); 232 | } 233 | bool operator == (const iterator& rhs) const 234 | { 235 | return (it == rhs.it); 236 | } 237 | bool operator != (const iterator& rhs) const 238 | { 239 | return !(operator == (rhs)); 240 | } 241 | iterator& operator ++ () 242 | { 243 | ::std::advance(it, utf8::internal::sequence_length(it)); 244 | return *this; 245 | } 246 | iterator operator ++ (int) 247 | { 248 | iterator temp = *this; 249 | ::std::advance(it, utf8::internal::sequence_length(it)); 250 | return temp; 251 | } 252 | iterator& operator -- () 253 | { 254 | utf8::unchecked::prior(it); 255 | return *this; 256 | } 257 | iterator operator -- (int) 258 | { 259 | iterator temp = *this; 260 | utf8::unchecked::prior(it); 261 | return temp; 262 | } 263 | }; // class iterator 264 | 265 | } // namespace utf8::unchecked 266 | } // namespace utf8 267 | -------------------------------------------------------------------------------- /app/src/main/jni/ByNameModding/BNM_settings.hpp: -------------------------------------------------------------------------------- 1 | /********** USER AREA **************/ 2 | 3 | //#define UNITY_VER 171 // 2017.1.x 4 | //#define UNITY_VER 172 // From 2017.2.x to 2017.4.x 5 | //#define UNITY_VER 181 // 2018.1.x 6 | //#define UNITY_VER 182 // 2018.2.x 7 | //#define UNITY_VER 183 // From 2018.3.x to 2018.4.x 8 | //#define UNITY_VER 191 // From 2019.1.x to 2019.2.x 9 | //#define UNITY_VER 193 // 2019.3.x 10 | //#define UNITY_VER 194 // 2019.4.x 11 | //#define UNITY_VER 201 // 2020.1.x 12 | #define UNITY_VER 202 // From 2020.2.x to 2020.3.x (They are same) 13 | //#define UNITY_VER 211 // 2021.1.x 14 | //#define UNITY_VER 212 // 2021.2.x 15 | //#define UNITY_VER 213 // 2021.3.x - 2022.1.x 16 | 17 | // Allow to use deprecated methods 18 | // #define BNM_DEPRECATED 19 | 20 | #ifndef NDEBUG 21 | 22 | //! DEBUG LOGS 23 | #define BNM_DEBUG 24 | 25 | //! INFO LOGS 26 | #define BNM_INFO 27 | 28 | //! ERROR LOGS 29 | #define BNM_ERROR 30 | 31 | //! WARNING LOGS 32 | #define BNM_WARNING 33 | 34 | #endif 35 | 36 | //! Include your string obfuscator 37 | #define OBFUSCATE_BNM(str) str // const char * 38 | #define OBFUSCATES_BNM(str) std::string(str) // std::string 39 | #define BNMTAG OBFUSCATE_BNM("ByNameModding") 40 | 41 | //! Include your hooking software 42 | //! Substrate MSHook with And64InlineHook 43 | //!!!!!!!! They may don't work !!!!!!!! 44 | /* 45 | #if defined(__ARM_ARCH_7A__) || defined(__i386__) // armv7 or x86 46 | #include 47 | #include 48 | #elif defined(__aarch64__) //arm64-v8a 49 | #include 50 | #endif 51 | auto HOOK = [](auto ptr, auto newMethod, auto&& oldBytes) { 52 | if (ptr != 0){ 53 | #if defined(__aarch64__) 54 | A64HookFunction((void *)ptr, (void *) newMethod, (void **) &oldBytes); 55 | #else 56 | MSHookFunction((void *)ptr, (void *) newMethod, (void **) &oldBytes); 57 | #endif 58 | } 59 | }; 60 | */ 61 | //! DobbyHook 62 | //!!!!!!!! Recommended !!!!!!!! 63 | #include 64 | auto HOOK = [](auto ptr, auto newMethod, auto&& oldBytes) { 65 | if (((void *)ptr) != nullptr) 66 | DobbyHook((void *)ptr, (void *) newMethod, (void **) &oldBytes); 67 | }; 68 | 69 | // For System.Collections.Generic.Dictionary 70 | 71 | // If the game uses .NET 3.5 uncomment this define 72 | // .NET 3.5 is deprecated but some old games use it 73 | 74 | // #define BNM_DOTNET35 75 | 76 | 77 | // If you need hide dl calls or use custom dl 78 | #define BNM_dlopen dlopen 79 | #define BNM_dlsym dlsym 80 | #define BNM_dlclose dlclose 81 | #define BNM_dladdr dladdr 82 | 83 | // Disabling BNM automatic loading when your lib loaded 84 | // Define it when you using BNM::HardBypass to speed up loading 85 | // #define BNM_DISABLE_AUTO_LOAD 86 | #define BNM_DISABLE_NEW_CLASSES 0 87 | 88 | // Can make game crashes on arm64 89 | // #define BNM_USE_APPDOMAIN // Use System.AppDomain to find il2cpp::vm::Assembly::GetAllAssemblies 90 | /********** USER AREA **************/ 91 | 92 | 93 | #ifdef _WIN32 94 | #define _CRT_SECURE_NO_WARNINGS // If you want try port for windows 95 | #endif 96 | 97 | #ifdef BNM_INFO 98 | #define LOGIBNM(...) ((void)__android_log_print(4, BNMTAG, __VA_ARGS__)) 99 | #else 100 | #define LOGIBNM(...) 101 | #endif 102 | 103 | #ifdef BNM_DEBUG 104 | #define LOGDBNM(...) ((void)__android_log_print(3, BNMTAG, __VA_ARGS__)) 105 | #else 106 | #define LOGDBNM(...) 107 | #endif 108 | 109 | #ifdef BNM_ERROR 110 | #define LOGEBNM(...) ((void)__android_log_print(6, BNMTAG, __VA_ARGS__)) 111 | #else 112 | #define LOGEBNM(...) 113 | #endif 114 | 115 | #ifdef BNM_WARNING 116 | #define LOGWBNM(...) ((void)__android_log_print(5, BNMTAG, __VA_ARGS__)) 117 | #else 118 | #define LOGWBNM(...) 119 | #endif 120 | -------------------------------------------------------------------------------- /app/src/main/jni/Includes/Dobby/dobby.h: -------------------------------------------------------------------------------- 1 | #ifndef dobby_h 2 | #define dobby_h 3 | 4 | // obfuscated interface 5 | #if 0 6 | #define DobbyBuildVersion c343f74888dffad84d9ad08d9c433456 7 | #define DobbyHook c8dc3ffa44f22dbd10ccae213dd8b1f8 8 | #define DobbyInstrument b71e27bca2c362de90c1034f19d839f9 9 | #endif 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #include 16 | #include 17 | 18 | void log_set_level(int level); 19 | void log_switch_to_syslog(); 20 | void log_switch_to_file(const char *path); 21 | 22 | typedef enum { 23 | kMemoryOperationSuccess, 24 | kMemoryOperationError, 25 | kNotSupportAllocateExecutableMemory, 26 | kNotEnough, 27 | kNone 28 | } MemoryOperationError; 29 | 30 | #define PLATFORM_INTERFACE_CODE_PATCH_TOOL_H 31 | MemoryOperationError CodePatch(void *address, uint8_t *buffer, uint32_t buffer_size); 32 | 33 | typedef uintptr_t addr_t; 34 | typedef uint32_t addr32_t; 35 | typedef uint64_t addr64_t; 36 | 37 | #if defined(__arm64__) || defined(__aarch64__) 38 | 39 | #define ARM64_TMP_REG_NDX_0 17 40 | 41 | // float register 42 | typedef union _FPReg { 43 | __int128_t q; 44 | struct { 45 | double d1; 46 | double d2; 47 | } d; 48 | struct { 49 | float f1; 50 | float f2; 51 | float f3; 52 | float f4; 53 | } f; 54 | } FPReg; 55 | 56 | // register context 57 | typedef struct _RegisterContext { 58 | uint64_t dmmpy_0; // dummy placeholder 59 | uint64_t sp; 60 | 61 | uint64_t dmmpy_1; // dummy placeholder 62 | union { 63 | uint64_t x[29]; 64 | struct { 65 | uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, 66 | x23, x24, x25, x26, x27, x28; 67 | } regs; 68 | } general; 69 | 70 | uint64_t fp; 71 | uint64_t lr; 72 | 73 | union { 74 | FPReg q[32]; 75 | struct { 76 | FPReg q0, q1, q2, q3, q4, q5, q6, q7; 77 | // [!!! READ ME !!!] 78 | // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack 79 | FPReg q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29, 80 | q30, q31; 81 | } regs; 82 | } floating; 83 | } RegisterContext; 84 | #elif defined(__arm__) 85 | typedef struct _RegisterContext { 86 | uint32_t dummy_0; 87 | uint32_t dummy_1; 88 | 89 | uint32_t dummy_2; 90 | uint32_t sp; 91 | 92 | union { 93 | uint32_t r[13]; 94 | struct { 95 | uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12; 96 | } regs; 97 | } general; 98 | 99 | uint32_t lr; 100 | } RegisterContext; 101 | #elif defined(_M_IX86) || defined(__i386__) 102 | typedef struct _RegisterContext { 103 | uint32_t dummy_0; 104 | uint32_t esp; 105 | 106 | uint32_t dummy_1; 107 | uint32_t flags; 108 | 109 | union { 110 | struct { 111 | uint32_t eax, ebx, ecx, edx, ebp, esp, edi, esi; 112 | } regs; 113 | } general; 114 | 115 | } RegisterContext; 116 | #elif defined(_M_X64) || defined(__x86_64__) 117 | typedef struct _RegisterContext { 118 | uint64_t dummy_0; 119 | uint64_t rsp; 120 | 121 | union { 122 | struct { 123 | uint64_t rax, rbx, rcx, rdx, rbp, rsp, rdi, rsi, r8, r9, r10, r11, r12, r13, r14, r15; 124 | } regs; 125 | } general; 126 | 127 | uint64_t dummy_1; 128 | uint64_t flags; 129 | } RegisterContext; 130 | #endif 131 | 132 | #define RT_FAILED -1 133 | #define RT_SUCCESS 0 134 | typedef enum _RetStatus { RS_FAILED = -1, RS_SUCCESS = 0 } RetStatus; 135 | 136 | typedef struct _HookEntryInfo { 137 | int hook_id; 138 | union { 139 | void *target_address; 140 | void *function_address; 141 | void *instruction_address; 142 | }; 143 | } HookEntryInfo; 144 | 145 | // DobbyWrap <==> DobbyInstrument, so use DobbyInstrument instead of DobbyWrap 146 | #if 0 147 | // wrap function with pre_call and post_call 148 | typedef void (*PreCallTy)(RegisterContext *ctx, const HookEntryInfo *info); 149 | typedef void (*PostCallTy)(RegisterContext *ctx, const HookEntryInfo *info); 150 | int DobbyWrap(void *function_address, PreCallTy pre_call, PostCallTy post_call); 151 | #endif 152 | 153 | // return dobby build date 154 | const char *DobbyBuildVersion(); 155 | 156 | // replace function 157 | int DobbyHook(void *address, void *replace_call, void **origin_call); 158 | 159 | // dynamic binary instrument for instruction 160 | // [!!! READ ME !!!] 161 | // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack 162 | typedef void (*DBICallTy)(RegisterContext *ctx, const HookEntryInfo *info); 163 | int DobbyInstrument(void *address, DBICallTy dbi_call); 164 | 165 | // destory and restore hook 166 | int DobbyDestroy(void *address); 167 | 168 | // iterate symbol table and find symbol 169 | void *DobbySymbolResolver(const char *image_name, const char *symbol_name); 170 | 171 | // global offset table 172 | int DobbyGlobalOffsetTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func); 173 | 174 | // [!!! READ ME !!!] 175 | // for arm, Arm64, dobby will use b xxx instead of ldr absolute indirect branch 176 | // for x64, dobby always use absolute indirect jump 177 | #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) 178 | void dobby_enable_near_branch_trampoline(); 179 | void dobby_disable_near_branch_trampoline(); 180 | #endif 181 | 182 | // register linker load image callback 183 | typedef void (*linker_load_callback_t)(const char *image_name, void *handle); 184 | void dobby_register_image_load_callback(linker_load_callback_t func); 185 | 186 | #ifdef __cplusplus 187 | } 188 | #endif 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /app/src/main/jni/Includes/Logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Logger.h 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #ifndef Logger_h 8 | #define Logger_h 9 | 10 | #include 11 | #include 12 | 13 | enum LogType { 14 | oDEBUG = 3, 15 | oERROR = 6, 16 | oINFO = 4, 17 | oWARN = 5 18 | }; 19 | 20 | #define TAG OBFUSCATE("Mod_Menu") 21 | 22 | #define LOGD(...) ((void)__android_log_print(oDEBUG, TAG, __VA_ARGS__)) 23 | #define LOGE(...) ((void)__android_log_print(oERROR, TAG, __VA_ARGS__)) 24 | #define LOGI(...) ((void)__android_log_print(oINFO, TAG, __VA_ARGS__)) 25 | #define LOGW(...) ((void)__android_log_print(oWARN, TAG, __VA_ARGS__)) 26 | 27 | #endif /* Logger_h */ 28 | -------------------------------------------------------------------------------- /app/src/main/jni/Includes/Macros.h: -------------------------------------------------------------------------------- 1 | // thanks to shmoo and joeyjurjens for the usefull stuff under this comment. 2 | #ifndef ANDROID_MOD_MENU_MACROS_H 3 | #define ANDROID_MOD_MENU_MACROS_H 4 | 5 | #if defined(__aarch64__) //Compile for arm64 lib only 6 | #include 7 | 8 | #else //Compile for armv7 lib only. Do not worry about greyed out highlighting code, it still works 9 | #include 10 | #include 11 | 12 | #endif 13 | 14 | void hook(void *offset, void* ptr, void **orig) 15 | { 16 | #if defined(__aarch64__) 17 | A64HookFunction(offset, ptr, orig); 18 | #else 19 | MSHookFunction(offset, ptr, orig); 20 | #endif 21 | } 22 | 23 | #define HOOK(offset, ptr, orig) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) 24 | #define HOOK_LIB(lib, offset, ptr, orig) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) 25 | 26 | #define HOOK_NO_ORIG(offset, ptr) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) 27 | #define HOOK_LIB_NO_ORIG(lib, offset, ptr) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) 28 | 29 | #define HOOKSYM(sym, ptr, org) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) 30 | #define HOOKSYM_LIB(lib, sym, ptr, org) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) 31 | 32 | #define HOOKSYM_NO_ORIG(sym, ptr) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, NULL) 33 | #define HOOKSYM_LIB_NO_ORIG(lib, sym, ptr) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, NULL) 34 | 35 | std::vector memoryPatches; 36 | std::vector offsetVector; 37 | 38 | // Patching a offset without switch. 39 | void patchOffset(const char *fileName, uint64_t offset, std::string hexBytes, bool isOn) { 40 | 41 | MemoryPatch patch = MemoryPatch::createWithHex(fileName, offset, hexBytes); 42 | 43 | //Check if offset exists in the offsetVector 44 | if (std::find(offsetVector.begin(), offsetVector.end(), offset) != offsetVector.end()) { 45 | //LOGE(OBFUSCATE("Already exists")); 46 | std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), offset); 47 | patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector 48 | } else { 49 | memoryPatches.push_back(patch); 50 | offsetVector.push_back(offset); 51 | //LOGI(OBFUSCATE("Added")); 52 | } 53 | 54 | if (!patch.isValid()) { 55 | LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), offset); 56 | return; 57 | } 58 | if (isOn) { 59 | if (!patch.Modify()) { 60 | LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), offset); 61 | } 62 | } else { 63 | if (!patch.Restore()) { 64 | LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), offset); 65 | } 66 | } 67 | } 68 | 69 | void patchOffsetSym(uintptr_t absolute_address, std::string hexBytes, bool isOn) { 70 | 71 | MemoryPatch patch = MemoryPatch::createWithHex(absolute_address, hexBytes); 72 | 73 | //Check if offset exists in the offsetVector 74 | if (std::find(offsetVector.begin(), offsetVector.end(), absolute_address) != offsetVector.end()) { 75 | //LOGE(OBFUSCATE("Already exists")); 76 | std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), absolute_address); 77 | patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector 78 | } else { 79 | memoryPatches.push_back(patch); 80 | offsetVector.push_back(absolute_address); 81 | //LOGI(OBFUSCATE("Added")); 82 | } 83 | 84 | if (!patch.isValid()) { 85 | LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), absolute_address); 86 | return; 87 | } 88 | if (isOn) { 89 | if (!patch.Modify()) { 90 | LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), absolute_address); 91 | } 92 | } else { 93 | if (!patch.Restore()) { 94 | LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), absolute_address); 95 | } 96 | } 97 | } 98 | 99 | #define PATCH(offset, hex) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true) 100 | #define PATCH_LIB(lib, offset, hex) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true) 101 | 102 | #define PATCH_SYM(sym, hex) patchOffset(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true) 103 | #define PATCH_LIB_SYM(lib, sym, hex) patchOffset(dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true) 104 | 105 | #define PATCH_SWITCH(offset, hex, boolean) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean) 106 | #define PATCH_LIB_SWITCH(lib, offset, hex, boolean) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean) 107 | 108 | #define PATCH_SYM_SWITCH(sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean) 109 | #define PATCH_LIB_SYM_SWITCH(lib, sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean) 110 | 111 | #define RESTORE(offset) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), "", false) 112 | #define RESTORE_LIB(lib, offset) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), "", false) 113 | 114 | #define RESTORE_SYM(sym) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), "", false) 115 | #define RESTORE_LIB_SYM(lib, sym) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), "", false) 116 | 117 | #endif //ANDROID_MOD_MENU_MACROS_H -------------------------------------------------------------------------------- /app/src/main/jni/Includes/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS 2 | #define UTILS 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "Logger.h" 11 | 12 | typedef unsigned long DWORD; 13 | static uintptr_t libBase; 14 | 15 | bool libLoaded = false; 16 | 17 | DWORD findLibrary(const char *library) { 18 | char filename[0xFF] = {0}, 19 | buffer[1024] = {0}; 20 | FILE *fp = NULL; 21 | DWORD address = 0; 22 | 23 | sprintf(filename, OBFUSCATE("/proc/self/maps")); 24 | 25 | fp = fopen(filename, OBFUSCATE("rt")); 26 | if (fp == NULL) { 27 | perror(OBFUSCATE("fopen")); 28 | goto done; 29 | } 30 | 31 | while (fgets(buffer, sizeof(buffer), fp)) { 32 | if (strstr(buffer, library)) { 33 | address = (DWORD) strtoul(buffer, NULL, 16); 34 | goto done; 35 | } 36 | } 37 | 38 | done: 39 | 40 | if (fp) { 41 | fclose(fp); 42 | } 43 | 44 | return address; 45 | } 46 | 47 | DWORD getAbsoluteAddress(const char *libraryName, DWORD relativeAddr) { 48 | libBase = findLibrary(libraryName); 49 | if (libBase == 0) 50 | return 0; 51 | return (reinterpret_cast(libBase + relativeAddr)); 52 | } 53 | 54 | 55 | jboolean isGameLibLoaded(JNIEnv *env, jobject thiz) { 56 | return libLoaded; 57 | } 58 | 59 | bool isLibraryLoaded(const char *libraryName) { 60 | //libLoaded = true; 61 | char line[512] = {0}; 62 | FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt")); 63 | if (fp != NULL) { 64 | while (fgets(line, sizeof(line), fp)) { 65 | std::string a = line; 66 | if (strstr(line, libraryName)) { 67 | libLoaded = true; 68 | return true; 69 | } 70 | } 71 | fclose(fp); 72 | } 73 | return false; 74 | } 75 | 76 | uintptr_t string2Offset(const char *c) { 77 | int base = 16; 78 | // See if this function catches all possibilities. 79 | // If it doesn't, the function would have to be amended 80 | // whenever you add a combination of architecture and 81 | // compiler that is not yet addressed. 82 | static_assert(sizeof(uintptr_t) == sizeof(unsigned long) 83 | || sizeof(uintptr_t) == sizeof(unsigned long long), 84 | "Please add string to handle conversion for this architecture."); 85 | 86 | // Now choose the correct function ... 87 | if (sizeof(uintptr_t) == sizeof(unsigned long)) { 88 | return strtoul(c, nullptr, base); 89 | } 90 | 91 | // All other options exhausted, sizeof(uintptr_t) == sizeof(unsigned long long)) 92 | return strtoull(c, nullptr, base); 93 | } 94 | 95 | namespace ToastLength { 96 | inline const int LENGTH_LONG = 1; 97 | inline const int LENGTH_SHORT = 0; 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /app/src/main/jni/Includes/obfuscate.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------- ABOUT ------------------------------------- 2 | Original Author: Adam Yaxley 3 | Website: https://github.com/adamyaxley 4 | License: See end of file 5 | Obfuscate 6 | Guaranteed compile-time string literal obfuscation library for C++14 7 | Usage: 8 | Pass string literals into the AY_OBFUSCATE macro to obfuscate them at compile 9 | time. AY_OBFUSCATE returns a reference to an ay::obfuscated_data object with the 10 | following traits: 11 | - Guaranteed obfuscation of string 12 | The passed string is encrypted with a simple XOR cipher at compile-time to 13 | prevent it being viewable in the binary image 14 | - Global lifetime 15 | The actual instantiation of the ay::obfuscated_data takes place inside a 16 | lambda as a function level static 17 | - Implicitly convertable to a char* 18 | This means that you can pass it directly into functions that would normally 19 | take a char* or a const char* 20 | Example: 21 | const char* obfuscated_string = AY_OBFUSCATE("Hello World"); 22 | std::cout << obfuscated_string << std::endl; 23 | ----------------------------------------------------------------------------- */ 24 | #include 25 | #include 26 | 27 | #ifndef AY_OBFUSCATE_DEFAULT_KEY 28 | // The default 64 bit key to obfuscate strings with. 29 | // This can be user specified by defining AY_OBFUSCATE_DEFAULT_KEY before 30 | // including obfuscate.h 31 | #define AY_OBFUSCATE_DEFAULT_KEY ay::generate_key(__LINE__) 32 | #endif 33 | 34 | namespace ay 35 | { 36 | using size_type = unsigned long long; 37 | using key_type = unsigned long long; 38 | 39 | // Generate a psuedo-random key that spans all 8 bytes 40 | constexpr key_type generate_key(key_type seed) 41 | { 42 | // Use the MurmurHash3 64-bit finalizer to hash our seed 43 | key_type key = seed; 44 | key ^= (key >> 33); 45 | key *= 0xff51afd7ed558ccd; 46 | key ^= (key >> 33); 47 | key *= 0xc4ceb9fe1a85ec53; 48 | key ^= (key >> 33); 49 | 50 | // Make sure that a bit in each byte is set 51 | key |= 0x0101010101010101ull; 52 | 53 | return key; 54 | } 55 | 56 | // Obfuscates or deobfuscates data with key 57 | constexpr void cipher(char* data, size_type size, key_type key) 58 | { 59 | // Obfuscate with a simple XOR cipher based on key 60 | for (size_type i = 0; i < size; i++) 61 | { 62 | data[i] ^= char(key >> ((i % 8) * 8)); 63 | } 64 | } 65 | 66 | // Obfuscates a string at compile time 67 | template 68 | class obfuscator 69 | { 70 | public: 71 | // Obfuscates the string 'data' on construction 72 | constexpr obfuscator(const char* data) 73 | { 74 | // Copy data 75 | for (size_type i = 0; i < N; i++) 76 | { 77 | m_data[i] = data[i]; 78 | } 79 | 80 | // On construction each of the characters in the string is 81 | // obfuscated with an XOR cipher based on key 82 | cipher(m_data, N, KEY); 83 | } 84 | 85 | constexpr const char* data() const 86 | { 87 | return &m_data[0]; 88 | } 89 | 90 | constexpr size_type size() const 91 | { 92 | return N; 93 | } 94 | 95 | constexpr key_type key() const 96 | { 97 | return KEY; 98 | } 99 | 100 | private: 101 | 102 | char m_data[N]{}; 103 | }; 104 | 105 | // Handles decryption and re-encryption of an encrypted string at runtime 106 | template 107 | class obfuscated_data 108 | { 109 | public: 110 | obfuscated_data(const obfuscator& obfuscator) 111 | { 112 | // Copy obfuscated data 113 | for (size_type i = 0; i < N; i++) 114 | { 115 | m_data[i] = obfuscator.data()[i]; 116 | } 117 | } 118 | 119 | ~obfuscated_data() 120 | { 121 | // Zero m_data to remove it from memory 122 | for (size_type i = 0; i < N; i++) 123 | { 124 | m_data[i] = 0; 125 | } 126 | } 127 | 128 | // Returns a pointer to the plain text string, decrypting it if 129 | // necessary 130 | operator char*() 131 | { 132 | decrypt(); 133 | return m_data; 134 | } 135 | 136 | operator std::string() 137 | { 138 | decrypt(); 139 | return m_data; 140 | } 141 | 142 | // Manually decrypt the string 143 | void decrypt() 144 | { 145 | if (m_encrypted) 146 | { 147 | cipher(m_data, N, KEY); 148 | m_encrypted = false; 149 | } 150 | } 151 | 152 | // Manually re-encrypt the string 153 | void encrypt() 154 | { 155 | if (!m_encrypted) 156 | { 157 | cipher(m_data, N, KEY); 158 | m_encrypted = true; 159 | } 160 | } 161 | 162 | // Returns true if this string is currently encrypted, false otherwise. 163 | bool is_encrypted() const 164 | { 165 | return m_encrypted; 166 | } 167 | 168 | private: 169 | 170 | // Local storage for the string. Call is_encrypted() to check whether or 171 | // not the string is currently obfuscated. 172 | char m_data[N]; 173 | 174 | // Whether data is currently encrypted 175 | bool m_encrypted{ true }; 176 | }; 177 | 178 | // This function exists purely to extract the number of elements 'N' in the 179 | // array 'data' 180 | template 181 | constexpr auto make_obfuscator(const char(&data)[N]) 182 | { 183 | return obfuscator(data); 184 | } 185 | } 186 | 187 | // Obfuscates the string 'data' at compile-time and returns a reference to a 188 | // ay::obfuscated_data object with global lifetime that has functions for 189 | // decrypting the string and is also implicitly convertable to a char* 190 | #define OBFUSCATE(data) OBFUSCATE_KEY(data, AY_OBFUSCATE_DEFAULT_KEY) 191 | 192 | // Obfuscates the string 'data' with 'key' at compile-time and returns a 193 | // reference to a ay::obfuscated_data object with global lifetime that has 194 | // functions for decrypting the string and is also implicitly convertable to a 195 | // char* 196 | #define OBFUSCATE_KEY(data, key) \ 197 | []() -> ay::obfuscated_data& { \ 198 | static_assert(sizeof(decltype(key)) == sizeof(ay::key_type), "key must be a 64 bit unsigned integer"); \ 199 | static_assert((key) >= (1ull << 56), "key must span all 8 bytes"); \ 200 | constexpr auto n = sizeof(data)/sizeof(data[0]); \ 201 | constexpr auto obfuscator = ay::make_obfuscator(data); \ 202 | static auto obfuscated_data = ay::obfuscated_data(obfuscator); \ 203 | return obfuscated_data; \ 204 | }() 205 | 206 | /* -------------------------------- LICENSE ------------------------------------ 207 | Public Domain (http://www.unlicense.org) 208 | This is free and unencumbered software released into the public domain. 209 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 210 | software, either in source code form or as a compiled binary, for any purpose, 211 | commercial or non-commercial, and by any means. 212 | In jurisdictions that recognize copyright laws, the author or authors of this 213 | software dedicate any and all copyright interest in the software to the public 214 | domain. We make this dedication for the benefit of the public at large and to 215 | the detriment of our heirs and successors. We intend this dedication to be an 216 | overt act of relinquishment in perpetuity of all present and future rights to 217 | this software under copyright law. 218 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 219 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 220 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE 221 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 222 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 223 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 224 | ----------------------------------------------------------------------------- */ -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/KittyMemory.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // KittyMemory.cpp 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #include 8 | #include "KittyMemory.h" 9 | 10 | using KittyMemory::Memory_Status; 11 | using KittyMemory::ProcMap; 12 | 13 | 14 | struct mapsCache { 15 | std::string identifier; 16 | ProcMap map; 17 | }; 18 | 19 | static std::vector __mapsCache; 20 | static ProcMap findMapInCache(std::string id){ 21 | ProcMap ret; 22 | for(int i = 0; i < __mapsCache.size(); i++){ 23 | if(__mapsCache[i].identifier.compare(id) == 0){ 24 | ret = __mapsCache[i].map; 25 | break; 26 | } 27 | } 28 | return ret; 29 | } 30 | 31 | 32 | bool KittyMemory::ProtectAddr(void *addr, size_t length, int protection) { 33 | uintptr_t pageStart = _PAGE_START_OF_(addr); 34 | uintptr_t pageLen = _PAGE_LEN_OF_(addr, length); 35 | return ( 36 | mprotect(reinterpret_cast(pageStart), pageLen, protection) != -1 37 | ); 38 | } 39 | 40 | 41 | Memory_Status KittyMemory::memWrite(void *addr, const void *buffer, size_t len) { 42 | if (addr == NULL) 43 | return INV_ADDR; 44 | 45 | if (buffer == NULL) 46 | return INV_BUF; 47 | 48 | if (len < 1 || len > INT_MAX) 49 | return INV_LEN; 50 | 51 | if (!ProtectAddr(addr, len, _PROT_RWX_)) 52 | return INV_PROT; 53 | 54 | if (memcpy(addr, buffer, len) != NULL && ProtectAddr(addr, len, _PROT_RX_)) 55 | return SUCCESS; 56 | 57 | return FAILED; 58 | } 59 | 60 | 61 | Memory_Status KittyMemory::memRead(void *buffer, const void *addr, size_t len) { 62 | if (addr == NULL) 63 | return INV_ADDR; 64 | 65 | if (buffer == NULL) 66 | return INV_BUF; 67 | 68 | if (len < 1 || len > INT_MAX) 69 | return INV_LEN; 70 | 71 | if (memcpy(buffer, addr, len) != NULL) 72 | return SUCCESS; 73 | 74 | return FAILED; 75 | } 76 | 77 | 78 | std::string KittyMemory::read2HexStr(const void *addr, size_t len) { 79 | char temp[len]; 80 | memset(temp, 0, len); 81 | 82 | const size_t bufferLen = len * 2 + 1; 83 | char buffer[bufferLen]; 84 | memset(buffer, 0, bufferLen); 85 | 86 | std::string ret; 87 | 88 | if (memRead(temp, addr, len) != SUCCESS) 89 | return ret; 90 | 91 | for (int i = 0; i < len; i++) { 92 | sprintf(&buffer[i * 2], "%02X", (unsigned char) temp[i]); 93 | } 94 | 95 | ret += buffer; 96 | return ret; 97 | } 98 | 99 | ProcMap KittyMemory::getLibraryMap(const char *libraryName) { 100 | ProcMap retMap; 101 | char line[512] = {0}; 102 | 103 | FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt")); 104 | if (fp != NULL) { 105 | while (fgets(line, sizeof(line), fp)) { 106 | if (strstr(line, libraryName)) { 107 | char tmpPerms[5] = {0}, tmpDev[12] = {0}, tmpPathname[444] = {0}; 108 | // parse a line in maps file 109 | // (format) startAddress-endAddress perms offset dev inode pathname 110 | sscanf(line, "%llx-%llx %s %ld %s %d %s", 111 | (long long unsigned *) &retMap.startAddr, 112 | (long long unsigned *) &retMap.endAddr, 113 | tmpPerms, &retMap.offset, tmpDev, &retMap.inode, tmpPathname); 114 | 115 | retMap.length = (uintptr_t) retMap.endAddr - (uintptr_t) retMap.startAddr; 116 | retMap.perms = tmpPerms; 117 | retMap.dev = tmpDev; 118 | retMap.pathname = tmpPathname; 119 | 120 | break; 121 | } 122 | } 123 | fclose(fp); 124 | } 125 | return retMap; 126 | } 127 | 128 | uintptr_t KittyMemory::getAbsoluteAddress(const char *libraryName, uintptr_t relativeAddr, bool useCache) { 129 | ProcMap libMap; 130 | 131 | if(useCache){ 132 | libMap = findMapInCache(libraryName); 133 | if(libMap.isValid()) 134 | return (reinterpret_cast(libMap.startAddr) + relativeAddr); 135 | } 136 | 137 | libMap = getLibraryMap(libraryName); 138 | if (!libMap.isValid()) 139 | return 0; 140 | 141 | if(useCache){ 142 | mapsCache cachedMap; 143 | cachedMap.identifier = libraryName; 144 | cachedMap.map = libMap; 145 | __mapsCache.push_back(cachedMap); 146 | } 147 | 148 | return (reinterpret_cast(libMap.startAddr) + relativeAddr); 149 | } 150 | -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/KittyMemory.h: -------------------------------------------------------------------------------- 1 | // 2 | // KittyMemory.hpp 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #define _SYS_PAGE_SIZE_ (sysconf(_SC_PAGE_SIZE)) 17 | 18 | #define _PAGE_START_OF_(x) ((uintptr_t)x & ~(uintptr_t)(_SYS_PAGE_SIZE_ - 1)) 19 | #define _PAGE_END_OF_(x, len) (_PAGE_START_OF_((uintptr_t)x + len - 1)) 20 | #define _PAGE_LEN_OF_(x, len) (_PAGE_END_OF_(x, len) - _PAGE_START_OF_(x) + _SYS_PAGE_SIZE_) 21 | #define _PAGE_OFFSET_OF_(x) ((uintptr_t)x - _PAGE_START_OF_(x)) 22 | 23 | #define _PROT_RWX_ (PROT_READ | PROT_WRITE | PROT_EXEC) 24 | #define _PROT_RX_ (PROT_READ | PROT_EXEC) 25 | 26 | 27 | #define EMPTY_VEC_OFFSET std::vector() 28 | 29 | namespace KittyMemory { 30 | 31 | typedef enum { 32 | FAILED = 0, 33 | SUCCESS = 1, 34 | INV_ADDR = 2, 35 | INV_LEN = 3, 36 | INV_BUF = 4, 37 | INV_PROT = 5 38 | } Memory_Status; 39 | 40 | 41 | struct ProcMap { 42 | void *startAddr; 43 | void *endAddr; 44 | size_t length; 45 | std::string perms; 46 | long offset; 47 | std::string dev; 48 | int inode; 49 | std::string pathname; 50 | 51 | bool isValid() { return (startAddr != NULL && endAddr != NULL && !pathname.empty()); } 52 | }; 53 | 54 | /* 55 | * Changes protection of an address with given length 56 | */ 57 | bool ProtectAddr(void *addr, size_t length, int protection); 58 | 59 | /* 60 | * Writes buffer content to an address 61 | */ 62 | Memory_Status memWrite(void *addr, const void *buffer, size_t len); 63 | 64 | /* 65 | * Reads an address content into a buffer 66 | */ 67 | Memory_Status memRead(void *buffer, const void *addr, size_t len); 68 | 69 | /* 70 | * Reads an address content and returns hex string 71 | */ 72 | std::string read2HexStr(const void *addr, size_t len); 73 | 74 | 75 | /* 76 | * Wrapper to dereference & get value of a multi level pointer 77 | * Make sure to use the correct data type! 78 | */ 79 | template 80 | Type readMultiPtr(void *ptr, std::vector offsets) { 81 | Type defaultVal = {}; 82 | if (ptr == NULL) 83 | return defaultVal; 84 | 85 | uintptr_t finalPtr = reinterpret_cast(ptr); 86 | int offsetsSize = offsets.size(); 87 | if (offsetsSize > 0) { 88 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) { 89 | if (i == (offsetsSize - 1)) 90 | return *reinterpret_cast(finalPtr + offsets[i]); 91 | 92 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]); 93 | } 94 | } 95 | 96 | if (finalPtr == 0) 97 | return defaultVal; 98 | 99 | return *reinterpret_cast(finalPtr); 100 | } 101 | 102 | 103 | /* 104 | * Wrapper to dereference & set value of a multi level pointer 105 | * Make sure to use the correct data type!, const objects won't work 106 | */ 107 | template 108 | bool writeMultiPtr(void *ptr, std::vector offsets, Type val) { 109 | if (ptr == NULL) 110 | return false; 111 | 112 | uintptr_t finalPtr = reinterpret_cast(ptr); 113 | int offsetsSize = offsets.size(); 114 | if (offsetsSize > 0) { 115 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) { 116 | if (i == (offsetsSize - 1)) { 117 | *reinterpret_cast(finalPtr + offsets[i]) = val; 118 | return true; 119 | } 120 | 121 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]); 122 | } 123 | } 124 | 125 | if (finalPtr == 0) 126 | return false; 127 | 128 | *reinterpret_cast(finalPtr) = val; 129 | return true; 130 | } 131 | 132 | /* 133 | * Wrapper to dereference & get value of a pointer 134 | * Make sure to use the correct data type! 135 | */ 136 | template 137 | Type readPtr(void *ptr) { 138 | Type defaultVal = {}; 139 | if (ptr == NULL) 140 | return defaultVal; 141 | 142 | return *reinterpret_cast(ptr); 143 | } 144 | 145 | /* 146 | * Wrapper to dereference & set value of a pointer 147 | * Make sure to use the correct data type!, const objects won't work 148 | */ 149 | template 150 | bool writePtr(void *ptr, Type val) { 151 | if (ptr == NULL) 152 | return false; 153 | 154 | *reinterpret_cast(ptr) = val; 155 | return true; 156 | } 157 | 158 | /* 159 | * Gets info of a mapped library in self process 160 | */ 161 | ProcMap getLibraryMap(const char *libraryName); 162 | 163 | /* 164 | * Expects a relative address in a library 165 | * Returns final absolute address 166 | */ 167 | uintptr_t 168 | getAbsoluteAddress(const char *libraryName, uintptr_t relativeAddr, bool useCache = false); 169 | }; 170 | -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/KittyUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "KittyUtils.h" 2 | 3 | static void xtrim(std::string &hex){ 4 | if(hex.compare(0, 2, "0x") == 0){ 5 | hex.erase(0, 2); 6 | } 7 | 8 | // https://www.techiedelight.com/remove-whitespaces-string-cpp/ 9 | hex.erase(std::remove_if(hex.begin(), hex.end(), [](char c){ 10 | return (c == ' ' || c == '\n' || c == '\r' || 11 | c == '\t' || c == '\v' || c == '\f'); 12 | }), 13 | hex.end()); 14 | } 15 | 16 | 17 | bool KittyUtils::validateHexString(std::string &xstr){ 18 | if(xstr.length() < 2) return false; 19 | xtrim(xstr); // first remove spaces 20 | if(xstr.length() % 2 != 0) return false; 21 | for(size_t i = 0; i < xstr.length(); i++){ 22 | if(!std::isxdigit((unsigned char)xstr[i])){ 23 | return false; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | 30 | // https://tweex.net/post/c-anything-tofrom-a-hex-string/ 31 | #include 32 | #include 33 | 34 | 35 | // ------------------------------------------------------------------ 36 | /*! 37 | Convert a block of data to a hex string 38 | */ 39 | void KittyUtils::toHex( 40 | void *const data, //!< Data to convert 41 | const size_t dataLength, //!< Length of the data to convert 42 | std::string &dest //!< Destination string 43 | ) 44 | { 45 | unsigned char *byteData = reinterpret_cast(data); 46 | std::stringstream hexStringStream; 47 | 48 | hexStringStream << std::hex << std::setfill('0'); 49 | for(size_t index = 0; index < dataLength; ++index) 50 | hexStringStream << std::setw(2) << static_cast(byteData[index]); 51 | dest = hexStringStream.str(); 52 | } 53 | 54 | 55 | // ------------------------------------------------------------------ 56 | /*! 57 | Convert a hex string to a block of data 58 | */ 59 | void KittyUtils::fromHex( 60 | const std::string &in, //!< Input hex string 61 | void *const data //!< Data store 62 | ) 63 | { 64 | size_t length = in.length(); 65 | unsigned char *byteData = reinterpret_cast(data); 66 | 67 | std::stringstream hexStringStream; hexStringStream >> std::hex; 68 | for(size_t strIndex = 0, dataIndex = 0; strIndex < length; ++dataIndex) 69 | { 70 | // Read out and convert the string two characters at a time 71 | const char tmpStr[3] = { in[strIndex++], in[strIndex++], 0 }; 72 | 73 | // Reset and fill the string stream 74 | hexStringStream.clear(); 75 | hexStringStream.str(tmpStr); 76 | 77 | // Do the conversion 78 | int tmpValue = 0; 79 | hexStringStream >> tmpValue; 80 | byteData[dataIndex] = static_cast(tmpValue); 81 | } 82 | } -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/KittyUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace KittyUtils { 7 | 8 | bool validateHexString(std::string &xstr); 9 | void toHex(void *const data, const size_t dataLength, std::string &dest); 10 | void fromHex(const std::string &in, void *const data); 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/MemoryBackup.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.cpp 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #include 8 | #include "MemoryBackup.h" 9 | 10 | 11 | MemoryBackup::MemoryBackup() { 12 | _address = 0; 13 | _size = 0; 14 | _orig_code.clear(); 15 | } 16 | 17 | MemoryBackup::MemoryBackup(const char *libraryName, uintptr_t address, size_t backup_size, bool useMapCache) { 18 | MemoryBackup(); 19 | 20 | if (libraryName == NULL || address == 0 || backup_size < 1) 21 | return; 22 | 23 | _address = KittyMemory::getAbsoluteAddress(libraryName, address, useMapCache); 24 | if(_address == 0) return; 25 | 26 | _size = backup_size; 27 | 28 | _orig_code.resize(backup_size); 29 | 30 | // backup current content 31 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size); 32 | } 33 | 34 | 35 | MemoryBackup::MemoryBackup(uintptr_t absolute_address, size_t backup_size) { 36 | MemoryBackup(); 37 | 38 | if (absolute_address == 0 || backup_size < 1) 39 | return; 40 | 41 | _address = absolute_address; 42 | 43 | _size = backup_size; 44 | 45 | _orig_code.resize(backup_size); 46 | 47 | // backup current content 48 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size); 49 | } 50 | 51 | MemoryBackup::~MemoryBackup() { 52 | // clean up 53 | _orig_code.clear(); 54 | } 55 | 56 | 57 | bool MemoryBackup::isValid() const { 58 | return (_address != 0 && _size > 0 59 | && _orig_code.size() == _size); 60 | } 61 | 62 | size_t MemoryBackup::get_BackupSize() const{ 63 | return _size; 64 | } 65 | 66 | uintptr_t MemoryBackup::get_TargetAddress() const{ 67 | return _address; 68 | } 69 | 70 | bool MemoryBackup::Restore() { 71 | if (!isValid()) return false; 72 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == Memory_Status::SUCCESS; 73 | } 74 | 75 | std::string MemoryBackup::get_CurrBytes() { 76 | if (!isValid()) 77 | _hexString = std::string(OBFUSCATE("0xInvalid")); 78 | else 79 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size); 80 | 81 | return _hexString; 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/MemoryBackup.h: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.h 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "KittyMemory.h" 12 | using KittyMemory::Memory_Status; 13 | using KittyMemory::ProcMap; 14 | 15 | 16 | class MemoryBackup { 17 | private: 18 | uintptr_t _address; 19 | size_t _size; 20 | 21 | std::vector _orig_code; 22 | 23 | std::string _hexString; 24 | 25 | public: 26 | MemoryBackup(); 27 | 28 | /* 29 | * expects library name and relative address 30 | */ 31 | MemoryBackup(const char *libraryName, uintptr_t address, size_t backup_size, bool useMapCache=true); 32 | 33 | /* 34 | * expects absolute address 35 | */ 36 | MemoryBackup(uintptr_t absolute_address, size_t backup_size); 37 | 38 | 39 | ~MemoryBackup(); 40 | 41 | 42 | /* 43 | * Validate patch 44 | */ 45 | bool isValid() const; 46 | 47 | 48 | size_t get_BackupSize() const; 49 | 50 | /* 51 | * Returns pointer to the target address 52 | */ 53 | uintptr_t get_TargetAddress() const; 54 | 55 | 56 | /* 57 | * Restores backup code 58 | */ 59 | bool Restore(); 60 | 61 | 62 | /* 63 | * Returns current target address bytes as hex string 64 | */ 65 | std::string get_CurrBytes(); 66 | }; 67 | -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/MemoryPatch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.cpp 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #include 8 | #include "MemoryPatch.h" 9 | #include "Includes/Logger.h" 10 | 11 | MemoryPatch::MemoryPatch() { 12 | _address = 0; 13 | _size = 0; 14 | _orig_code.clear(); 15 | _patch_code.clear(); 16 | } 17 | 18 | MemoryPatch::MemoryPatch(const char *libraryName, uintptr_t address, 19 | const void *patch_code, size_t patch_size, bool useMapCache) { 20 | MemoryPatch(); 21 | 22 | if (libraryName == NULL || address == 0 || patch_code == NULL || patch_size < 1) 23 | return; 24 | 25 | _address = KittyMemory::getAbsoluteAddress(libraryName, address, useMapCache); 26 | if (_address == 0) return; 27 | 28 | _size = patch_size; 29 | 30 | _orig_code.resize(patch_size); 31 | _patch_code.resize(patch_size); 32 | 33 | // initialize patch & backup current content 34 | KittyMemory::memRead(&_patch_code[0], patch_code, patch_size); 35 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), patch_size); 36 | } 37 | 38 | MemoryPatch::MemoryPatch(uintptr_t absolute_address, 39 | const void *patch_code, size_t patch_size) { 40 | MemoryPatch(); 41 | 42 | if (absolute_address == 0 || patch_code == NULL || patch_size < 1) 43 | return; 44 | 45 | _address = absolute_address; 46 | _size = patch_size; 47 | 48 | _orig_code.resize(patch_size); 49 | _patch_code.resize(patch_size); 50 | 51 | // initialize patch & backup current content 52 | KittyMemory::memRead(&_patch_code[0], patch_code, patch_size); 53 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), patch_size); 54 | } 55 | 56 | MemoryPatch::~MemoryPatch() { 57 | // clean up 58 | _orig_code.clear(); 59 | _patch_code.clear(); 60 | } 61 | 62 | MemoryPatch MemoryPatch::createWithHex(const char *libraryName, uintptr_t address, 63 | std::string hex, bool useMapCache) { 64 | MemoryPatch patch; 65 | 66 | if (libraryName == NULL || address == 0 || !KittyUtils::validateHexString(hex)) 67 | return patch; 68 | 69 | patch._address = KittyMemory::getAbsoluteAddress(libraryName, address, useMapCache); 70 | if (patch._address == 0) return patch; 71 | 72 | patch._size = hex.length() / 2; 73 | 74 | patch._orig_code.resize(patch._size); 75 | patch._patch_code.resize(patch._size); 76 | 77 | // initialize patch 78 | KittyUtils::fromHex(hex, &patch._patch_code[0]); 79 | 80 | // backup current content 81 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), 82 | patch._size); 83 | return patch; 84 | } 85 | 86 | MemoryPatch MemoryPatch::createWithHex(uintptr_t absolute_address, std::string hex) { 87 | MemoryPatch patch; 88 | 89 | if (absolute_address == 0 || !KittyUtils::validateHexString(hex)) 90 | return patch; 91 | 92 | patch._address = absolute_address; 93 | patch._size = hex.length() / 2; 94 | 95 | patch._orig_code.resize(patch._size); 96 | patch._patch_code.resize(patch._size); 97 | 98 | // initialize patch 99 | KittyUtils::fromHex(hex, &patch._patch_code[0]); 100 | 101 | // backup current content 102 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), 103 | patch._size); 104 | return patch; 105 | } 106 | 107 | bool MemoryPatch::isValid() const { 108 | return (_address != 0 && _size > 0 109 | && _orig_code.size() == _size && _patch_code.size() == _size); 110 | } 111 | 112 | size_t MemoryPatch::get_PatchSize() const { 113 | return _size; 114 | } 115 | 116 | uintptr_t MemoryPatch::get_TargetAddress() const { 117 | return _address; 118 | } 119 | 120 | bool MemoryPatch::Restore() { 121 | if (!isValid()) return false; 122 | //LOGI("Restore %i", isLeeched); 123 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == 124 | Memory_Status::SUCCESS; 125 | } 126 | 127 | bool MemoryPatch::Modify() { 128 | if (!isValid()) return false; 129 | //LOGI("Modify"); 130 | return (KittyMemory::memWrite(reinterpret_cast(_address), &_patch_code[0], _size) == 131 | Memory_Status::SUCCESS); 132 | } 133 | 134 | std::string MemoryPatch::get_CurrBytes() { 135 | if (!isValid()) 136 | _hexString = std::string(OBFUSCATE("0xInvalid")); 137 | else 138 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size); 139 | 140 | return _hexString; 141 | } 142 | -------------------------------------------------------------------------------- /app/src/main/jni/KittyMemory/MemoryPatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.h 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | #include "KittyUtils.h" 11 | #include "KittyMemory.h" 12 | using KittyMemory::Memory_Status; 13 | using KittyMemory::ProcMap; 14 | 15 | class MemoryPatch { 16 | private: 17 | uintptr_t _address; 18 | size_t _size; 19 | 20 | std::vector _orig_code; 21 | std::vector _patch_code; 22 | 23 | std::string _hexString; 24 | 25 | public: 26 | MemoryPatch(); 27 | 28 | /* 29 | * expects library name and relative address 30 | */ 31 | MemoryPatch(const char *libraryName, uintptr_t address, 32 | const void *patch_code, size_t patch_size, bool useMapCache=true); 33 | 34 | 35 | /* 36 | * expects absolute address 37 | */ 38 | MemoryPatch(uintptr_t absolute_address, 39 | const void *patch_code, size_t patch_size); 40 | 41 | 42 | ~MemoryPatch(); 43 | 44 | /* 45 | * compatible hex format (0xffff & ffff & ff ff) 46 | */ 47 | static MemoryPatch createWithHex(const char *libraryName, uintptr_t address, std::string hex, bool useMapCache=true); 48 | static MemoryPatch createWithHex(uintptr_t absolute_address, std::string hex); 49 | 50 | /* 51 | * Validate patch 52 | */ 53 | bool isValid() const; 54 | 55 | 56 | size_t get_PatchSize() const; 57 | 58 | /* 59 | * Returns pointer to the target address 60 | */ 61 | uintptr_t get_TargetAddress() const; 62 | 63 | 64 | /* 65 | * Restores patch to original value 66 | */ 67 | bool Restore(); 68 | 69 | 70 | /* 71 | * Applies patch modifications to target address 72 | */ 73 | bool Modify(); 74 | 75 | 76 | /* 77 | * Returns current patch target address bytes as hex string 78 | */ 79 | std::string get_CurrBytes(); 80 | }; 81 | -------------------------------------------------------------------------------- /app/src/main/jni/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "Includes/Logger.h" 13 | #include "Includes/obfuscate.h" 14 | #include "Includes/Utils.h" 15 | #include "KittyMemory/MemoryPatch.h" 16 | #include "Menu/Setup.h" 17 | #include "Includes/Dobby/dobby.h" 18 | #include "ByNameModding/BNM.hpp" 19 | #define targetLibName OBFUSCATE("libil2cpp.so") 20 | #include "Includes/Macros.h" 21 | #define HOOKBNM(Namespace,Class,Method,count,newfun,oldfun) DobbyHook((void *)LoadClass(Namespace, Class).GetMethodByName(OBFUSCATE_BNM(Method), count).GetOffset(), (void *)newfun, (void **)&oldfun); 22 | 23 | 24 | 25 | 26 | 27 | void *hack_thread(void *) { 28 | using namespace BNM; 29 | LOGI(OBFUSCATE("pthread created")); 30 | 31 | do { 32 | sleep(1); 33 | } while (!Il2cppLoaded()); 34 | AttachIl2Cpp(); 35 | LOGI(OBFUSCATE("%s has been loaded"), (const char *) targetLibName); 36 | #if defined(__aarch64__) 37 | #define BNM_USE_APPDOMAIN 38 | 39 | #else 40 | 41 | LOGI(OBFUSCATE("Done")); 42 | #endif 43 | DetachIl2Cpp(); 44 | return nullptr; 45 | } 46 | jobjectArray GetFeatureList(JNIEnv *env, jobject context) { 47 | jobjectArray ret; 48 | 49 | const char *features[] = { 50 | OBFUSCATE("Category_The Category"), 51 | OBFUSCATE("1_Toggle_test") 52 | }; 53 | int Total_Feature = (sizeof features / sizeof features[0]); 54 | ret = (jobjectArray) 55 | env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")), 56 | env->NewStringUTF("")); 57 | 58 | for (int i = 0; i < Total_Feature; i++) 59 | env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i])); 60 | 61 | return (ret); 62 | } 63 | 64 | void Changes(JNIEnv *env, jclass clazz, jobject obj, 65 | jint featNum, jstring featName, jint value, 66 | jboolean boolean, jstring str) { 67 | 68 | LOGD(OBFUSCATE("Feature name: %d - %s | Value: = %d | Bool: = %d | Text: = %s"), featNum, 69 | env->GetStringUTFChars(featName, 0), value, 70 | boolean, str != NULL ? env->GetStringUTFChars(str, 0) : ""); 71 | 72 | 73 | switch (featNum) { 74 | case 1: 75 | break; 76 | } 77 | } 78 | 79 | __attribute__((constructor)) 80 | void lib_main() { 81 | pthread_t ptid; 82 | pthread_create(&ptid, nullptr, hack_thread, nullptr); 83 | } 84 | 85 | int RegisterMenu(JNIEnv *env) { 86 | JNINativeMethod methods[] = { 87 | {OBFUSCATE("Icon"), OBFUSCATE("()Ljava/lang/String;"), reinterpret_cast(Icon)}, 88 | {OBFUSCATE("IconWebViewData"), OBFUSCATE("()Ljava/lang/String;"), reinterpret_cast(IconWebViewData)}, 89 | {OBFUSCATE("IsGameLibLoaded"), OBFUSCATE("()Z"), reinterpret_cast(isGameLibLoaded)}, 90 | {OBFUSCATE("Init"), OBFUSCATE("(Landroid/content/Context;Landroid/widget/TextView;Landroid/widget/TextView;)V"), reinterpret_cast(Init)}, 91 | {OBFUSCATE("SettingsList"), OBFUSCATE("()[Ljava/lang/String;"), reinterpret_cast(SettingsList)}, 92 | {OBFUSCATE("GetFeatureList"), OBFUSCATE("()[Ljava/lang/String;"), reinterpret_cast(GetFeatureList)}, 93 | }; 94 | 95 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Menu")); 96 | if (!clazz) 97 | return JNI_ERR; 98 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0) 99 | return JNI_ERR; 100 | return JNI_OK; 101 | } 102 | 103 | int RegisterPreferences(JNIEnv *env) { 104 | JNINativeMethod methods[] = { 105 | {OBFUSCATE("Changes"), OBFUSCATE("(Landroid/content/Context;ILjava/lang/String;IZLjava/lang/String;)V"), reinterpret_cast(Changes)}, 106 | }; 107 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Preferences")); 108 | if (!clazz) 109 | return JNI_ERR; 110 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0) 111 | return JNI_ERR; 112 | return JNI_OK; 113 | } 114 | 115 | int RegisterMain(JNIEnv *env) { 116 | JNINativeMethod methods[] = { 117 | {OBFUSCATE("CheckOverlayPermission"), OBFUSCATE("(Landroid/content/Context;)V"), reinterpret_cast(CheckOverlayPermission)}, 118 | }; 119 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Main")); 120 | if (!clazz) 121 | return JNI_ERR; 122 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0) 123 | return JNI_ERR; 124 | 125 | return JNI_OK; 126 | } 127 | 128 | extern "C" 129 | JNIEXPORT jint JNICALL 130 | JNI_OnLoad(JavaVM *vm, void *reserved) { 131 | JNIEnv *env; 132 | vm->GetEnv((void **) &env, JNI_VERSION_1_6); 133 | if (RegisterMenu(env) != 0) 134 | return JNI_ERR; 135 | if (RegisterPreferences(env) != 0) 136 | return JNI_ERR; 137 | if (RegisterMain(env) != 0) 138 | return JNI_ERR; 139 | return JNI_VERSION_1_6; 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/jni/Menu/Menu.h: -------------------------------------------------------------------------------- 1 | bool iconValid, settingsValid, initValid; 2 | 3 | //Big letter cause crash 4 | void setText(JNIEnv *env, jobject obj, const char* text){ 5 | //https://stackoverflow.com/a/33627640/3763113 6 | //A little JNI calls here. You really really need a great knowledge if you want to play with JNI stuff 7 | //Html.fromHtml(""); 8 | jclass html = (*env).FindClass(OBFUSCATE("android/text/Html")); 9 | jmethodID fromHtml = (*env).GetStaticMethodID(html, OBFUSCATE("fromHtml"), OBFUSCATE("(Ljava/lang/String;)Landroid/text/Spanned;")); 10 | 11 | //setText(""); 12 | jclass textView = (*env).FindClass(OBFUSCATE("android/widget/TextView")); 13 | jmethodID setText = (*env).GetMethodID(textView, OBFUSCATE("setText"), OBFUSCATE("(Ljava/lang/CharSequence;)V")); 14 | 15 | //Java string 16 | jstring jstr = (*env).NewStringUTF(text); 17 | (*env).CallVoidMethod(obj, setText, (*env).CallStaticObjectMethod(html, fromHtml, jstr)); 18 | } 19 | 20 | jstring Icon(JNIEnv *env, jobject thiz) { 21 | iconValid = true; 22 | 23 | //Use https://www.base64encode.org/ to encode your image to base64 24 | return env->NewStringUTF( 25 | OBFUSCATE("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")); 26 | } 27 | 28 | jstring IconWebViewData(JNIEnv *env, jobject thiz) { 29 | iconValid = true; 30 | //WebView support GIF animation. Upload your image or GIF on imgur.com or other sites 31 | 32 | // From internet (Requires android.permission.INTERNET) 33 | // return env->NewStringUTF(OBFUSCATE("https://i.imgur.com/SujJ85j.gif")); 34 | 35 | // Base64 html: 36 | // return env->NewStringUTF("data:image/png;base64, "); 37 | 38 | // To disable it, return NULL. It will use normal image above: 39 | // return NULL 40 | 41 | //return env->NewStringUTF(OBFUSCATE_KEY("https://i.imgur.com/SujJ85j.gif", 'u')); 42 | return NULL; 43 | } 44 | 45 | jobjectArray SettingsList(JNIEnv *env, jobject activityObject) { 46 | jobjectArray ret; 47 | 48 | const char *features[] = { 49 | OBFUSCATE("Category_Settings"), 50 | OBFUSCATE("-1_Toggle_Save feature preferences"), //-1 is checked on Preferences.java 51 | OBFUSCATE("-3_Toggle_Auto size vertically"), 52 | OBFUSCATE("Category_Menu"), 53 | OBFUSCATE("-6_Button_Close settings"), 54 | }; 55 | 56 | int Total_Feature = (sizeof features / 57 | sizeof features[0]); //Now you dont have to manually update the number everytime; 58 | ret = (jobjectArray) 59 | env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")), 60 | env->NewStringUTF("")); 61 | int i; 62 | for (i = 0; i < Total_Feature; i++) 63 | env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i])); 64 | 65 | settingsValid = true; 66 | 67 | return (ret); 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/jni/Menu/Setup.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Menu/Menu.h" 3 | #include "Menu/get_device_api_level_inlines.h" 4 | 5 | //Jni stuff from MrDarkRX https://github.com/MrDarkRXx/DarkMod-Floating 6 | void setDialog(jobject ctx, JNIEnv *env, const char *title, const char *msg){ 7 | jclass Alert = env->FindClass(OBFUSCATE("android/app/AlertDialog$Builder")); 8 | jmethodID AlertCons = env->GetMethodID(Alert, OBFUSCATE(""), OBFUSCATE("(Landroid/content/Context;)V")); 9 | 10 | jobject MainAlert = env->NewObject(Alert, AlertCons, ctx); 11 | 12 | jmethodID setTitle = env->GetMethodID(Alert, OBFUSCATE("setTitle"), OBFUSCATE("(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;")); 13 | env->CallObjectMethod(MainAlert, setTitle, env->NewStringUTF(title)); 14 | 15 | jmethodID setMsg = env->GetMethodID(Alert, OBFUSCATE("setMessage"), OBFUSCATE("(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;")); 16 | env->CallObjectMethod(MainAlert, setMsg, env->NewStringUTF(msg)); 17 | 18 | jmethodID setCa = env->GetMethodID(Alert, OBFUSCATE("setCancelable"), OBFUSCATE("(Z)Landroid/app/AlertDialog$Builder;")); 19 | env->CallObjectMethod(MainAlert, setCa, false); 20 | 21 | jmethodID setPB = env->GetMethodID(Alert, OBFUSCATE("setPositiveButton"), OBFUSCATE("(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;")); 22 | env->CallObjectMethod(MainAlert, setPB, env->NewStringUTF("Ok"), static_cast(NULL)); 23 | 24 | jmethodID create = env->GetMethodID(Alert, OBFUSCATE("create"), OBFUSCATE("()Landroid/app/AlertDialog;")); 25 | jobject creaetob = env->CallObjectMethod(MainAlert, create); 26 | 27 | jclass AlertN = env->FindClass(OBFUSCATE("android/app/AlertDialog")); 28 | 29 | jmethodID show = env->GetMethodID(AlertN, OBFUSCATE("show"), OBFUSCATE("()V")); 30 | env->CallVoidMethod(creaetob, show); 31 | } 32 | 33 | void Toast(JNIEnv *env, jobject thiz, const char *text, int length) { 34 | jstring jstr = env->NewStringUTF(text); 35 | jclass toast = env->FindClass(OBFUSCATE("android/widget/Toast")); 36 | jmethodID methodMakeText =env->GetStaticMethodID(toast,OBFUSCATE("makeText"),OBFUSCATE("(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;")); 37 | jobject toastobj = env->CallStaticObjectMethod(toast, methodMakeText,thiz, jstr, length); 38 | jmethodID methodShow = env->GetMethodID(toast, OBFUSCATE("show"), OBFUSCATE("()V")); 39 | env->CallVoidMethod(toastobj, methodShow); 40 | } 41 | 42 | void startActivityPermisson(JNIEnv *env, jobject ctx){ 43 | jclass native_context = env->GetObjectClass(ctx); 44 | jmethodID startActivity = env->GetMethodID(native_context, OBFUSCATE("startActivity"),OBFUSCATE("(Landroid/content/Intent;)V")); 45 | 46 | jmethodID pack = env->GetMethodID(native_context, OBFUSCATE("getPackageName"),OBFUSCATE("()Ljava/lang/String;")); 47 | jstring packageName = static_cast(env->CallObjectMethod(ctx, pack)); 48 | 49 | const char *pkg = env->GetStringUTFChars(packageName, 0); 50 | 51 | std::stringstream pkgg; 52 | pkgg << OBFUSCATE("package:"); 53 | pkgg << pkg; 54 | std::string pakg = pkgg.str(); 55 | 56 | jclass Uri = env->FindClass(OBFUSCATE("android/net/Uri")); 57 | jmethodID Parce = env->GetStaticMethodID(Uri, OBFUSCATE("parse"), OBFUSCATE("(Ljava/lang/String;)Landroid/net/Uri;")); 58 | jobject UriMethod = env->CallStaticObjectMethod(Uri, Parce, env->NewStringUTF(pakg.c_str())); 59 | 60 | jclass intentclass = env->FindClass(OBFUSCATE("android/content/Intent")); 61 | jmethodID newIntent = env->GetMethodID(intentclass, OBFUSCATE(""), OBFUSCATE("(Ljava/lang/String;Landroid/net/Uri;)V")); 62 | jobject intent = env->NewObject(intentclass,newIntent,env->NewStringUTF(OBFUSCATE("android.settings.action.MANAGE_OVERLAY_PERMISSION")), UriMethod); 63 | 64 | env->CallVoidMethod(ctx, startActivity, intent); 65 | } 66 | 67 | void startService(JNIEnv *env, jobject ctx){ 68 | jclass native_context = env->GetObjectClass(ctx); 69 | jclass intentClass = env->FindClass(OBFUSCATE("android/content/Intent")); 70 | jclass actionString = env->FindClass(OBFUSCATE("com/android/support/Launcher")); 71 | jmethodID newIntent = env->GetMethodID(intentClass, OBFUSCATE(""), OBFUSCATE("(Landroid/content/Context;Ljava/lang/Class;)V")); 72 | jobject intent = env->NewObject(intentClass,newIntent,ctx,actionString); 73 | jmethodID startActivityMethodId = env->GetMethodID(native_context, OBFUSCATE("startService"), OBFUSCATE("(Landroid/content/Intent;)Landroid/content/ComponentName;")); 74 | env->CallObjectMethod(ctx, startActivityMethodId, intent); 75 | } 76 | 77 | void *exit_thread(void *) { 78 | sleep(5); 79 | exit(0); 80 | } 81 | 82 | //Needed jclass parameter because this is a static java method 83 | void CheckOverlayPermission(JNIEnv *env, jclass thiz, jobject ctx){ 84 | //If overlay permission option is greyed out, make sure to add android.permission.SYSTEM_ALERT_WINDOW in manifest 85 | 86 | LOGI(OBFUSCATE("Check overlay permission")); 87 | 88 | int sdkVer = api_level(); 89 | if (sdkVer >= 23){ //Android 6.0 90 | jclass Settings = env->FindClass(OBFUSCATE("android/provider/Settings")); 91 | jmethodID canDraw =env->GetStaticMethodID(Settings, OBFUSCATE("canDrawOverlays"), OBFUSCATE("(Landroid/content/Context;)Z")); 92 | if (!env->CallStaticBooleanMethod(Settings, canDraw, ctx)){ 93 | Toast(env,ctx,OBFUSCATE("Overlay permission is required in order to show mod menu."),1); 94 | Toast(env,ctx,OBFUSCATE("Overlay permission is required in order to show mod menu."),1); 95 | startActivityPermisson(env, ctx); 96 | 97 | pthread_t ptid; 98 | pthread_create(&ptid, NULL, exit_thread, NULL); 99 | return; 100 | } 101 | } 102 | 103 | 104 | LOGI(OBFUSCATE("Start service")); 105 | 106 | //StartMod Normal 107 | startService(env, ctx); 108 | } 109 | 110 | void Init(JNIEnv *env, jobject thiz, jobject ctx, jobject title, jobject subtitle){ 111 | //Set sub title 112 | setText(env, title, OBFUSCATE("Modded by (yourname)")); 113 | 114 | //Set sub title 115 | setText(env, subtitle, OBFUSCATE("

" 116 | "

Modded by LGL

| " 117 | "https://github.com/LGLTeam | Lorem Ipsum is simply dummy text of the printing and typesetting

" 118 | "
")); 119 | 120 | //Dialog Example 121 | //setDialog(ctx,env,OBFUSCATE("Title"),OBFUSCATE("Message Example")); 122 | 123 | //Toast Example 124 | Toast(env,ctx,OBFUSCATE("Modded by YOU"),ToastLength::LENGTH_LONG); 125 | 126 | initValid = true; 127 | } -------------------------------------------------------------------------------- /app/src/main/jni/Menu/get_device_api_level_inlines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | #include 33 | 34 | __BEGIN_DECLS 35 | 36 | // Avoid circular dependencies since this is exposed from . 37 | int __system_property_get(const char* __name, char* __value); 38 | int atoi(const char* __s) __attribute_pure__; 39 | 40 | int api_level() { 41 | char value[92] = { 0 }; 42 | if (__system_property_get("ro.build.version.sdk", value) < 1) return -1; 43 | int api_level = atoi(value); 44 | return (api_level > 0) ? api_level : -1; 45 | } 46 | 47 | __END_DECLS 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/Buffer.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_BUFFER_HPP 23 | #define SUBSTRATE_BUFFER_HPP 24 | 25 | #include 26 | 27 | template 28 | _disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { 29 | *reinterpret_cast(buffer) = value; 30 | buffer += sizeof(Type_); 31 | } 32 | 33 | _disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { 34 | memcpy(buffer, data, size); 35 | buffer += size; 36 | } 37 | 38 | #endif//SUBSTRATE_BUFFER_HPP 39 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/CydiaSubstrate.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_H_ 23 | #define SUBSTRATE_H_ 24 | 25 | #ifdef __APPLE__ 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | #include 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #include 35 | #include 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | #define _finline \ 42 | inline __attribute__((__always_inline__)) 43 | #define _disused \ 44 | __attribute__((__unused__)) 45 | 46 | #define _extern \ 47 | extern "C" __attribute__((__visibility__("default"))) 48 | 49 | #ifdef __cplusplus 50 | #define _default(value) = value 51 | #else 52 | #define _default(value) 53 | #endif 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif 58 | 59 | bool MSHookProcess(pid_t pid, const char *library); 60 | 61 | typedef const void *MSImageRef; 62 | 63 | MSImageRef MSGetImageByName(const char *file); 64 | void *MSFindSymbol(MSImageRef image, const char *name); 65 | 66 | void MSHookFunction(void *symbol, void *replace, void **result); 67 | 68 | #ifdef __APPLE__ 69 | #ifdef __arm__ 70 | __attribute__((__deprecated__)) 71 | IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); 72 | #endif 73 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); 74 | #endif 75 | 76 | #ifdef SubstrateInternal 77 | typedef void *SubstrateAllocatorRef; 78 | typedef struct __SubstrateProcess *SubstrateProcessRef; 79 | typedef struct __SubstrateMemory *SubstrateMemoryRef; 80 | 81 | SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); 82 | void SubstrateProcessRelease(SubstrateProcessRef process); 83 | 84 | SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); 85 | void SubstrateMemoryRelease(SubstrateMemoryRef memory); 86 | #endif 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | 94 | #ifdef SubstrateInternal 95 | struct SubstrateHookMemory { 96 | SubstrateMemoryRef handle_; 97 | 98 | SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : 99 | handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) 100 | { 101 | } 102 | 103 | ~SubstrateHookMemory() { 104 | if (handle_ != NULL) 105 | SubstrateMemoryRelease(handle_); 106 | } 107 | }; 108 | #endif 109 | 110 | 111 | template 112 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { 113 | MSHookFunction( 114 | reinterpret_cast(symbol), 115 | reinterpret_cast(replace), 116 | reinterpret_cast(result) 117 | ); 118 | } 119 | 120 | template 121 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { 122 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); 123 | } 124 | 125 | template 126 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { 127 | value = reinterpret_cast(MSFindSymbol(image, name)); 128 | } 129 | 130 | template 131 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { 132 | Type_ *symbol; 133 | MSHookSymbol(symbol, name); 134 | return MSHookFunction(symbol, replace, result); 135 | } 136 | 137 | #endif 138 | 139 | #define MSHook(type, name, args...) \ 140 | _disused static type (*_ ## name)(args); \ 141 | static type $ ## name(args) 142 | 143 | #ifdef __cplusplus 144 | #define MSHake(name) \ 145 | &$ ## name, &_ ## name 146 | #else 147 | #define MSHake(name) \ 148 | &$ ## name, (void **) &_ ## name 149 | #endif 150 | 151 | 152 | #endif//SUBSTRATE_H_ 153 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateARM.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_ARM_HPP 23 | #define SUBSTRATE_ARM_HPP 24 | 25 | enum A$r { 26 | A$r0, A$r1, A$r2, A$r3, 27 | A$r4, A$r5, A$r6, A$r7, 28 | A$r8, A$r9, A$r10, A$r11, 29 | A$r12, A$r13, A$r14, A$r15, 30 | A$sp = A$r13, 31 | A$lr = A$r14, 32 | A$pc = A$r15 33 | }; 34 | 35 | enum A$c { 36 | A$eq, A$ne, A$cs, A$cc, 37 | A$mi, A$pl, A$vs, A$vc, 38 | A$hi, A$ls, A$ge, A$lt, 39 | A$gt, A$le, A$al, 40 | A$hs = A$cs, 41 | A$lo = A$cc 42 | }; 43 | 44 | #define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ 45 | (0xe10f0000 | ((rd) << 12)) 46 | #define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ 47 | (0xe128f000 | (rm)) 48 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ 49 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs((int)(im))) 50 | #define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ 51 | (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 52 | #define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ 53 | (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) 54 | #define A$blx_rm(rm) /* blx rm */ \ 55 | (0xe12fff30 | (rm)) 56 | #define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 57 | (0xe1a00000 | ((rd) << 12) | (rm)) 58 | #define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ 59 | (0xe8b00000 | (A$sp << 16) | (rs)) 60 | #define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ 61 | (0xe9200000 | (A$sp << 16) | (rs)) 62 | #define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ 63 | #define A$bx_r0 0xe12fff10 /* bx r0 */ 64 | 65 | #endif//SUBSTRATE_ARM_HPP 66 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateDebug.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "SubstrateHook.h" 23 | #include "SubstrateDebug.hpp" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | _extern bool MSDebug; 31 | bool MSDebug = false; 32 | 33 | static char _MSHexChar(uint8_t value) { 34 | return value < 0x20 || value >= 0x80 ? '.' : value; 35 | } 36 | 37 | #define HexWidth_ 16 38 | #define HexDepth_ 4 39 | 40 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { 41 | const uint8_t *data((const uint8_t *) vdata); 42 | 43 | size_t i(0), j; 44 | 45 | char d[256]; 46 | size_t b(0); 47 | d[0] = '\0'; 48 | 49 | while (i != size) { 50 | if (i % HexWidth_ == 0) { 51 | if (mark != NULL) 52 | b += sprintf(d + b, OBFUSCATE("\n[%s] "), mark); 53 | b += sprintf(d + b, OBFUSCATE("0x%.3zx:"), i); 54 | } 55 | 56 | b += sprintf(d + b, " "); 57 | 58 | for (size_t q(0); q != stride; ++q) 59 | b += sprintf(d + b, OBFUSCATE("%.2x"), data[i + stride - q - 1]); 60 | 61 | i += stride; 62 | 63 | for (size_t q(1); q != stride; ++q) 64 | b += sprintf(d + b, " "); 65 | 66 | if (i % HexDepth_ == 0) 67 | b += sprintf(d + b, " "); 68 | 69 | if (i % HexWidth_ == 0) { 70 | b += sprintf(d + b, " "); 71 | for (j = i - HexWidth_; j != i; ++j) 72 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 73 | 74 | lprintf("%s", d); 75 | b = 0; 76 | d[0] = '\0'; 77 | } 78 | } 79 | 80 | if (i % HexWidth_ != 0) { 81 | for (j = i % HexWidth_; j != HexWidth_; ++j) 82 | b += sprintf(d + b, " "); 83 | for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) 84 | b += sprintf(d + b, " "); 85 | b += sprintf(d + b, " "); 86 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j) 87 | b += sprintf(d + b, OBFUSCATE("%c"), _MSHexChar(data[j])); 88 | 89 | // lprintf("%s", d); 90 | b = 0; 91 | d[0] = '\0'; 92 | } 93 | } 94 | 95 | void MSLogHex(const void *vdata, size_t size, const char *mark) { 96 | return MSLogHexEx(vdata, size, 1, mark); 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateDebug.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_DEBUG_HPP 23 | #define SUBSTRATE_DEBUG_HPP 24 | 25 | #include "SubstrateLog.hpp" 26 | #define lprintf(format, ...) \ 27 | MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) 28 | 29 | extern "C" bool MSDebug; 30 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); 31 | void MSLogHex(const void *vdata, size_t size, const char *mark = 0); 32 | 33 | #endif//SUBSTRATE_DEBUG_HPP 34 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateHook.h: -------------------------------------------------------------------------------- 1 | #ifndef __SUBSTRATEHOOK_H__ 2 | #define __SUBSTRATEHOOK_H__ 3 | 4 | 5 | #include 6 | 7 | #define _extern extern "C" __attribute__((__visibility__("hidden"))) 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | void MSHookFunction(void *symbol, void *replace, void **result); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateLog.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_LOG_HPP 23 | #define SUBSTRATE_LOG_HPP 24 | 25 | #if 0 26 | #include 27 | 28 | #define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__)) 29 | 30 | #define MSLogLevelNotice ANDROID_LOG_INFO 31 | #define MSLogLevelWarning ANDROID_LOG_WARN 32 | #define MSLogLevelError ANDROID_LOG_ERROR 33 | 34 | #else 35 | 36 | #define MSLog(level, format, ...) printf(format, __VA_ARGS__) 37 | 38 | #endif 39 | 40 | #endif//SUBSTRATE_LOG_HPP 41 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstratePosixMemory.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #define SubstrateInternal 23 | #include "CydiaSubstrate.h" 24 | #include "SubstrateLog.hpp" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | extern "C" void __clear_cache (void *beg, void *end); 34 | 35 | struct __SubstrateMemory { 36 | void *address_; 37 | size_t width_; 38 | 39 | __SubstrateMemory(void *address, size_t width) : 40 | address_(address), 41 | width_(width) 42 | { 43 | } 44 | }; 45 | 46 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { 47 | if (allocator != NULL) { 48 | MSLog(MSLogLevelError, OBFUSCATE("MS:Error:allocator != %d"), 0); 49 | return NULL; 50 | } 51 | 52 | if (size == 0) 53 | return NULL; 54 | 55 | int page(getpagesize()); 56 | 57 | uintptr_t base(reinterpret_cast(data) / page * page); 58 | size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); 59 | void *address(reinterpret_cast(base)); 60 | 61 | if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { 62 | MSLog(MSLogLevelError, OBFUSCATE("MS:Error:mprotect() = %d"), errno); 63 | return NULL; 64 | } 65 | 66 | return new __SubstrateMemory(address, width); 67 | } 68 | 69 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { 70 | if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) 71 | MSLog(MSLogLevelError, OBFUSCATE("MS:Error:mprotect() = %d"), errno); 72 | 73 | __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); 74 | 75 | delete memory; 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SubstrateX86.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_X86_HPP 23 | #define SUBSTRATE_X86_HPP 24 | 25 | #include "Buffer.hpp" 26 | 27 | #ifdef __LP64__ 28 | static const bool ia32 = false; 29 | #else 30 | static const bool ia32 = true; 31 | #endif 32 | 33 | enum I$r { 34 | I$rax, I$rcx, I$rdx, I$rbx, 35 | I$rsp, I$rbp, I$rsi, I$rdi, 36 | I$r8, I$r9, I$r10, I$r11, 37 | I$r12, I$r13, I$r14, I$r15, 38 | }; 39 | 40 | _disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { 41 | intptr_t offset(target - source); 42 | return int32_t(offset) == offset; 43 | } 44 | 45 | _disused static size_t MSSizeOfSkip() { 46 | return 5; 47 | } 48 | 49 | _disused static size_t MSSizeOfPushPointer(uintptr_t target) { 50 | return uint64_t(target) >> 32 == 0 ? 5 : 13; 51 | } 52 | 53 | _disused static size_t MSSizeOfPushPointer(void *target) { 54 | return MSSizeOfPushPointer(reinterpret_cast(target)); 55 | } 56 | 57 | _disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { 58 | if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) 59 | return MSSizeOfSkip(); 60 | else 61 | return MSSizeOfPushPointer(target) + 1; 62 | } 63 | 64 | _disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { 65 | return MSSizeOfJump(false, target, source); 66 | } 67 | 68 | _disused static size_t MSSizeOfJump(uintptr_t target) { 69 | return MSSizeOfJump(true, target); 70 | } 71 | 72 | _disused static size_t MSSizeOfJump(void *target, void *source) { 73 | return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); 74 | } 75 | 76 | _disused static size_t MSSizeOfJump(void *target) { 77 | return MSSizeOfJump(reinterpret_cast(target)); 78 | } 79 | 80 | _disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { 81 | MSWrite(current, 0xe9); 82 | MSWrite(current, size); 83 | } 84 | 85 | _disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { 86 | MSWrite(current, 0x68); 87 | MSWrite(current, target); 88 | 89 | if (uint32_t high = uint64_t(target) >> 32) { 90 | MSWrite(current, 0xc7); 91 | MSWrite(current, 0x44); 92 | MSWrite(current, 0x24); 93 | MSWrite(current, 0x04); 94 | MSWrite(current, high); 95 | } 96 | } 97 | 98 | _disused static void MSPushPointer(uint8_t *¤t, void *target) { 99 | return MSPushPointer(current, reinterpret_cast(target)); 100 | } 101 | 102 | _disused static void MSWriteCall(uint8_t *¤t, I$r target) { 103 | if (target >> 3 != 0) 104 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 105 | MSWrite(current, 0xff); 106 | MSWrite(current, 0xd0 | target & 0x07); 107 | } 108 | 109 | _disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { 110 | uintptr_t source(reinterpret_cast(current)); 111 | 112 | if (ia32 || MSIs32BitOffset(target, source + 5)) { 113 | MSWrite(current, 0xe8); 114 | MSWrite(current, target - (source + 5)); 115 | } else { 116 | MSPushPointer(current, target); 117 | 118 | MSWrite(current, 0x83); 119 | MSWrite(current, 0xc4); 120 | MSWrite(current, 0x08); 121 | 122 | MSWrite(current, 0x67); 123 | MSWrite(current, 0xff); 124 | MSWrite(current, 0x54); 125 | MSWrite(current, 0x24); 126 | MSWrite(current, 0xf8); 127 | } 128 | } 129 | 130 | template 131 | _disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { 132 | return MSWriteCall(current, reinterpret_cast(target)); 133 | } 134 | 135 | _disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { 136 | uintptr_t source(reinterpret_cast(current)); 137 | 138 | if (ia32 || MSIs32BitOffset(target, source + 5)) 139 | MSWriteSkip(current, target - (source + 5)); 140 | else { 141 | MSPushPointer(current, target); 142 | MSWrite(current, 0xc3); 143 | } 144 | } 145 | 146 | _disused static void MSWriteJump(uint8_t *¤t, void *target) { 147 | return MSWriteJump(current, reinterpret_cast(target)); 148 | } 149 | 150 | _disused static void MSWriteJump(uint8_t *¤t, I$r target) { 151 | if (target >> 3 != 0) 152 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 153 | MSWrite(current, 0xff); 154 | MSWrite(current, 0xe0 | target & 0x07); 155 | } 156 | 157 | _disused static void MSWritePop(uint8_t *¤t, uint8_t target) { 158 | if (target >> 3 != 0) 159 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 160 | MSWrite(current, 0x58 | target & 0x07); 161 | } 162 | 163 | _disused static size_t MSSizeOfPop(uint8_t target) { 164 | return target >> 3 != 0 ? 2 : 1; 165 | } 166 | 167 | _disused static void MSWritePush(uint8_t *¤t, I$r target) { 168 | if (target >> 3 != 0) 169 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 170 | MSWrite(current, 0x50 | target & 0x07); 171 | } 172 | 173 | _disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { 174 | MSWrite(current, 0x83); 175 | MSWrite(current, 0xc4 | target & 0x07); 176 | MSWrite(current, source); 177 | } 178 | 179 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { 180 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); 181 | MSWrite(current, 0xb8 | target & 0x7); 182 | MSWrite(current, source); 183 | } 184 | 185 | template 186 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { 187 | return MSWriteSet64(current, target, reinterpret_cast(source)); 188 | } 189 | 190 | _disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { 191 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); 192 | MSWrite(current, 0x8b); 193 | MSWrite(current, (target & 0x07) << 3 | source & 0x07); 194 | } 195 | 196 | _disused static size_t MSSizeOfMove64() { 197 | return 3; 198 | } 199 | 200 | #endif//SUBSTRATE_X86_HPP 201 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/SymbolFinder.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_FINDER 2 | #define SYMBOL_FINDER 3 | 4 | #include 5 | 6 | extern int find_name(pid_t pid, const char *name,const char *libn, unsigned long *addr); 7 | extern int find_libbase(pid_t pid, const char *libn, unsigned long *addr); 8 | #endif -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "hde64.h" 12 | #include "table64.h" 13 | 14 | unsigned int hde64_disasm(const void *code, hde64s *hs) 15 | { 16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 17 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 18 | uint8_t op64 = 0; 19 | 20 | memset(hs,0,sizeof(hde64s)); 21 | char *tmp=(char*)hs; 22 | 23 | for (x = 16; x; x--) 24 | switch (c = *p++) { 25 | case 0xf3: 26 | hs->p_rep = c; 27 | pref |= PRE_F3; 28 | break; 29 | case 0xf2: 30 | hs->p_rep = c; 31 | pref |= PRE_F2; 32 | break; 33 | case 0xf0: 34 | hs->p_lock = c; 35 | pref |= PRE_LOCK; 36 | break; 37 | case 0x26: case 0x2e: case 0x36: 38 | case 0x3e: case 0x64: case 0x65: 39 | hs->p_seg = c; 40 | pref |= PRE_SEG; 41 | break; 42 | case 0x66: 43 | hs->p_66 = c; 44 | pref |= PRE_66; 45 | break; 46 | case 0x67: 47 | hs->p_67 = c; 48 | pref |= PRE_67; 49 | break; 50 | default: 51 | goto pref_done; 52 | } 53 | pref_done: 54 | 55 | hs->flags = (uint32_t)pref << 23; 56 | 57 | if (!pref) 58 | pref |= PRE_NONE; 59 | 60 | if ((c & 0xf0) == 0x40) { 61 | hs->flags |= F_PREFIX_REX; 62 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 63 | op64++; 64 | hs->rex_r = (c & 7) >> 2; 65 | hs->rex_x = (c & 3) >> 1; 66 | hs->rex_b = c & 1; 67 | if (((c = *p++) & 0xf0) == 0x40) { 68 | opcode = c; 69 | goto error_opcode; 70 | } 71 | } 72 | 73 | if ((hs->opcode = c) == 0x0f) { 74 | hs->opcode2 = c = *p++; 75 | ht += DELTA_OPCODES; 76 | } else if (c >= 0xa0 && c <= 0xa3) { 77 | op64++; 78 | if (pref & PRE_67) 79 | pref |= PRE_66; 80 | else 81 | pref &= ~PRE_66; 82 | } 83 | 84 | opcode = c; 85 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 86 | 87 | if (cflags == C_ERROR) { 88 | error_opcode: 89 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 90 | cflags = 0; 91 | if ((opcode & -3) == 0x24) 92 | cflags++; 93 | } 94 | 95 | x = 0; 96 | if (cflags & C_GROUP) { 97 | uint16_t t; 98 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 99 | cflags = (uint8_t)t; 100 | x = (uint8_t)(t >> 8); 101 | } 102 | 103 | if (hs->opcode2) { 104 | ht = hde64_table + DELTA_PREFIXES; 105 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 106 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 107 | } 108 | 109 | if (cflags & C_MODRM) { 110 | hs->flags |= F_MODRM; 111 | hs->modrm = c = *p++; 112 | hs->modrm_mod = m_mod = c >> 6; 113 | hs->modrm_rm = m_rm = c & 7; 114 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 115 | 116 | if (x && ((x << m_reg) & 0x80)) 117 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 118 | 119 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 120 | uint8_t t = opcode - 0xd9; 121 | if (m_mod == 3) { 122 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 123 | t = ht[m_reg] << m_rm; 124 | } else { 125 | ht = hde64_table + DELTA_FPU_REG; 126 | t = ht[t] << m_reg; 127 | } 128 | if (t & 0x80) 129 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 130 | } 131 | 132 | if (pref & PRE_LOCK) { 133 | if (m_mod == 3) { 134 | hs->flags |= F_ERROR | F_ERROR_LOCK; 135 | } else { 136 | uint8_t *table_end, op = opcode; 137 | if (hs->opcode2) { 138 | ht = hde64_table + DELTA_OP2_LOCK_OK; 139 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 140 | } else { 141 | ht = hde64_table + DELTA_OP_LOCK_OK; 142 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 143 | op &= -2; 144 | } 145 | for (; ht != table_end; ht++) 146 | if (*ht++ == op) { 147 | if (!((*ht << m_reg) & 0x80)) 148 | goto no_lock_error; 149 | else 150 | break; 151 | } 152 | hs->flags |= F_ERROR | F_ERROR_LOCK; 153 | no_lock_error: 154 | ; 155 | } 156 | } 157 | 158 | if (hs->opcode2) { 159 | switch (opcode) { 160 | case 0x20: case 0x22: 161 | m_mod = 3; 162 | if (m_reg > 4 || m_reg == 1) 163 | goto error_operand; 164 | else 165 | goto no_error_operand; 166 | case 0x21: case 0x23: 167 | m_mod = 3; 168 | if (m_reg == 4 || m_reg == 5) 169 | goto error_operand; 170 | else 171 | goto no_error_operand; 172 | } 173 | } else { 174 | switch (opcode) { 175 | case 0x8c: 176 | if (m_reg > 5) 177 | goto error_operand; 178 | else 179 | goto no_error_operand; 180 | case 0x8e: 181 | if (m_reg == 1 || m_reg > 5) 182 | goto error_operand; 183 | else 184 | goto no_error_operand; 185 | } 186 | } 187 | 188 | if (m_mod == 3) { 189 | uint8_t *table_end; 190 | if (hs->opcode2) { 191 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 192 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 193 | } else { 194 | ht = hde64_table + DELTA_OP_ONLY_MEM; 195 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 196 | } 197 | for (; ht != table_end; ht += 2) 198 | if (*ht++ == opcode) { 199 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 200 | goto error_operand; 201 | else 202 | break; 203 | } 204 | goto no_error_operand; 205 | } else if (hs->opcode2) { 206 | switch (opcode) { 207 | case 0x50: case 0xd7: case 0xf7: 208 | if (pref & (PRE_NONE | PRE_66)) 209 | goto error_operand; 210 | break; 211 | case 0xd6: 212 | if (pref & (PRE_F2 | PRE_F3)) 213 | goto error_operand; 214 | break; 215 | case 0xc5: 216 | goto error_operand; 217 | } 218 | goto no_error_operand; 219 | } else 220 | goto no_error_operand; 221 | 222 | error_operand: 223 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 224 | no_error_operand: 225 | 226 | c = *p++; 227 | if (m_reg <= 1) { 228 | if (opcode == 0xf6) 229 | cflags |= C_IMM8; 230 | else if (opcode == 0xf7) 231 | cflags |= C_IMM_P66; 232 | } 233 | 234 | switch (m_mod) { 235 | case 0: 236 | if (pref & PRE_67) { 237 | if (m_rm == 6) 238 | disp_size = 2; 239 | } else 240 | if (m_rm == 5) 241 | disp_size = 4; 242 | break; 243 | case 1: 244 | disp_size = 1; 245 | break; 246 | case 2: 247 | disp_size = 2; 248 | if (!(pref & PRE_67)) 249 | disp_size <<= 1; 250 | } 251 | 252 | if (m_mod != 3 && m_rm == 4) { 253 | hs->flags |= F_SIB; 254 | p++; 255 | hs->sib = c; 256 | hs->sib_scale = c >> 6; 257 | hs->sib_index = (c & 0x3f) >> 3; 258 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 259 | disp_size = 4; 260 | } 261 | 262 | p--; 263 | switch (disp_size) { 264 | case 1: 265 | hs->flags |= F_DISP8; 266 | hs->disp.disp8 = *p; 267 | break; 268 | case 2: 269 | hs->flags |= F_DISP16; 270 | hs->disp.disp16 = *(uint16_t *)p; 271 | break; 272 | case 4: 273 | hs->flags |= F_DISP32; 274 | hs->disp.disp32 = *(uint32_t *)p; 275 | } 276 | p += disp_size; 277 | } else if (pref & PRE_LOCK) 278 | hs->flags |= F_ERROR | F_ERROR_LOCK; 279 | 280 | if (cflags & C_IMM_P66) { 281 | if (cflags & C_REL32) { 282 | if (pref & PRE_66) { 283 | hs->flags |= F_IMM16 | F_RELATIVE; 284 | hs->imm.imm16 = *(uint16_t *)p; 285 | p += 2; 286 | goto disasm_done; 287 | } 288 | goto rel32_ok; 289 | } 290 | if (op64) { 291 | hs->flags |= F_IMM64; 292 | hs->imm.imm64 = *(uint64_t *)p; 293 | p += 8; 294 | } else if (!(pref & PRE_66)) { 295 | hs->flags |= F_IMM32; 296 | hs->imm.imm32 = *(uint32_t *)p; 297 | p += 4; 298 | } else 299 | goto imm16_ok; 300 | } 301 | 302 | 303 | if (cflags & C_IMM16) { 304 | imm16_ok: 305 | hs->flags |= F_IMM16; 306 | hs->imm.imm16 = *(uint16_t *)p; 307 | p += 2; 308 | } 309 | if (cflags & C_IMM8) { 310 | hs->flags |= F_IMM8; 311 | hs->imm.imm8 = *p++; 312 | } 313 | 314 | if (cflags & C_REL32) { 315 | rel32_ok: 316 | hs->flags |= F_IMM32 | F_RELATIVE; 317 | hs->imm.imm32 = *(uint32_t *)p; 318 | p += 4; 319 | } else if (cflags & C_REL8) { 320 | hs->flags |= F_IMM8 | F_RELATIVE; 321 | hs->imm.imm8 = *p++; 322 | } 323 | 324 | disasm_done: 325 | 326 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 327 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 328 | hs->len = 15; 329 | } 330 | 331 | return (unsigned int)hs->len; 332 | } 333 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /app/src/main/jni/Substrate/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /app/src/main/jni/libs/arm64-v8a/libdobby.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/jni/libs/arm64-v8a/libdobby.a -------------------------------------------------------------------------------- /app/src/main/jni/libs/armeabi-v7a/libdobby.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/jni/libs/armeabi-v7a/libdobby.a -------------------------------------------------------------------------------- /app/src/main/jni/libs/x86/libdobby.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/jni/libs/x86/libdobby.a -------------------------------------------------------------------------------- /app/src/main/jni/libs/x86_64/libdobby.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/jni/libs/x86_64/libdobby.a -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oobbb/Android-Mod-Menu-BNM/bad8fd2bdbf6af8fb4fb72758c5f3b613cb8e532/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #202020 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #0277BD 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LGL Mod Menu 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.1.0' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Oct 24 18:32:28 CEST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------