├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── styles.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
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ └── inject.xml
│ │ └── drawable
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── jniLibs
│ │ ├── x86
│ │ │ └── libinject.so
│ │ ├── x86_64
│ │ │ └── libinject.so
│ │ ├── arm64-v8a
│ │ │ └── libinject.so
│ │ └── armeabi-v7a
│ │ │ └── libinject.so
│ │ ├── ic_launcher-playstore.png
│ │ ├── jni
│ │ ├── Client
│ │ │ ├── libs
│ │ │ │ ├── x86
│ │ │ │ │ └── libinject.so
│ │ │ │ ├── x86_64
│ │ │ │ │ └── libinject.so
│ │ │ │ ├── arm64-v8a
│ │ │ │ │ └── libinject.so
│ │ │ │ └── armeabi-v7a
│ │ │ │ │ └── libinject.so
│ │ │ ├── Sources
│ │ │ │ └── Socket
│ │ │ │ │ ├── Socket.h
│ │ │ │ │ ├── request.h
│ │ │ │ │ └── Socket.cpp
│ │ │ ├── includes
│ │ │ │ ├── get_device_api_level_inlines.h
│ │ │ │ ├── Setup.h
│ │ │ │ └── Menu.h
│ │ │ └── Client.cpp
│ │ ├── Server
│ │ │ ├── Sources
│ │ │ │ ├── Substrate
│ │ │ │ │ ├── SymbolFinder.h
│ │ │ │ │ ├── SubstrateHook.h
│ │ │ │ │ ├── SubstrateDebug.hpp
│ │ │ │ │ ├── Buffer.hpp
│ │ │ │ │ ├── SubstrateLog.hpp
│ │ │ │ │ ├── SubstrateARM.hpp
│ │ │ │ │ ├── SubstratePosixMemory.cpp
│ │ │ │ │ ├── hde64.h
│ │ │ │ │ ├── SubstrateDebug.cpp
│ │ │ │ │ ├── table64.h
│ │ │ │ │ ├── CydiaSubstrate.h
│ │ │ │ │ ├── SubstrateX86.hpp
│ │ │ │ │ ├── hde64.c
│ │ │ │ │ └── SymbolFinder.cpp
│ │ │ │ ├── KittyMemory
│ │ │ │ │ ├── KittyUtils.h
│ │ │ │ │ ├── MemoryBackup.h
│ │ │ │ │ ├── MemoryPatch.h
│ │ │ │ │ ├── MemoryBackup.cpp
│ │ │ │ │ ├── KittyUtils.cpp
│ │ │ │ │ ├── KittyMemory.cpp
│ │ │ │ │ ├── MemoryPatch.cpp
│ │ │ │ │ └── KittyMemory.h
│ │ │ │ ├── And64InlineHook
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── LICENSE
│ │ │ │ │ └── And64InlineHook.hpp
│ │ │ │ └── Socket
│ │ │ │ │ ├── response.h
│ │ │ │ │ ├── Socket.h
│ │ │ │ │ └── Socket.cpp
│ │ │ └── Server.cpp
│ │ ├── Application.mk
│ │ ├── Includes
│ │ │ ├── config.h
│ │ │ ├── log.h
│ │ │ ├── Logger.h
│ │ │ ├── Utils.h
│ │ │ ├── Macros.h
│ │ │ └── obfuscate.h
│ │ └── Android.mk
│ │ ├── java
│ │ └── com
│ │ │ └── android
│ │ │ └── support
│ │ │ ├── AppMain.java
│ │ │ ├── Main.java
│ │ │ ├── Launcher.java
│ │ │ ├── MainActivity.java
│ │ │ ├── ApkExtract.java
│ │ │ ├── GameInfo.java
│ │ │ ├── CrashHandler.java
│ │ │ └── Preferences.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ └── gradle-wrapper.properties
├── gradle.properties
├── README.md
├── .gitignore
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LGL Mod Menu
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/jniLibs/x86/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jniLibs/x86/libinject.so
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/jniLibs/x86_64/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jniLibs/x86_64/libinject.so
--------------------------------------------------------------------------------
/app/src/main/jni/Client/libs/x86/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jni/Client/libs/x86/libinject.so
--------------------------------------------------------------------------------
/app/src/main/jniLibs/arm64-v8a/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jniLibs/arm64-v8a/libinject.so
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jniLibs/armeabi-v7a/libinject.so
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/jni/Client/libs/x86_64/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jni/Client/libs/x86_64/libinject.so
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/jni/Client/libs/arm64-v8a/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jni/Client/libs/arm64-v8a/libinject.so
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/jni/Client/libs/armeabi-v7a/libinject.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/app/src/main/jni/Client/libs/armeabi-v7a/libinject.so
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XiaBei-cy/BetterInject/HEAD/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/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/jni/Application.mk:
--------------------------------------------------------------------------------
1 | # To AIDE Users: If you are using 32-bit/ARMv7 phone, please remove arm64-v8a
2 | APP_ABI := APP_ABI := armeabi-v7a
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/Server/Sources/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/Server/Sources/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/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/And64InlineHook/README.md:
--------------------------------------------------------------------------------
1 | # Server.Sources.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/Includes/config.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Perfare on 2020/7/4.
3 | //
4 |
5 | #ifndef AUTO_IL2CPPDUMPER_CONFIG_H
6 | #define AUTO_IL2CPPDUMPER_CONFIG_H
7 |
8 | // Try increase sleep time if having issues with the game. Decrease sleep time if anti-cheat detection it earlier
9 | #define Sleep 2
10 |
11 | // Uncomment for fake lib mode
12 | // It is to load our fake libmain.so or libunity.so and load game's real librealmain.so or librealunity.so
13 | #define UseFakeLib
14 |
15 | #endif //AUTO_IL2CPPDUMPER_CONFIG_H
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/support/AppMain.java:
--------------------------------------------------------------------------------
1 | package com.android.support;
2 | import android.app.Application;
3 | import java.io.IOException;
4 | import com.topjohnwu.superuser.Shell;
5 | public class AppMain extends Application {
6 |
7 | @Override
8 | public void onCreate() {
9 | super.onCreate();
10 | try {
11 | Runtime.getRuntime().exec("su");
12 | Shell.su("setenforce 0").exec();
13 | } catch (IOException e) {
14 | e.printStackTrace();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/jni/Includes/log.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Perfare on 2020/7/4.
3 | //
4 |
5 | #ifndef RIRU_IL2CPPDUMPER_LOG_H
6 | #define RIRU_IL2CPPDUMPER_LOG_H
7 |
8 | #include
9 |
10 | #define LOG_TAG "Il2CppDumper"
11 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
12 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
13 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
14 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
15 |
16 | #endif //RIRU_IL2CPPDUMPER_LOG_H
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/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 ("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/res/layout/inject.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## For more details on how to configure your build environment visit
2 | # http://www.gradle.org/docs/current/userguide/build_environment.html
3 | #
4 | # Specifies the JVM arguments used for the daemon process.
5 | # The setting is particularly useful for tweaking memory settings.
6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
8 | #
9 | # When configured, Gradle will run in incubating parallel mode.
10 | # This option should only be used with decoupled projects. For more details, visit
11 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
12 | # org.gradle.parallel=true
13 | #Wed Jun 19 09:27:32 NPT 2024
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 | org.gradle.jvmargs=-Xmx1536m
17 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Socket/response.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #ifndef ANDROID_MOD_MENU_3_2_RESPONSE_H
6 | #define ANDROID_MOD_MENU_3_2_RESPONSE_H
7 |
8 | Socket server;
9 |
10 | enum Mode {
11 | InitMode = -1,
12 | HackMode = -2,
13 | StopMode = -3,
14 | };
15 |
16 | struct Request {
17 | int Mode;
18 | int value;
19 | bool boolean;
20 | };
21 |
22 | struct Response {
23 | bool Success;
24 | };
25 |
26 | int InitServer() {
27 | if (!server.Create()) {
28 | //LOGE("SE:1");
29 | return -1;
30 | }
31 |
32 | if (!server.Bind()) {
33 | //LOGE("SE:2");
34 | return -1;
35 | }
36 |
37 | if (!server.Listen()) {
38 | //LOGE("SE:3");
39 | return -1;
40 | }
41 | return 0;
42 | }
43 | #endif //ANDROID_MOD_MENU_3_2_RESPONSE_H
44 |
--------------------------------------------------------------------------------
/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/jni/Client/Sources/Socket/Socket.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #ifndef ANDROID_MOD_MENU_3_2_SOCKET_H
6 | #define ANDROID_MOD_MENU_3_2_SOCKET_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #define SOCKET_NAME "nepmods"
24 |
25 | class Socket {
26 | public:
27 | int sockfd;
28 | sockaddr_un addr_server;
29 | char socket_name[108]; // 108 sun_path length max
30 | bool created,connected;
31 |
32 | Socket();
33 |
34 | bool Create();
35 | bool Connect();
36 | void Close();
37 |
38 | int sendData(void *inData, size_t size);
39 | bool send(void* inData, size_t size);
40 |
41 | int recvData(void *outData, size_t size);
42 | size_t receive(void* outData);
43 | };
44 |
45 |
46 | #endif //ANDROID_MOD_MENU_3_2_SOCKET_H
47 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/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 | static {
15 | System.loadLibrary("MyLibName");
16 | }
17 | private static native void CheckOverlayPermission(Context context);
18 |
19 | public static void StartWithoutPermission(Context context) {
20 | CrashHandler.init(context, true);
21 | if (context instanceof Activity) {
22 | //Check if context is an Activity.
23 | Menu menu = new Menu(context);
24 | menu.SetWindowManagerActivity();
25 | menu.ShowMenu();
26 | } else {
27 | //Anything else, ask for permission
28 | CheckOverlayPermission(context);
29 | }
30 | }
31 |
32 | public static void Start(Context context) {
33 | CrashHandler.init(context, false);
34 |
35 | CheckOverlayPermission(context);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Socket/Socket.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #ifndef ANDROID_MOD_MENU_3_2_SOCKET_H
6 | #define ANDROID_MOD_MENU_3_2_SOCKET_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #define SOCKET_NAME "nepmods"
24 | #define BACKLOG 8
25 | #define PacketSize 4096
26 |
27 | class Socket {
28 | public:
29 | int listenfd, acceptfd;
30 | bool isCreated;
31 | sockaddr_un addr_server;
32 | char socket_name[108]; // 108 sun_path length max
33 |
34 | Socket();
35 |
36 | bool Create();
37 | bool Accept();
38 | bool Bind();
39 | bool Listen();
40 | void Close();
41 |
42 | int sendData(void *inData, size_t size);
43 | bool send(void* inData, size_t size);
44 |
45 | int recvData(void *outData, size_t size);
46 | size_t receive(void* outData);
47 |
48 |
49 | };
50 |
51 |
52 | #endif //ANDROID_MOD_MENU_3_2_SOCKET_H
53 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/Client/Sources/Socket/request.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #ifndef ANDROID_MOD_MENU_3_2_REQUEST_H
6 | #define ANDROID_MOD_MENU_3_2_REQUEST_H
7 |
8 | Socket client;
9 |
10 | enum Mode {
11 | InitMode = -1,
12 | HackMode = -2,
13 | StopMode = -3,
14 | };
15 |
16 | struct Request {
17 | int Mode;
18 | int value;
19 | bool boolean;
20 | };
21 |
22 | struct Response {
23 | bool Success;
24 | };
25 |
26 | bool isSConnected(){
27 | return client.connected;
28 | }
29 |
30 | bool Send(int mode = Mode::HackMode, int value = 0, bool boolean = false){
31 | Request request{mode, value, boolean};
32 | int code = client.send((void*) &request, sizeof(request));
33 | if(code > 0) {
34 | Response response{};
35 | size_t length = client.receive((void*) &response);
36 | if(length > 0){
37 | return response.Success;
38 | }
39 | }
40 | return false;
41 | }
42 |
43 | int startClient(){
44 | client = Socket();
45 | if(!client.Create()){
46 | return -1;
47 | }
48 | if(!client.Connect()){
49 | return -1;
50 | }
51 | if(!Send(Mode::InitMode)){
52 | return -1;
53 | }
54 | return 0;
55 | }
56 | void stopClient() {
57 | if(client.created && isSConnected()){
58 | Send(Mode::StopMode);
59 | client.Close();
60 | }
61 | }
62 | #endif //ANDROID_MOD_MENU_3_2_REQUEST_H
63 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Substrate/SubstrateDebug.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/Server/Sources/Substrate/Buffer.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/Server/Sources/Substrate/SubstrateLog.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/Server/Sources/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/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Better Inject
3 |
4 | Android Shared Library Mod Injector (Ptrace).
5 |
6 | ### Support:
7 | - Android 5 ~ 14
8 | - ABI arm, arm64, x86, x86_64
9 | - Emulator Support (libhoudini.so or libndk_translation.so)
10 | - Bypass android linker namespace restrictions
11 | - memfd dlopen support
12 | - Auto launch
13 |
14 | ### How To use
15 |
16 | Edit the ```package_name``` in ```Client/Client.cpp``` as per your need
17 |
18 | Add ``Features List`` in ```Client/Client.cpp```
19 | and Add ```mods``` in ```Server/Server.cpp```. Also you can follow all wiki lie ```LGL Mod Menu``` but, you have to put ```cases``` in ```Server/Server.cpp```
20 |
21 |
22 | For JavaVM support, you can add following code to ```Server/Server.cpp```
23 |
24 | ```cpp
25 | extern "C" jint JNIEXPORT JNI_OnLoad(JavaVM* vm, void *key)
26 | {
27 | // key 1337 is passed by injector
28 | if (key != (void*)1337)
29 | return JNI_VERSION_1_6;
30 |
31 | KITTY_LOGI("JNI_OnLoad called by injector.");
32 |
33 | JNIEnv *env = nullptr;
34 | if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK)
35 | {
36 | KITTY_LOGI("JavaEnv: %p.", env);
37 | // ...
38 | }
39 |
40 | std::thread(thread_function).detach();
41 |
42 | return JNI_VERSION_1_6;
43 | }
44 | ```
45 |
46 | YOU MUST HAVE ANDROID STUDIO TO BUILD THE PROJECT, LATER I WILL FIX THE BUILD FOR AIDE.
47 |
48 | # Credits
49 | - ```Android Mod Menu```: https://github.com/LGLTeam/Android-Mod-Menu
50 | - ```AndKittyInjector```: https://github.com/MJx0/AndKittyInjector
51 | - ```KittyMemory```: https://github.com/MJx0/KittyMemory
52 | - ```SubstraceHook```: https://github.com/Octowolve/Substrate-Hooking-Example
53 | - ```And64inlineHook```: https://github.com/Rprop/And64InlineHook
54 |
55 |
56 | ## Authors
57 |
58 | - [@nepmods](https://www.github.com/nepmods)
59 |
60 |
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/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 29
9 | versionCode 1
10 | versionName "3.2"
11 | ndk {
12 | //noinspection ChromeOsAbiSupport
13 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
14 | }
15 | signingConfig signingConfigs.debug
16 | }
17 | buildTypes {
18 | release {
19 | shrinkResources false
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | debug {
24 | shrinkResources false
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 | externalNativeBuild {
30 | ndkBuild {
31 | path file('src/main/jni/Android.mk')
32 | }
33 | }
34 | compileOptions {
35 | // The library uses Java 8 features
36 | sourceCompatibility JavaVersion.VERSION_1_8
37 | targetCompatibility JavaVersion.VERSION_1_8
38 | }
39 | }
40 |
41 | //dependencies must be placed below 'android' brackets to get it work on AIDE
42 | dependencies {
43 | implementation fileTree(dir: 'libs', include: ['*.jar'])
44 |
45 | implementation 'org.zeroturnaround:zt-zip:1.14'
46 | def libsuVersion = '3.2.1'
47 |
48 | // The core module that provides APIs to a shell
49 | implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
50 |
51 | // Optional: APIs for creating root services. Depends on ":core"
52 | implementation "com.github.topjohnwu.libsu:service:${libsuVersion}"
53 | }
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/Client/includes/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/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 |
4 | include $(CLEAR_VARS)
5 | LOCAL_MODULE := GlobalInject
6 | LOCAL_SRC_FILES := Client/libs/$(TARGET_ARCH_ABI)/libinject.so
7 | include $(PREBUILT_SHARED_LIBRARY)
8 |
9 | include $(CLEAR_VARS)
10 | LOCAL_MODULE := MyLibName
11 | LOCAL_CFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -fpermissive -fexceptions
12 | LOCAL_CPPFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -Werror -std=c++17
13 | LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fpermissive -Wall -fexceptions
14 | LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all,-llog
15 | LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
16 | LOCAL_ARM_MODE := arm
17 | LOCAL_C_INCLUDES += $(LOCAL_PATH)
18 |
19 | # Here you add the cpp file to compile
20 | LOCAL_SRC_FILES := Client/Client.cpp \
21 | Client/Sources/Socket/Socket.cpp \
22 |
23 | include $(BUILD_SHARED_LIBRARY)
24 |
25 |
26 | include $(CLEAR_VARS)
27 | LOCAL_MODULE := Server
28 | LOCAL_CFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -fpermissive -fexceptions
29 | LOCAL_CPPFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -Werror -std=c++17
30 | LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fpermissive -Wall -fexceptions
31 | LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all,-llog
32 | LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
33 | LOCAL_ARM_MODE := arm
34 |
35 | LOCAL_C_INCLUDES += $(LOCAL_PATH)
36 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/Server/Sources
37 |
38 | LOCAL_SRC_FILES := Server/Server.cpp \
39 | Server/Sources/Substrate/hde64.c \
40 | Server/Sources/Substrate/SubstrateDebug.cpp \
41 | Server/Sources/Substrate/SubstrateHook.cpp \
42 | Server/Sources/Substrate/SubstratePosixMemory.cpp \
43 | Server/Sources/Substrate/SymbolFinder.cpp \
44 | Server/Sources/KittyMemory/KittyMemory.cpp \
45 | Server/Sources/KittyMemory/MemoryPatch.cpp \
46 | Server/Sources/KittyMemory/MemoryBackup.cpp \
47 | Server/Sources/KittyMemory/KittyUtils.cpp \
48 | Server/Sources/And64InlineHook/And64InlineHook.cpp \
49 | Server/Sources/Socket/Socket.cpp \
50 |
51 |
52 | include $(BUILD_SHARED_LIBRARY)
53 |
54 |
55 |
--------------------------------------------------------------------------------
/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 | public 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 |
47 | }
48 |
49 | //Destroy our View
50 | public void onDestroy() {
51 | }
52 |
53 | //Same as above so it wont crash in the background and therefore use alot of Battery life
54 | public void onTaskRemoved(Intent intent) {
55 | super.onTaskRemoved(intent);
56 | try {
57 | Thread.sleep(100);
58 | } catch (InterruptedException e) {
59 | e.printStackTrace();
60 | }
61 | stopSelf();
62 | }
63 |
64 | //Override our Start Command so the Service doesnt try to recreate itself when the App is closed
65 | public int onStartCommand(Intent intent, int i, int i2) {
66 | return Service.START_NOT_STICKY;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Server.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "Includes/Logger.h"
16 | #include "Socket/Socket.h"
17 | #include "Socket/response.h"
18 | #include "Includes/obfuscate.h"
19 | #include "Includes/Utils.h"
20 | #include "KittyMemory/MemoryPatch.h"
21 |
22 | #define targetLibName "libil2cpp.so"
23 | #include "Includes/Macros.h"
24 |
25 | void *dl = nullptr;
26 |
27 |
28 | bool stopZ = false;
29 | void (*_stopZombie)(void *player);
30 | void StopZombie(void *player) {
31 | if(player != nullptr) {
32 | if(stopZ) {
33 | return;
34 | }
35 | }
36 | _stopZombie(player);
37 | }
38 |
39 | void *hack_thread(void *) {
40 | do {
41 | sleep(1);
42 | } while (!isLibraryLoaded(targetLibName));
43 |
44 | LOGI("%s LOADED", targetLibName);
45 | HOOK("0x85C3C8", StopZombie, _stopZombie);
46 | return nullptr;
47 | }
48 |
49 | void Changes(int featNum, int value, bool boolean) {
50 | switch (featNum) {
51 | case 2:
52 | LOGD("TOGGLE %d", boolean);
53 | stopZ = boolean;
54 | break;
55 | }
56 | }
57 |
58 | void *CreateServer(void *) {
59 | if (InitServer() == 0) {
60 | if (server.Accept()) {
61 | Request request{};
62 | while (server.receive((void*)&request) > 0) {
63 | Response response{};
64 |
65 | if (request.Mode == Mode::InitMode) {
66 | response.Success = true;
67 | }
68 |
69 | if (request.Mode == Mode::StopMode) {
70 | response.Success = true;
71 | server.send((void *) &response, sizeof(response));
72 | server.Close();
73 | }
74 |
75 |
76 | response.Success = true;
77 | Changes(request.Mode, request.value, request.boolean);
78 | server.send((void*)& response, sizeof(response));
79 | }
80 | }
81 | }
82 | return nullptr;
83 | }
84 |
85 |
86 | __attribute__((constructor))
87 | void lib_main() {
88 | pthread_t t_server;
89 | pthread_t t_hack;
90 | pthread_create(&t_server, nullptr, CreateServer, nullptr);
91 | pthread_create(&t_hack, nullptr, hack_thread, nullptr);
92 | }
93 |
--------------------------------------------------------------------------------
/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 | DWORD findLibrary(const char *library) {
16 | char filename[0xFF] = {0},
17 | buffer[1024] = {0};
18 | FILE *fp = NULL;
19 | DWORD address = 0;
20 |
21 | sprintf(filename, OBFUSCATE("/proc/self/maps"));
22 |
23 | fp = fopen(filename, OBFUSCATE("rt"));
24 | if (fp == NULL) {
25 | perror(OBFUSCATE("fopen"));
26 | goto done;
27 | }
28 |
29 | while (fgets(buffer, sizeof(buffer), fp)) {
30 | if (strstr(buffer, library)) {
31 | address = (DWORD) strtoul(buffer, NULL, 16);
32 | goto done;
33 | }
34 | }
35 |
36 | done:
37 |
38 | if (fp) {
39 | fclose(fp);
40 | }
41 |
42 | return address;
43 | }
44 |
45 | DWORD getAbsoluteAddress(const char *libraryName, DWORD relativeAddr) {
46 | libBase = findLibrary(libraryName);
47 | if (libBase == 0)
48 | return 0;
49 | return (reinterpret_cast(libBase + relativeAddr));
50 | }
51 |
52 |
53 | bool isLibraryLoaded(const char *libraryName) {
54 | //libLoaded = true;
55 | char line[512] = {0};
56 | FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt"));
57 | if (fp != NULL) {
58 | while (fgets(line, sizeof(line), fp)) {
59 | std::string a = line;
60 | if (strstr(line, libraryName)) {
61 | return true;
62 | }
63 | }
64 | fclose(fp);
65 | }
66 | return false;
67 | }
68 |
69 | uintptr_t string2Offset(const char *c) {
70 | int base = 16;
71 | // See if this function catches all possibilities.
72 | // If it doesn't, the function would have to be amended
73 | // whenever you add a combination of architecture and
74 | // compiler that is not yet addressed.
75 | static_assert(sizeof(uintptr_t) == sizeof(unsigned long)
76 | || sizeof(uintptr_t) == sizeof(unsigned long long),
77 | "Please add string to handle conversion for this architecture.");
78 |
79 | // Now choose the correct function ...
80 | if (sizeof(uintptr_t) == sizeof(unsigned long)) {
81 | return strtoul(c, nullptr, base);
82 | }
83 |
84 | // All other options exhausted, sizeof(uintptr_t) == sizeof(unsigned long long))
85 | return strtoull(c, nullptr, base);
86 | }
87 |
88 |
89 |
90 | #endif
--------------------------------------------------------------------------------
/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 | import com.topjohnwu.superuser.Shell;
9 |
10 | public class MainActivity extends Activity {
11 |
12 | //Only if you have changed MainActivity to yours and you wanna call game's activity.
13 | public String GameActivity = "com.unity3d.player.UnityPlayerActivity";
14 | public boolean hasLaunched = false;
15 |
16 | @Override
17 | protected void onResume() {
18 | super.onResume();
19 |
20 | Intent intent = new Intent(Intent.ACTION_MAIN);
21 | intent.addCategory(Intent.CATEGORY_HOME);
22 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
23 | startActivity(intent);
24 | // Your code here
25 | }
26 |
27 |
28 | //To call onCreate, please refer to README.md
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | ApkExtract.extractLibDirToAppData(this);
33 | /*Thread.setDefaultUncaughtExceptionHandler(
34 | new Thread.UncaughtExceptionHandler() {
35 | @Override
36 | public void uncaughtException(Thread thread, Throwable e) {
37 | Log.e("AppCrash", "Error just lunched ");
38 | }
39 | });*/
40 |
41 |
42 | //To launch game activity
43 | if (!hasLaunched) {
44 | try {
45 | //Start service
46 | hasLaunched = true;
47 | //Launch mod menu.
48 | MainActivity.this.startActivity(new Intent(MainActivity.this, Class.forName(MainActivity.this.GameActivity)));
49 | Main.Start(this);
50 | return;
51 | } catch (ClassNotFoundException e) {
52 | Log.e("Mod_menu", "Error. Game's main activity does not exist");
53 | //Uncomment this if you are following METHOD 2 to launch menu
54 | //Toast.makeText(MainActivity.this, "Error. Game's main activity does not exist", Toast.LENGTH_LONG).show();
55 | }
56 | }
57 |
58 | //Launch mod menu.
59 | // Main.StartWithoutPermission(this);
60 | Main.Start(this);
61 | Intent intent = new Intent(Intent.ACTION_MAIN);
62 | intent.addCategory(Intent.CATEGORY_HOME);
63 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
64 | startActivity(intent);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Substrate/SubstrateARM.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/Client/Sources/Socket/Socket.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #include "Socket.h"
6 |
7 |
8 | Socket::Socket(){
9 | created = false;
10 | connected = false;
11 | }
12 |
13 | bool Socket::Create() {
14 | created = (sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) != -1;
15 | return created;
16 | }
17 |
18 | bool Socket::Connect() {
19 | memset(socket_name, 0, sizeof(socket_name));
20 | memcpy(&socket_name[0], "\0", 1);
21 | strcpy(&socket_name[1], SOCKET_NAME);
22 |
23 | memset(&addr_server, 0, sizeof(struct sockaddr_un));
24 | addr_server.sun_family = AF_UNIX; // Unix Domain instead of AF_INET IP domain
25 | strncpy(addr_server.sun_path, socket_name, sizeof(addr_server.sun_path) - 1); // 108 char max
26 |
27 | if (connect(sockfd, (sockaddr *) &addr_server, sizeof(addr_server)) == -1) {
28 | Close();
29 | return false;
30 | }
31 |
32 | connected = true;
33 | return true;
34 | }
35 |
36 | int Socket::sendData(void *inData, size_t size) {
37 | char *buffer = (char *) inData;
38 | int numSent = 0;
39 |
40 | while (size > 0) {
41 | do {
42 | numSent = write(sockfd, buffer, size);
43 | } while (numSent == -1 && EINTR == errno);
44 |
45 | if (numSent <= 0) {
46 | Close();
47 |
48 | return numSent;
49 | break;
50 | }
51 |
52 | size -= numSent;
53 | buffer += numSent;
54 | }
55 | return numSent;
56 | }
57 |
58 | bool Socket::send(void *inData, size_t size) {
59 | uint32_t length = htonl(static_cast(size));
60 | if (sendData(&length, sizeof(length)) <= 0) {
61 | return false;
62 | }
63 | return sendData(inData, size) > 0;
64 | }
65 |
66 | int Socket::recvData(void *outData, size_t size) {
67 | char *buffer = (char *) outData;
68 | int numReceived = 0;
69 |
70 | while (size) {
71 | do {
72 | numReceived = read(sockfd, buffer, size);
73 | } while (numReceived == -1 && EINTR == errno);
74 |
75 | if (numReceived <= 0) {
76 | Close();
77 | break;
78 | }
79 |
80 | size -= numReceived;
81 | buffer += numReceived;
82 | }
83 | return numReceived;
84 | }
85 |
86 | size_t Socket::receive(void *outData) {
87 | uint32_t length = 0;
88 | int code = recvData(&length, sizeof(uint32_t));
89 | if(code > 0){
90 | length = ntohl(length);
91 | recvData(outData, static_cast(length));
92 | }
93 | return length;
94 | }
95 |
96 | void Socket::Close() {
97 | connected = false;
98 | if (sockfd > 0)
99 | close(sockfd);
100 | }
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/Server/Sources/Substrate/SubstratePosixMemory.cpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/java/com/android/support/ApkExtract.java:
--------------------------------------------------------------------------------
1 | package com.android.support;
2 | import android.content.Context;import android.content.Context;
3 | import android.content.pm.ApplicationInfo;
4 | import android.content.pm.PackageManager;
5 | import java.io.*;
6 | import java.util.zip.ZipEntry;
7 | import java.util.zip.ZipInputStream;
8 |
9 | public class ApkExtract {
10 |
11 | public static void extractLibDirToAppData(Context context) {
12 | try {
13 | // Get the path to the APK of your app
14 | ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
15 | String apkPath = appInfo.sourceDir;
16 |
17 | // Define the output directory within the app's data directory
18 | File appDataLibDir = new File(context.getFilesDir(), "lib");
19 | if (!appDataLibDir.exists()) {
20 | appDataLibDir.mkdirs(); // Create the directory if not already present
21 | }
22 |
23 | // Extract the lib directory from the APK and copy it to the app's data directory
24 | extractLibFromApk(apkPath, appDataLibDir);
25 |
26 | System.out.println("Lib directory copied to " + appDataLibDir.getAbsolutePath());
27 | } catch (PackageManager.NameNotFoundException | IOException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 |
32 |
33 |
34 | // Method to extract the lib directory from the APK
35 | private static void extractLibFromApk(String apkPath, File outputDir) throws IOException {
36 | try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(apkPath))) {
37 | ZipEntry entry;
38 | while ((entry = zipInputStream.getNextEntry()) != null) {
39 | if (entry.getName().startsWith("lib/")) {
40 | // Create the file structure for the lib files
41 | File file = new File(outputDir, entry.getName().replaceFirst("lib/", ""));
42 | if (entry.isDirectory()) {
43 | file.mkdirs();
44 | } else {
45 | File parent = file.getParentFile();
46 | if (parent != null && !parent.exists()) {
47 | parent.mkdirs();
48 | }
49 |
50 | // Write the file
51 | try (FileOutputStream fos = new FileOutputStream(file)) {
52 | byte[] buffer = new byte[1024];
53 | int length;
54 | while ((length = zipInputStream.read(buffer)) > 0) {
55 | fos.write(buffer, 0, length);
56 | }
57 | }
58 | }
59 | }
60 | zipInputStream.closeEntry();
61 | }
62 | }
63 | }
64 |
65 | public static void extractLibDirToTmp(MainActivity mainActivity) {
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/support/GameInfo.java:
--------------------------------------------------------------------------------
1 | package com.android.support;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.io.IOException;
6 |
7 | public class GameInfo {
8 |
9 | String pkgName = "";
10 | String tmp = "/data/local/tmp";
11 | String abi = "";
12 | String gameAbi = "";
13 |
14 | public GameInfo(String pkgName) {
15 | this.pkgName = pkgName;
16 |
17 | try {
18 | if (!isRooted()) {
19 | System.out.println("App is not running as root.");
20 | return;
21 | }
22 | gameAbi = getCommandOutputAsRoot("dumpsys package " + pkgName + " | grep \"primaryCpuAbi\" | awk -F '=' '{print $2}'");
23 | abi = getCommandOutputAsRoot("getprop ro.product.cpu.abi");
24 | abi = adjustAbi(abi, gameAbi);
25 |
26 | } catch (Exception e) {
27 | e.printStackTrace();
28 | }
29 | }
30 |
31 | private static String adjustAbi(String abi, String gameAbi) {
32 | if (abi == null || gameAbi == null) {
33 | return null; // Null check to avoid exceptions
34 | }
35 |
36 | switch (abi) {
37 | case "arm64-v8a":
38 | case "armeabi-v7a":
39 | return gameAbi;
40 | case "x86_64":
41 | if (gameAbi.equals("armeabi-v7a")) {
42 | return "x86";
43 | }
44 | return abi;
45 | case "x86":
46 | return abi;
47 | default:
48 | // If the device ABI is not supported
49 | return null;
50 | }
51 | }
52 |
53 | private static String getCommandOutputAsRoot(String command) throws IOException {
54 | // Run the command as root by using 'su -c'
55 | ProcessBuilder processBuilder = new ProcessBuilder("su", "-c", command);
56 | Process process = processBuilder.start();
57 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
58 | StringBuilder output = new StringBuilder();
59 | String line;
60 |
61 | while ((line = reader.readLine()) != null) {
62 | output.append(line).append("\n");
63 | }
64 |
65 | return output.toString().trim();
66 | }
67 |
68 |
69 | private static boolean isRooted() {
70 | // Check if the app is running as root using 'su -c id'
71 | try {
72 | String output = getCommandOutputAsRoot("id");
73 | return output != null && output.contains("uid=0");
74 | } catch (IOException e) {
75 | e.printStackTrace();
76 | return false;
77 | }
78 | }
79 |
80 | public String getPkgName() {
81 | return pkgName;
82 | }
83 |
84 | public String getAbi() {
85 | return abi;
86 | }
87 |
88 | public String getTmp() {
89 | return tmp;
90 | }
91 |
92 | public String getGameAbi() {
93 | return gameAbi;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Socket/Socket.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #include "Socket.h"
6 |
7 | #include
8 | #include
9 |
10 | Socket::Socket(){
11 | isCreated = false;
12 | }
13 |
14 | bool Socket::Create() {
15 | isCreated = (listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0;
16 | return isCreated;
17 | }
18 |
19 | bool Socket::Bind() {
20 | memset(socket_name, 0, sizeof(socket_name));
21 | memcpy(&socket_name[0], "\0", 1);
22 | strcpy(&socket_name[1], SOCKET_NAME);
23 |
24 | memset(&addr_server, 0, sizeof(addr_server));
25 | addr_server.sun_family = AF_UNIX; // Unix Domain instead of AF_INET IP domain
26 | strncpy(addr_server.sun_path, socket_name, sizeof(addr_server.sun_path) - 1); // 108 char max
27 |
28 | if (bind(listenfd, (sockaddr *) &addr_server, sizeof(addr_server)) < 0) {
29 | Close();
30 | return false;
31 | }
32 | return true;
33 | }
34 |
35 | bool Socket::Listen() {
36 | if (listen(listenfd, BACKLOG) < 0) {
37 | Close();
38 | return false;
39 | }
40 | return true;
41 | }
42 |
43 | bool Socket::Accept() {
44 | if ((acceptfd = accept(listenfd, nullptr, nullptr)) < 0) {
45 | Close();
46 | return false;
47 | }
48 | return true;
49 | }
50 |
51 | int Socket::sendData(void *inData, size_t size) {
52 | char *buffer = (char *) inData;
53 | int numSent = 0;
54 |
55 | while (size) {
56 | do {
57 | numSent = write(acceptfd, buffer, size);
58 | } while (numSent == -1 && EINTR == errno);
59 |
60 | if (numSent <= 0) {
61 | Close();
62 | break;
63 | }
64 |
65 | size -= numSent;
66 | buffer += numSent;
67 | }
68 | return numSent;
69 | }
70 |
71 | bool Socket::send(void* inData, size_t size) {
72 | uint32_t length = htonl(size);
73 | if(sendData(&length, sizeof(uint32_t)) <= 0){
74 | return false;
75 | }
76 | return sendData((void*)inData, size) > 0;
77 | }
78 |
79 | int Socket::recvData(void *outData, size_t size) {
80 | char *buffer = (char *) outData;
81 | int numReceived = 0;
82 |
83 | while (size) {
84 | do {
85 | numReceived = read(acceptfd, buffer, size);
86 | } while (numReceived == -1 && EINTR == errno);
87 |
88 | if (numReceived <= 0) {
89 | Close();
90 | break;
91 | }
92 |
93 | size -= numReceived;
94 | buffer += numReceived;
95 | }
96 | return numReceived;
97 | }
98 |
99 | size_t Socket::receive(void* outData) {
100 | uint32_t length = 0;
101 | int code = recvData(&length, sizeof(uint32_t));
102 | if(code > 0){
103 | length = ntohl(length);
104 | recvData(outData, static_cast(length));
105 | }
106 | return length;
107 | }
108 |
109 | void Socket::Close() {
110 | if (acceptfd > 0)
111 | close(acceptfd);
112 | if (listenfd > 0)
113 | close(listenfd);
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/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/Server/Sources/Substrate/SubstrateDebug.cpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/Server/Sources/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/Server/Sources/KittyMemory/KittyMemory.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Server.Sources.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/Server/Sources/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/Server/Sources/Substrate/CydiaSubstrate.h:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/java/com/android/support/CrashHandler.java:
--------------------------------------------------------------------------------
1 |
2 | package com.android.support;
3 |
4 |
5 | import android.content.Context;
6 | import android.content.pm.PackageInfo;
7 | import android.content.pm.PackageManager;
8 | import android.os.Build;
9 | import android.util.Log;
10 | import android.widget.Toast;
11 | import java.io.File;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.PrintWriter;
15 | import java.io.StringWriter;
16 | import java.lang.Thread.UncaughtExceptionHandler;
17 | import java.text.SimpleDateFormat;
18 | import java.util.Date;
19 |
20 | public final class CrashHandler {
21 |
22 | public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
23 |
24 | public static void init(final Context app, final boolean overlayRequired) {
25 | Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
26 |
27 | @Override
28 | public void uncaughtException(Thread thread, Throwable throwable) {
29 | Log.e("AppCrash", "Error just lunched ");
30 | try {
31 | tryUncaughtException(thread, throwable);
32 | } catch (Throwable e) {
33 | e.printStackTrace();
34 | if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
35 | DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
36 | else
37 | System.exit(2);
38 | }
39 | }
40 |
41 | private void tryUncaughtException(Thread thread, Throwable throwable) {
42 | Log.e("AppCrash", "Try saving log");
43 |
44 | final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss").format(new Date());
45 | String fileName = "mod_menu_crash_" + time + ".txt";
46 | String dirName;
47 |
48 | if (Build.VERSION.SDK_INT >= 30) { //Android R. AIDE didn't support Build.VERSION_CODES.R
49 | dirName = "/storage/emulated/0/Documents/";
50 | } else {
51 | dirName = String.valueOf(app.getExternalFilesDir(null));
52 | }
53 |
54 | File crashFile = new File(dirName, fileName);
55 |
56 | String versionName = "unknown";
57 | long versionCode = 0;
58 | try {
59 | PackageInfo packageInfo = app.getPackageManager().getPackageInfo(app.getPackageName(), 0);
60 | versionName = packageInfo.versionName;
61 | versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode()
62 | : packageInfo.versionCode;
63 | } catch (PackageManager.NameNotFoundException ignored) {
64 | }
65 |
66 | String fullStackTrace;
67 | {
68 | StringWriter sw = new StringWriter();
69 | PrintWriter pw = new PrintWriter(sw);
70 | throwable.printStackTrace(pw);
71 | fullStackTrace = sw.toString();
72 | pw.close();
73 | }
74 |
75 | String errorLog = "************* Crash Head ****************\n" +
76 | "Time Of Crash : " + time + "\n" +
77 | "Device Manufacturer: " + Build.MANUFACTURER + "\n" +
78 | "Device Model : " + Build.MODEL + "\n" +
79 | "Android Version : " + Build.VERSION.RELEASE + "\n" +
80 | "Android SDK : " + Build.VERSION.SDK_INT + "\n" +
81 | "App VersionName : " + versionName + "\n" +
82 | "App VersionCode : " + versionCode + "\n" +
83 | "************* Crash Head ****************\n" +
84 | "\n" + fullStackTrace;
85 |
86 | try {
87 | writeFile(crashFile, errorLog);
88 | } catch (IOException ignored) {
89 | }
90 |
91 | Toast.makeText(app, "Game has crashed unexpectedly", Toast.LENGTH_LONG).show();
92 | Toast.makeText(app, "Log saved to: " + String.valueOf(crashFile).replace("/storage/emulated/0/", ""), Toast.LENGTH_LONG).show();
93 |
94 | Log.e("AppCrash", "Done");
95 |
96 | System.exit(2);
97 | }
98 |
99 | private void writeFile(File file, String content) throws IOException {
100 | File parentFile = file.getParentFile();
101 | if (parentFile != null && !parentFile.exists()) {
102 | parentFile.mkdirs();
103 | }
104 | file.createNewFile();
105 | FileOutputStream fos = new FileOutputStream(file);
106 | fos.write(content.getBytes());
107 | try {
108 | fos.close();
109 | } catch (IOException e) {
110 | }
111 | }
112 | });
113 | }
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/app/src/main/jni/Client/Client.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by arjun on 6/19/24.
3 | //
4 |
5 | #include
6 | #include
7 | #include "Includes/Logger.h"
8 | #include "Includes/obfuscate.h"
9 | #include "Client/includes/Setup.h"
10 | #include "Client/Sources/Socket/Socket.h"
11 | #include "Client/Sources/Socket/request.h"
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include
19 |
20 |
21 | const char *package_name = "com.mobirix.zombiefire";
22 |
23 |
24 | jobjectArray GetFeatureList(JNIEnv *env, jobject context) {
25 | jobjectArray ret;
26 |
27 | const char *features[] = {
28 | OBFUSCATE("Category_The Category"), //Not counted
29 | OBFUSCATE("2_Toggle_Stop Zombies"),
30 | };
31 |
32 | //Now you dont have to manually update the number everytime;
33 | int Total_Feature = (sizeof features / sizeof features[0]);
34 | ret = (jobjectArray)
35 | env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")),
36 | env->NewStringUTF(""));
37 |
38 | for (int i = 0; i < Total_Feature; i++)
39 | env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i]));
40 |
41 | return (ret);
42 | }
43 |
44 |
45 |
46 | void Changes(JNIEnv *env, jclass clazz, jobject obj,
47 | jint featNum, jstring featName, jint value,
48 | jboolean boolean, jstring str) {
49 |
50 | LOGD(OBFUSCATE("Feature name: %d - %s | Value: = %d | Bool: = %d | Text: = %s"), featNum,
51 | env->GetStringUTFChars(featName, 0), value,
52 | boolean, str != NULL ? env->GetStringUTFChars(str, 0) : "");
53 |
54 | Send(featNum, value, boolean);
55 | }
56 |
57 | int RegisterMenu(JNIEnv *env) {
58 | JNINativeMethod methods[] = {
59 | {OBFUSCATE("Icon"), OBFUSCATE("()Ljava/lang/String;"), reinterpret_cast(Icon)},
60 | {OBFUSCATE("IconWebViewData"), OBFUSCATE("()Ljava/lang/String;"), reinterpret_cast(IconWebViewData)},
61 | {OBFUSCATE("Init"), OBFUSCATE("(Landroid/content/Context;Landroid/widget/TextView;Landroid/widget/TextView;)V"), reinterpret_cast(Init)},
62 | {OBFUSCATE("SettingsList"), OBFUSCATE("()[Ljava/lang/String;"), reinterpret_cast(SettingsList)},
63 | {OBFUSCATE("GetFeatureList"), OBFUSCATE("()[Ljava/lang/String;"), reinterpret_cast(GetFeatureList)},
64 | };
65 |
66 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Menu"));
67 | if (!clazz)
68 | return JNI_ERR;
69 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0)
70 | return JNI_ERR;
71 | return JNI_OK;
72 | }
73 |
74 | int RegisterPreferences(JNIEnv *env) {
75 | JNINativeMethod methods[] = {
76 | {OBFUSCATE("Changes"), OBFUSCATE("(Landroid/content/Context;ILjava/lang/String;IZLjava/lang/String;)V"), reinterpret_cast(Changes)},
77 | };
78 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Preferences"));
79 | if (!clazz)
80 | return JNI_ERR;
81 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0)
82 | return JNI_ERR;
83 | return JNI_OK;
84 | }
85 |
86 | int RegisterMain(JNIEnv *env) {
87 | JNINativeMethod methods[] = {
88 | {OBFUSCATE("CheckOverlayPermission"), OBFUSCATE("(Landroid/content/Context;)V"), reinterpret_cast(CheckOverlayPermission)},
89 | };
90 | jclass clazz = env->FindClass(OBFUSCATE("com/android/support/Main"));
91 | if (!clazz)
92 | return JNI_ERR;
93 | if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != 0)
94 | return JNI_ERR;
95 |
96 | return JNI_OK;
97 | }
98 |
99 | extern "C"
100 | JNIEXPORT void JNICALL
101 | Java_com_android_support_Menu_InitServer(JNIEnv *env, jobject thiz) {
102 |
103 |
104 | startClient();
105 |
106 | }
107 | extern "C"
108 | JNIEXPORT void JNICALL
109 | Java_com_android_support_Menu_Stop(JNIEnv *env, jobject thiz) {
110 | stopClient();
111 | }
112 |
113 | extern "C"
114 | JNIEXPORT jint JNICALL
115 | Java_com_android_support_injector_InjectorData_Inject(JNIEnv * env, jclass clazz) {
116 |
117 | return 0;
118 | }
119 |
120 | extern "C"
121 | JNIEXPORT jboolean JNICALL
122 | Java_com_android_support_Menu_IsConnected(JNIEnv *env, jobject thiz) {
123 | return isSConnected();
124 | }
125 | extern "C"
126 | JNIEXPORT jint JNICALL
127 | JNI_OnLoad(JavaVM *vm, void *reserved) {
128 | JNIEnv *env;
129 | vm->GetEnv((void **) &env, JNI_VERSION_1_6);
130 | if (RegisterMenu(env) != 0)
131 | return JNI_ERR;
132 | if (RegisterPreferences(env) != 0)
133 | return JNI_ERR;
134 | if (RegisterMain(env) != 0)
135 | return JNI_ERR;
136 | return JNI_VERSION_1_6;
137 | }
138 |
139 | extern "C"
140 | JNIEXPORT void JNICALL
141 | Java_com_android_support_Main_CheckOverlayPermission(JNIEnv *env, jclass clazz, jobject context) {
142 | CheckOverlayPermission(env, clazz, context);
143 | }
144 | extern "C"
145 | JNIEXPORT jstring JNICALL
146 | Java_com_android_support_Menu_get_1package_1name(JNIEnv *env, jobject thiz) {
147 | return env->NewStringUTF(package_name);
148 | }
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/KittyMemory/KittyMemory.h:
--------------------------------------------------------------------------------
1 | //
2 | // Server.Sources.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/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 | #endif
12 |
13 | void hook(void *offset, void* ptr, void **orig)
14 | {
15 | #if defined(__aarch64__)
16 | A64HookFunction(offset, ptr, orig);
17 | #else
18 | MSHookFunction(offset, ptr, orig);
19 | #endif
20 | }
21 |
22 | #define HOOK(offset, ptr, orig) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig)
23 | #define HOOK_LIB(lib, offset, ptr, orig) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig)
24 |
25 | #define HOOK_NO_ORIG(offset, ptr) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL)
26 | #define HOOK_LIB_NO_ORIG(lib, offset, ptr) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL)
27 |
28 | #define HOOKSYM(sym, ptr, org) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org)
29 | #define HOOKSYM_LIB(lib, sym, ptr, org) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org)
30 |
31 | #define HOOKSYM_NO_ORIG(sym, ptr) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, NULL)
32 | #define HOOKSYM_LIB_NO_ORIG(lib, sym, ptr) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, NULL)
33 |
34 | std::vector memoryPatches;
35 | std::vector offsetVector;
36 |
37 | // Patching a offset without switch.
38 | void patchOffset(const char *fileName, uint64_t offset, std::string hexBytes, bool isOn) {
39 |
40 | MemoryPatch patch = MemoryPatch::createWithHex(fileName, offset, hexBytes);
41 |
42 | //Check if offset exists in the offsetVector
43 | if (std::find(offsetVector.begin(), offsetVector.end(), offset) != offsetVector.end()) {
44 | //LOGE(OBFUSCATE("Already exists"));
45 | std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), offset);
46 | patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector
47 | } else {
48 | memoryPatches.push_back(patch);
49 | offsetVector.push_back(offset);
50 | //LOGI(OBFUSCATE("Added"));
51 | }
52 |
53 | if (!patch.isValid()) {
54 | LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), offset);
55 | return;
56 | }
57 | if (isOn) {
58 | if (!patch.Modify()) {
59 | LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), offset);
60 | }
61 | } else {
62 | if (!patch.Restore()) {
63 | LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), offset);
64 | }
65 | }
66 | }
67 |
68 | void patchOffsetSym(uintptr_t absolute_address, std::string hexBytes, bool isOn) {
69 |
70 | MemoryPatch patch = MemoryPatch::createWithHex(absolute_address, hexBytes);
71 |
72 | //Check if offset exists in the offsetVector
73 | if (std::find(offsetVector.begin(), offsetVector.end(), absolute_address) != offsetVector.end()) {
74 | //LOGE(OBFUSCATE("Already exists"));
75 | std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), absolute_address);
76 | patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector
77 | } else {
78 | memoryPatches.push_back(patch);
79 | offsetVector.push_back(absolute_address);
80 | //LOGI(OBFUSCATE("Added"));
81 | }
82 |
83 | if (!patch.isValid()) {
84 | LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), absolute_address);
85 | return;
86 | }
87 | if (isOn) {
88 | if (!patch.Modify()) {
89 | LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), absolute_address);
90 | }
91 | } else {
92 | if (!patch.Restore()) {
93 | LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), absolute_address);
94 | }
95 | }
96 | }
97 |
98 | #define PATCH(offset, hex) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true)
99 | #define PATCH_LIB(lib, offset, hex) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true)
100 |
101 | #define PATCH_SYM(sym, hex) patchOffset(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true)
102 | #define PATCH_LIB_SYM(lib, sym, hex) patchOffset(dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true)
103 |
104 | #define PATCH_SWITCH(offset, hex, boolean) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean)
105 | #define PATCH_LIB_SWITCH(lib, offset, hex, boolean) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean)
106 |
107 | #define PATCH_SYM_SWITCH(sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean)
108 | #define PATCH_LIB_SYM_SWITCH(lib, sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean)
109 |
110 | #define RESTORE(offset) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), "", false)
111 | #define RESTORE_LIB(lib, offset) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), "", false)
112 |
113 | #define RESTORE_SYM(sym) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), "", false)
114 | #define RESTORE_LIB_SYM(lib, sym) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), "", false)
115 |
116 | #endif //ANDROID_MOD_MENU_MACROS_H
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/jni/Client/includes/Setup.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Client/includes/Menu.h"
3 | #include "Client/includes/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 | namespace ToastLength {
33 | inline const int LENGTH_LONG = 1;
34 | inline const int LENGTH_SHORT = 0;
35 | }
36 | void Toast(JNIEnv *env, jobject thiz, const char *text, int length) {
37 | jstring jstr = env->NewStringUTF(text);
38 | jclass toast = env->FindClass(OBFUSCATE("android/widget/Toast"));
39 | jmethodID methodMakeText =env->GetStaticMethodID(toast,OBFUSCATE("makeText"),OBFUSCATE("(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;"));
40 | jobject toastobj = env->CallStaticObjectMethod(toast, methodMakeText,thiz, jstr, length);
41 | jmethodID methodShow = env->GetMethodID(toast, OBFUSCATE("show"), OBFUSCATE("()V"));
42 | env->CallVoidMethod(toastobj, methodShow);
43 | }
44 |
45 | void startActivityPermisson(JNIEnv *env, jobject ctx){
46 | jclass native_context = env->GetObjectClass(ctx);
47 | jmethodID startActivity = env->GetMethodID(native_context, OBFUSCATE("startActivity"),OBFUSCATE("(Landroid/content/Intent;)V"));
48 |
49 | jmethodID pack = env->GetMethodID(native_context, OBFUSCATE("getPackageName"),OBFUSCATE("()Ljava/lang/String;"));
50 | jstring packageName = static_cast(env->CallObjectMethod(ctx, pack));
51 |
52 | const char *pkg = env->GetStringUTFChars(packageName, 0);
53 |
54 | std::stringstream pkgg;
55 | pkgg << OBFUSCATE("package:");
56 | pkgg << pkg;
57 | std::string pakg = pkgg.str();
58 |
59 | jclass Uri = env->FindClass(OBFUSCATE("android/net/Uri"));
60 | jmethodID Parce = env->GetStaticMethodID(Uri, OBFUSCATE("parse"), OBFUSCATE("(Ljava/lang/String;)Landroid/net/Uri;"));
61 | jobject UriMethod = env->CallStaticObjectMethod(Uri, Parce, env->NewStringUTF(pakg.c_str()));
62 |
63 | jclass intentclass = env->FindClass(OBFUSCATE("android/content/Intent"));
64 | jmethodID newIntent = env->GetMethodID(intentclass, OBFUSCATE(""), OBFUSCATE("(Ljava/lang/String;Landroid/net/Uri;)V"));
65 | jobject intent = env->NewObject(intentclass,newIntent,env->NewStringUTF(OBFUSCATE("android.settings.action.MANAGE_OVERLAY_PERMISSION")), UriMethod);
66 |
67 | env->CallVoidMethod(ctx, startActivity, intent);
68 | }
69 |
70 | void startService(JNIEnv *env, jobject ctx){
71 | jclass native_context = env->GetObjectClass(ctx);
72 | jclass intentClass = env->FindClass(OBFUSCATE("android/content/Intent"));
73 | jclass actionString = env->FindClass(OBFUSCATE("com/android/support/Launcher"));
74 | jmethodID newIntent = env->GetMethodID(intentClass, OBFUSCATE(""), OBFUSCATE("(Landroid/content/Context;Ljava/lang/Class;)V"));
75 | jobject intent = env->NewObject(intentClass,newIntent,ctx,actionString);
76 | jmethodID startActivityMethodId = env->GetMethodID(native_context, OBFUSCATE("startService"), OBFUSCATE("(Landroid/content/Intent;)Landroid/content/ComponentName;"));
77 | env->CallObjectMethod(ctx, startActivityMethodId, intent);
78 | }
79 |
80 | void *exit_thread(void *) {
81 | sleep(5);
82 | exit(0);
83 | }
84 |
85 | //Needed jclass parameter because this is a static java method
86 | void CheckOverlayPermission(JNIEnv *env, jclass thiz, jobject ctx){
87 | //If overlay permission option is greyed out, make sure to add android.permission.SYSTEM_ALERT_WINDOW in manifest
88 |
89 | LOGI(OBFUSCATE("Check overlay permission"));
90 |
91 | int sdkVer = api_level();
92 | if (sdkVer >= 23){ //Android 6.0
93 | jclass Settings = env->FindClass(OBFUSCATE("android/provider/Settings"));
94 | jmethodID canDraw =env->GetStaticMethodID(Settings, OBFUSCATE("canDrawOverlays"), OBFUSCATE("(Landroid/content/Context;)Z"));
95 | if (!env->CallStaticBooleanMethod(Settings, canDraw, ctx)){
96 | Toast(env,ctx,OBFUSCATE("Overlay permission is required in order to show mod menu."),1);
97 | Toast(env,ctx,OBFUSCATE("Overlay permission is required in order to show mod menu."),1);
98 | startActivityPermisson(env, ctx);
99 |
100 | pthread_t ptid;
101 | pthread_create(&ptid, NULL, exit_thread, NULL);
102 | return;
103 | }
104 | }
105 |
106 |
107 | LOGI(OBFUSCATE("Start service"));
108 |
109 | //StartMod Normal
110 | startService(env, ctx);
111 | }
112 |
113 | void Init(JNIEnv *env, jobject thiz, jobject ctx, jobject title, jobject subtitle){
114 | //Set sub title
115 | setText(env, title, OBFUSCATE("Modded by (yourname)"));
116 |
117 | //Set sub title
118 | setText(env, subtitle, OBFUSCATE("
"
121 | ""));
122 |
123 | //Dialog Example
124 | //setDialog(ctx,env,OBFUSCATE("Title"),OBFUSCATE("Message Example"));
125 |
126 | //Toast Example
127 | Toast(env,ctx,OBFUSCATE("Modded by YOU"),ToastLength::LENGTH_LONG);
128 |
129 | initValid = true;
130 | }
--------------------------------------------------------------------------------
/app/src/main/jni/Server/Sources/Substrate/SubstrateX86.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Server.Sources.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 | * Server.Sources.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 | * Server.Sources.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 Server.Sources.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/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/Server/Sources/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/Client/includes/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/Server/Sources/Substrate/SymbolFinder.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include "SymbolFinder.h"
11 |
12 | #define TAG "MSHook"
13 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
14 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
15 | /* memory map for libraries */
16 | #define MAX_NAME_LEN 256
17 | #define MEMORY_ONLY "[memory]"
18 | struct mm {
19 | char name[MAX_NAME_LEN];
20 | unsigned long start, end;
21 | };
22 |
23 | typedef struct symtab *symtab_t;
24 | struct symlist {
25 | Elf32_Sym *sym; /* symbols */
26 | char *str; /* symbol strings */
27 | unsigned num; /* number of symbols */
28 | };
29 | struct symtab {
30 | struct symlist *st; /* "static" symbols */
31 | struct symlist *dyn; /* dynamic symbols */
32 | };
33 |
34 | static void *xmalloc(size_t size) {
35 | void *p;
36 | p = malloc(size);
37 | if (!p) {
38 | printf(OBFUSCATE("Out of memory\n"));
39 | exit(1);
40 | }
41 | return p;
42 | }
43 |
44 | static int my_pread(int fd, void *buf, size_t count, off_t offset) {
45 | lseek(fd, offset, SEEK_SET);
46 | return read(fd, buf, count);
47 | }
48 |
49 | static struct symlist *get_syms(int fd, Elf32_Shdr *symh, Elf32_Shdr *strh) {
50 | struct symlist *sl, *ret;
51 | int rv;
52 |
53 | ret = NULL;
54 | sl = (struct symlist *) xmalloc(sizeof(struct symlist));
55 | sl->str = NULL;
56 | sl->sym = NULL;
57 |
58 | /* sanity */
59 | if (symh->sh_size % sizeof(Elf32_Sym)) {
60 | //printf("elf_error\n");
61 | goto out;
62 | }
63 |
64 | /* symbol table */
65 | sl->num = symh->sh_size / sizeof(Elf32_Sym);
66 | sl->sym = (Elf32_Sym *) xmalloc(symh->sh_size);
67 | rv = my_pread(fd, sl->sym, symh->sh_size, symh->sh_offset);
68 | if (0 > rv) {
69 | //perror("read");
70 | goto out;
71 | }
72 | if (rv != symh->sh_size) {
73 | //printf("elf error\n");
74 | goto out;
75 | }
76 |
77 | /* string table */
78 | sl->str = (char *) xmalloc(strh->sh_size);
79 | rv = my_pread(fd, sl->str, strh->sh_size, strh->sh_offset);
80 | if (0 > rv) {
81 | //perror("read");
82 | goto out;
83 | }
84 | if (rv != strh->sh_size) {
85 | //printf("elf error");
86 | goto out;
87 | }
88 |
89 | ret = sl;
90 | out:
91 | return ret;
92 | }
93 |
94 | static int do_load(int fd, symtab_t symtab) {
95 | int rv;
96 | size_t size;
97 | Elf32_Ehdr ehdr;
98 | Elf32_Shdr *shdr = NULL, *p;
99 | Elf32_Shdr *dynsymh, *dynstrh;
100 | Elf32_Shdr *symh, *strh;
101 | char *shstrtab = NULL;
102 | int i;
103 | int ret = -1;
104 |
105 | /* elf header */
106 | rv = read(fd, &ehdr, sizeof(ehdr));
107 | if (0 > rv) {
108 | LOGD(OBFUSCATE("read\n"));
109 | goto out;
110 | }
111 | if (rv != sizeof(ehdr)) {
112 | LOGD(OBFUSCATE("elf error 1\n"));
113 | goto out;
114 | }
115 | if (strncmp((const char *) ELFMAG, (const char *) ehdr.e_ident, SELFMAG)) { /* sanity */
116 | LOGD(OBFUSCATE("not an elf\n"));
117 | goto out;
118 | }
119 | if (sizeof(Elf32_Shdr) != ehdr.e_shentsize) { /* sanity */
120 | LOGD(OBFUSCATE("elf error 2\n"));
121 | goto out;
122 | }
123 |
124 | /* section header table */
125 | size = ehdr.e_shentsize * ehdr.e_shnum;
126 | shdr = (Elf32_Shdr *) xmalloc(size);
127 | rv = my_pread(fd, shdr, size, ehdr.e_shoff);
128 | if (0 > rv) {
129 | LOGD(OBFUSCATE("read\n"));
130 | goto out;
131 | }
132 | if (rv != size) {
133 | LOGD(OBFUSCATE("elf error 3 %d %d\n"), rv, size);
134 | goto out;
135 | }
136 |
137 | /* section header string table */
138 | size = shdr[ehdr.e_shstrndx].sh_size;
139 | shstrtab = (char *) xmalloc(size);
140 | rv = my_pread(fd, shstrtab, size, shdr[ehdr.e_shstrndx].sh_offset);
141 | if (0 > rv) {
142 | LOGD(OBFUSCATE("read\n"));
143 | goto out;
144 | }
145 | if (rv != size) {
146 | LOGD(OBFUSCATE("elf error 4 %d %d\n"), rv, size);
147 | goto out;
148 | }
149 |
150 | /* symbol table headers */
151 | symh = dynsymh = NULL;
152 | strh = dynstrh = NULL;
153 | for (i = 0, p = shdr; i < ehdr.e_shnum; i++, p++)
154 | if (SHT_SYMTAB == p->sh_type) {
155 | if (symh) {
156 | LOGD(OBFUSCATE("too many symbol tables\n"));
157 | goto out;
158 | }
159 | symh = p;
160 | } else if (SHT_DYNSYM == p->sh_type) {
161 | if (dynsymh) {
162 | LOGD(OBFUSCATE("too many symbol tables\n"));
163 | goto out;
164 | }
165 | dynsymh = p;
166 | } else if (SHT_STRTAB == p->sh_type
167 | && !strncmp(shstrtab + p->sh_name, OBFUSCATE(".strtab"), 7)) {
168 | if (strh) {
169 | LOGD(OBFUSCATE("too many string tables\n"));
170 | goto out;
171 | }
172 | strh = p;
173 | } else if (SHT_STRTAB == p->sh_type
174 | && !strncmp(shstrtab + p->sh_name, OBFUSCATE(".dynstr"), 7)) {
175 | if (dynstrh) {
176 | LOGD(OBFUSCATE("too many string tables\n"));
177 | goto out;
178 | }
179 | dynstrh = p;
180 | }
181 | /* sanity checks */
182 | if ((!dynsymh && dynstrh) || (dynsymh && !dynstrh)) {
183 | LOGD(OBFUSCATE("bad dynamic symbol table\n"));
184 | goto out;
185 | }
186 | if ((!symh && strh) || (symh && !strh)) {
187 | LOGD(OBFUSCATE("bad symbol table\n"));
188 | goto out;
189 | }
190 | if (!dynsymh && !symh) {
191 | LOGD(OBFUSCATE("no symbol table\n"));
192 | goto out;
193 | }
194 |
195 | /* symbol tables */
196 | if (dynsymh)
197 | symtab->dyn = get_syms(fd, dynsymh, dynstrh);
198 | if (symh)
199 | symtab->st = get_syms(fd, symh, strh);
200 | ret = 0;
201 | out:
202 | free(shstrtab);
203 | free(shdr);
204 | return ret;
205 | }
206 |
207 | static symtab_t load_symtab(char *filename) {
208 | int fd;
209 | symtab_t symtab;
210 |
211 | symtab = (symtab_t) xmalloc(sizeof(*symtab));
212 | memset(symtab, 0, sizeof(*symtab));
213 |
214 | fd = open(filename, O_RDONLY);
215 | if (0 > fd) {
216 | LOGE(OBFUSCATE("%s open\n"), __func__);
217 | return NULL;
218 | }
219 | if (0 > do_load(fd, symtab)) {
220 | LOGE(OBFUSCATE("Error ELF parsing %s\n"), filename);
221 | free(symtab);
222 | symtab = NULL;
223 | }
224 | close(fd);
225 | return symtab;
226 | }
227 |
228 | static int load_memmap(pid_t pid, struct mm *mm, int *nmmp) {
229 | size_t buf_size = 0x40000;
230 | char *p_buf = (char *) malloc(buf_size); // increase this if needed for larger "maps"
231 | char name[MAX_NAME_LEN] = {0};
232 | char *p;
233 | unsigned long start, end;
234 | struct mm *m;
235 | int nmm = 0;
236 | int fd, rv;
237 | int i;
238 |
239 | sprintf(p_buf, OBFUSCATE("/proc/%d/maps"), pid);
240 | fd = open(p_buf, O_RDONLY);
241 | if (0 > fd) {
242 | LOGE(OBFUSCATE("Can't open %s for reading\n"), p_buf);
243 | free(p_buf);
244 | return -1;
245 | }
246 |
247 | /* Zero to ensure data is null terminated */
248 | memset(p_buf, 0, buf_size);
249 |
250 | p = p_buf;
251 | while (1) {
252 | rv = read(fd, p, buf_size - (p - p_buf));
253 | if (0 > rv) {
254 | LOGE(OBFUSCATE("%s read"), __FUNCTION__);
255 | free(p_buf);
256 | return -1;
257 | }
258 | if (0 == rv)
259 | break;
260 | p += rv;
261 | if (p - p_buf >= buf_size) {
262 | LOGE(OBFUSCATE("Too many memory mapping\n"));
263 | free(p_buf);
264 | return -1;
265 | }
266 | }
267 | close(fd);
268 |
269 | p = strtok(p_buf, "\n");
270 | m = mm;
271 | while (p) {
272 | /* parse current map line */
273 | rv = sscanf(p, OBFUSCATE("%08lx-%08lx %*s %*s %*s %*s %s\n"), &start, &end, name);
274 |
275 | p = strtok(NULL, "\n");
276 |
277 | if (rv == 2) {
278 | m = &mm[nmm++];
279 | m->start = start;
280 | m->end = end;
281 | memcpy(m->name, MEMORY_ONLY, sizeof(MEMORY_ONLY));
282 | continue;
283 | }
284 |
285 | /* search backward for other mapping with same name */
286 | for (i = nmm - 1; i >= 0; i--) {
287 | m = &mm[i];
288 | if (!strcmp(m->name, name))
289 | break;
290 | }
291 |
292 | if (i >= 0) {
293 | if (start < m->start)
294 | m->start = start;
295 | if (end > m->end)
296 | m->end = end;
297 | } else {
298 | /* new entry */
299 | m = &mm[nmm++];
300 | m->start = start;
301 | m->end = end;
302 | memcpy(m->name, name, strlen(name));
303 | }
304 | }
305 |
306 | *nmmp = nmm;
307 | free(p_buf);
308 | return 0;
309 | }
310 |
311 | /* Find libc in MM, storing no more than LEN-1 chars of
312 | its name in NAME and set START to its starting
313 | address. If libc cannot be found return -1 and
314 | leave NAME and START untouched. Otherwise return 0
315 | and null-terminated NAME. */
316 | static int find_libname(const char *libn, char *name, int len, unsigned long *start,
317 | struct mm *mm, int nmm) {
318 | int i;
319 | struct mm *m;
320 | char *p;
321 | for (i = 0, m = mm; i < nmm; i++, m++) {
322 | if (!strcmp(m->name, MEMORY_ONLY))
323 | continue;
324 | p = strrchr(m->name, '/');
325 | if (!p)
326 | continue;
327 | p++;
328 | if (strncmp(libn, p, strlen(libn)))
329 | continue;
330 | p += strlen(libn);
331 |
332 | /* here comes our crude test -> 'libc.so' or 'libc-[0-9]' */
333 | if (!strncmp(OBFUSCATE("so"), p, 2) || 1) // || (p[0] == '-' && isdigit(p[1])))
334 | break;
335 | }
336 | if (i >= nmm)
337 | /* not found */
338 | return -1;
339 |
340 | *start = m->start;
341 | strncpy(name, m->name, len);
342 | if (strlen(m->name) >= len)
343 | name[len - 1] = '\0';
344 |
345 | mprotect((void *) m->start, m->end - m->start,
346 | PROT_READ | PROT_WRITE | PROT_EXEC);
347 | return 0;
348 | }
349 |
350 | static int lookup2(struct symlist *sl, unsigned char type, char *name,
351 | unsigned long *val) {
352 | Elf32_Sym *p;
353 | int len;
354 | int i;
355 |
356 | len = strlen(name);
357 | for (i = 0, p = sl->sym; i < sl->num; i++, p++) {
358 | //LOGD("name: %s %x\n", sl->str+p->st_name, p->st_value)
359 | if (!strncmp(sl->str + p->st_name, name, len)
360 | && *(sl->str + p->st_name + len) == 0
361 | && ELF32_ST_TYPE(p->st_info) == type) {
362 | //if (p->st_value != 0) {
363 | *val = p->st_value;
364 | return 0;
365 | //}
366 | }
367 | }
368 | return -1;
369 | }
370 |
371 | static int lookup_sym(symtab_t s, unsigned char type, char *name,
372 | unsigned long *val) {
373 | if (s->dyn && !lookup2(s->dyn, type, name, val))
374 | return 0;
375 | if (s->st && !lookup2(s->st, type, name, val))
376 | return 0;
377 | return -1;
378 | }
379 |
380 | static int lookup_func_sym(symtab_t s, char *name, unsigned long *val) {
381 | return lookup_sym(s, STT_FUNC, name, val);
382 | }
383 |
384 | int find_name(pid_t pid, const char *name, const char *libn,
385 | unsigned long *addr) {
386 | struct mm mm[1000] = {0};
387 | unsigned long libcaddr;
388 | int nmm;
389 | char libc[1024] = {0};
390 | symtab_t s;
391 |
392 | if (0 > load_memmap(pid, mm, &nmm)) {
393 | LOGD(OBFUSCATE("cannot read memory map\n"));
394 | return -1;
395 | }
396 | if (0
397 | > find_libname((char *) libn, (char *) libc, sizeof(libc),
398 | &libcaddr, mm, nmm)) {
399 | LOGD(OBFUSCATE("cannot find lib: %s\n"), libn);
400 | return -1;
401 | }
402 | //LOGD("lib: >%s<\n", libc)
403 | s = load_symtab(libc);
404 | if (!s) {
405 | LOGD(OBFUSCATE("cannot read symbol table\n"));
406 | return -1;
407 | }
408 | if (0 > lookup_func_sym(s, (char *) name, addr)) {
409 | LOGD(OBFUSCATE("cannot find function: %s\n"), name);
410 | return -1;
411 | }
412 | *addr += libcaddr;
413 | return 0;
414 | }
415 |
416 | int find_libbase(pid_t pid, const char *libn, unsigned long *addr) {
417 | struct mm mm[1000] = {0};
418 | unsigned long libcaddr;
419 | int nmm;
420 | char libc[1024] = {0};
421 | symtab_t s;
422 |
423 | if (0 > load_memmap(pid, mm, &nmm)) {
424 | LOGD(OBFUSCATE("cannot read memory map\n"));
425 | return -1;
426 | }
427 | if (0 > find_libname(libn, libc, sizeof(libc), &libcaddr, mm, nmm)) {
428 | LOGD(OBFUSCATE("cannot find lib\n"));
429 | return -1;
430 | }
431 | *addr = libcaddr;
432 | return 0;
433 | }
434 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/support/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.android.support;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.os.Build;
7 |
8 | import java.util.LinkedHashSet;
9 | import java.util.Set;
10 |
11 | public class Preferences {
12 | private static SharedPreferences sharedPreferences;
13 | private static Preferences prefsInstance;
14 | public static Context context;
15 | public static boolean loadPref, isExpanded;
16 |
17 | private static final String LENGTH = "_length";
18 | private static final String DEFAULT_STRING_VALUE = "";
19 | private static final int DEFAULT_INT_VALUE = 0; //-1
20 | private static final double DEFAULT_DOUBLE_VALUE = 0d; //-1d
21 | private static final float DEFAULT_FLOAT_VALUE = 0f; //-1f
22 | private static final long DEFAULT_LONG_VALUE = 0L; //-1L
23 | private static final boolean DEFAULT_BOOLEAN_VALUE = false;
24 |
25 | public static native void Changes(Context con, int fNum, String fName, int i, boolean bool, String str);
26 |
27 | public static void changeFeatureInt(String featureName, int featureNum, int value) {
28 | Preferences.with(context).writeInt(featureNum, value);
29 | Changes(context, featureNum, featureName, value, false, null);
30 | }
31 |
32 | public static void changeFeatureString(String featureName, int featureNum, String str) {
33 | Preferences.with(context).writeString(featureNum, str);
34 | Changes(context, featureNum, featureName, 0, false, str);
35 | }
36 |
37 | public static void changeFeatureBool(String featureName, int featureNum, boolean bool) {
38 | Preferences.with(context).writeBoolean(featureNum, bool);
39 | Changes(context, featureNum, featureName, 0, bool, null);
40 | }
41 |
42 | public static int loadPrefInt(String featureName, int featureNum) {
43 | if (loadPref) {
44 | int i = Preferences.with(context).readInt(featureNum);
45 | Changes(context, featureNum, featureName, i, false, null);
46 | return i;
47 | }
48 | return 0;
49 | }
50 |
51 | public static boolean loadPrefBool(String featureName, int featureNum, boolean bDef) {
52 | boolean bool = Preferences.with(context).readBoolean(featureNum, bDef);
53 | if (featureNum == -1) {
54 | loadPref = bool;
55 | }
56 | if (featureNum == -3) {
57 | isExpanded = bool;
58 | }
59 | if (loadPref || featureNum < 0) {
60 | bDef = bool;
61 | }
62 |
63 | Changes(context, featureNum, featureName, 0, bDef, null);
64 | return bDef;
65 | }
66 |
67 | public static String loadPrefString(String featureName, int featureNum) {
68 | if (loadPref || featureNum <= 0) {
69 | String str = Preferences.with(context).readString(featureNum);
70 | Changes(context, featureNum, featureName, 0, false, str);
71 | return str;
72 | }
73 | return "";
74 | }
75 |
76 | private Preferences(Context context) {
77 | sharedPreferences = context.getApplicationContext().getSharedPreferences(
78 | context.getPackageName() + "_preferences",
79 | Context.MODE_PRIVATE
80 | );
81 | }
82 |
83 | private Preferences(Context context, String preferencesName) {
84 | sharedPreferences = context.getApplicationContext().getSharedPreferences(
85 | preferencesName,
86 | Context.MODE_PRIVATE
87 | );
88 | }
89 |
90 | /**
91 | * @param context
92 | * @return Returns a 'Preferences' instance
93 | */
94 | public static Preferences with(Context context) {
95 | if (prefsInstance == null) {
96 | prefsInstance = new Preferences(context);
97 | }
98 | return prefsInstance;
99 | }
100 |
101 | /**
102 | * @param context
103 | * @param forceInstantiation
104 | * @return Returns a 'Preferences' instance
105 | */
106 | public static Preferences with(Context context, boolean forceInstantiation) {
107 | if (forceInstantiation) {
108 | prefsInstance = new Preferences(context);
109 | }
110 | return prefsInstance;
111 | }
112 |
113 | /**
114 | * @param context
115 | * @param preferencesName
116 | * @return Returns a 'Preferences' instance
117 | */
118 | public static Preferences with(Context context, String preferencesName) {
119 | if (prefsInstance == null) {
120 | prefsInstance = new Preferences(context, preferencesName);
121 | }
122 | return prefsInstance;
123 | }
124 |
125 | /**
126 | * @param context
127 | * @param preferencesName
128 | * @param forceInstantiation
129 | * @return Returns a 'Preferences' instance
130 | */
131 | public static Preferences with(Context context, String preferencesName,
132 | boolean forceInstantiation) {
133 | if (forceInstantiation) {
134 | prefsInstance = new Preferences(context, preferencesName);
135 | }
136 | return prefsInstance;
137 | }
138 |
139 | // String related methods
140 |
141 | /**
142 | * @param what
143 | * @return Returns the stored value of 'what'
144 | */
145 | public String readString(String what) {
146 | return sharedPreferences.getString(what, DEFAULT_STRING_VALUE);
147 | }
148 |
149 | /**
150 | * @param what
151 | * @return Returns the stored value of 'what'
152 | */
153 | public String readString(int what) {
154 | try {
155 | return sharedPreferences.getString(String.valueOf(what), DEFAULT_STRING_VALUE);
156 | } catch (java.lang.ClassCastException ex) {
157 | return "";
158 | }
159 | }
160 |
161 | /**
162 | * @param what
163 | * @param defaultString
164 | * @return Returns the stored value of 'what'
165 | */
166 | public String readString(String what, String defaultString) {
167 | return sharedPreferences.getString(what, defaultString);
168 | }
169 |
170 | /**
171 | * @param where
172 | * @param what
173 | */
174 | public void writeString(String where, String what) {
175 | sharedPreferences.edit().putString(where, what).apply();
176 | }
177 |
178 | /**
179 | * @param where
180 | * @param what
181 | */
182 | public void writeString(int where, String what) {
183 | sharedPreferences.edit().putString(String.valueOf(where), what).apply();
184 | }
185 |
186 | // int related methods
187 |
188 | /**
189 | * @param what
190 | * @return Returns the stored value of 'what'
191 | */
192 | public int readInt(String what) {
193 | return sharedPreferences.getInt(what, DEFAULT_INT_VALUE);
194 | }
195 |
196 |
197 | /**
198 | * @param what
199 | * @return Returns the stored value of 'what'
200 | */
201 | public int readInt(int what) {
202 | try {
203 | return sharedPreferences.getInt(String.valueOf(what), DEFAULT_INT_VALUE);
204 | } catch (java.lang.ClassCastException ex) {
205 | return 0;
206 | }
207 | }
208 |
209 | /**
210 | * @param what
211 | * @param defaultInt
212 | * @return Returns the stored value of 'what'
213 | */
214 | public int readInt(String what, int defaultInt) {
215 | return sharedPreferences.getInt(what, defaultInt);
216 | }
217 |
218 | /**
219 | * @param where
220 | * @param what
221 | */
222 | public void writeInt(String where, int what) {
223 | sharedPreferences.edit().putInt(where, what).apply();
224 | }
225 |
226 | /**
227 | * @param where
228 | * @param what
229 | */
230 | public void writeInt(int where, int what) {
231 | sharedPreferences.edit().putInt(String.valueOf(where), what).apply();
232 | }
233 |
234 | // double related methods
235 |
236 | /**
237 | * @param what
238 | * @return Returns the stored value of 'what'
239 | */
240 | public double readDouble(String what) {
241 | if (!contains(what))
242 | return DEFAULT_DOUBLE_VALUE;
243 | return Double.longBitsToDouble(readLong(what));
244 | }
245 |
246 | /**
247 | * @param what
248 | * @param defaultDouble
249 | * @return Returns the stored value of 'what'
250 | */
251 | public double readDouble(String what, double defaultDouble) {
252 | if (!contains(what))
253 | return defaultDouble;
254 | return Double.longBitsToDouble(readLong(what));
255 | }
256 |
257 | /**
258 | * @param where
259 | * @param what
260 | */
261 | public void writeDouble(String where, double what) {
262 | writeLong(where, Double.doubleToRawLongBits(what));
263 | }
264 |
265 | // float related methods
266 |
267 | /**
268 | * @param what
269 | * @return Returns the stored value of 'what'
270 | */
271 | public float readFloat(String what) {
272 | return sharedPreferences.getFloat(what, DEFAULT_FLOAT_VALUE);
273 | }
274 |
275 | /**
276 | * @param what
277 | * @param defaultFloat
278 | * @return Returns the stored value of 'what'
279 | */
280 | public float readFloat(String what, float defaultFloat) {
281 | return sharedPreferences.getFloat(what, defaultFloat);
282 | }
283 |
284 | /**
285 | * @param where
286 | * @param what
287 | */
288 | public void writeFloat(String where, float what) {
289 | sharedPreferences.edit().putFloat(where, what).apply();
290 | }
291 |
292 | // long related methods
293 |
294 | /**
295 | * @param what
296 | * @return Returns the stored value of 'what'
297 | */
298 | public long readLong(String what) {
299 | return sharedPreferences.getLong(what, DEFAULT_LONG_VALUE);
300 | }
301 |
302 | /**
303 | * @param what
304 | * @param defaultLong
305 | * @return Returns the stored value of 'what'
306 | */
307 | public long readLong(String what, long defaultLong) {
308 | return sharedPreferences.getLong(what, defaultLong);
309 | }
310 |
311 | /**
312 | * @param where
313 | * @param what
314 | */
315 | public void writeLong(String where, long what) {
316 | sharedPreferences.edit().putLong(where, what).apply();
317 | }
318 |
319 | // boolean related methods
320 |
321 | /**
322 | * @param what
323 | * @return Returns the stored value of 'what'
324 | */
325 | public boolean readBoolean(String what) {
326 | return sharedPreferences.getBoolean(what, DEFAULT_BOOLEAN_VALUE);
327 | }
328 |
329 | /**
330 | * @param what
331 | * @return Returns the stored value of 'what'
332 | */
333 | public boolean readBoolean(int what) {
334 | return sharedPreferences.getBoolean(String.valueOf(what), DEFAULT_BOOLEAN_VALUE);
335 | }
336 |
337 | /**
338 | * @param what
339 | * @param defaultBoolean
340 | * @return Returns the stored value of 'what'
341 | */
342 | public boolean readBoolean(String what, boolean defaultBoolean) {
343 | /*if (defaultBoolean == true && !sharedPreferences.contains(what))
344 | writeBoolean(what, true);*/
345 | return sharedPreferences.getBoolean(what, defaultBoolean);
346 | }
347 |
348 | /**
349 | * @param what
350 | * @param defaultBoolean
351 | * @return Returns the stored value of 'what'
352 | */
353 | public boolean readBoolean(int what, boolean defaultBoolean) {
354 | /*if (defaultBoolean == true && !sharedPreferences.contains(String.valueOf(what)))
355 | writeBoolean(what, true);*/
356 | try {
357 | return sharedPreferences.getBoolean(String.valueOf(what), defaultBoolean);
358 | } catch (java.lang.ClassCastException ex) {
359 | return defaultBoolean;
360 | }
361 | }
362 |
363 | /**
364 | * @param where
365 | * @param what
366 | */
367 | public void writeBoolean(String where, boolean what) {
368 | sharedPreferences.edit().putBoolean(where, what).apply();
369 | }
370 |
371 | /**
372 | * @param where
373 | * @param what
374 | */
375 | public void writeBoolean(int where, boolean what) {
376 | sharedPreferences.edit().putBoolean(String.valueOf(where), what).apply();
377 | }
378 |
379 | // String set methods
380 |
381 | /**
382 | * @param key
383 | * @param value
384 | */
385 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
386 | public void putStringSet(final String key, final Set value) {
387 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
388 | sharedPreferences.edit().putStringSet(key, value).apply();
389 | } else {
390 | // Workaround for pre-HC's lack of StringSets
391 | putOrderedStringSet(key, value);
392 | }
393 | }
394 |
395 | /**
396 | * @param key
397 | * @param value
398 | */
399 | public void putOrderedStringSet(String key, Set value) {
400 | int stringSetLength = 0;
401 | if (sharedPreferences.contains(key + LENGTH)) {
402 | // First read what the value was
403 | stringSetLength = readInt(key + LENGTH);
404 | }
405 | writeInt(key + LENGTH, value.size());
406 | int i = 0;
407 | for (String aValue : value) {
408 | writeString(key + "[" + i + "]", aValue);
409 | i++;
410 | }
411 | for (; i < stringSetLength; i++) {
412 | // Remove any remaining values
413 | remove(key + "[" + i + "]");
414 | }
415 | }
416 |
417 | /**
418 | * @param key
419 | * @param defValue
420 | * @return Returns the String Set with HoneyComb compatibility
421 | */
422 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
423 | public Set getStringSet(final String key, final Set defValue) {
424 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
425 | return sharedPreferences.getStringSet(key, defValue);
426 | } else {
427 | // Workaround for pre-HC's missing getStringSet
428 | return getOrderedStringSet(key, defValue);
429 | }
430 | }
431 |
432 | /**
433 | * @param key
434 | * @param defValue
435 | * @return Returns the ordered String Set
436 | */
437 | public Set getOrderedStringSet(String key, final Set defValue) {
438 | if (contains(key + LENGTH)) {
439 | LinkedHashSet set = new LinkedHashSet<>();
440 | int stringSetLength = readInt(key + LENGTH);
441 | if (stringSetLength >= 0) {
442 | for (int i = 0; i < stringSetLength; i++) {
443 | set.add(readString(key + "[" + i + "]"));
444 | }
445 | }
446 | return set;
447 | }
448 | return defValue;
449 | }
450 |
451 | // end related methods
452 |
453 | /**
454 | * @param key
455 | */
456 | public void remove(final String key) {
457 | if (contains(key + LENGTH)) {
458 | // Workaround for pre-HC's lack of StringSets
459 | int stringSetLength = readInt(key + LENGTH);
460 | if (stringSetLength >= 0) {
461 | sharedPreferences.edit().remove(key + LENGTH).apply();
462 | for (int i = 0; i < stringSetLength; i++) {
463 | sharedPreferences.edit().remove(key + "[" + i + "]").apply();
464 | }
465 | }
466 | }
467 | sharedPreferences.edit().remove(key).apply();
468 | }
469 |
470 | /**
471 | * @param key
472 | * @return Returns if that key exists
473 | */
474 | public boolean contains(final String key) {
475 | return sharedPreferences.contains(key);
476 | }
477 |
478 | /**
479 | * Clear all the preferences
480 | */
481 | public void clear() {
482 | sharedPreferences.edit().clear().apply();
483 | }
484 | }
--------------------------------------------------------------------------------