├── .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("
"
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 |
--------------------------------------------------------------------------------