├── Android-Mod-Menu-master
├── FloatingModMenu.iml
├── LICENSE
├── README-MOBILE.md
├── README.md
├── app
│ ├── app.iml
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── uk
│ │ │ └── lgl
│ │ │ ├── MainActivity.java
│ │ │ ├── NativeToast.java
│ │ │ └── modmenu
│ │ │ ├── FloatingModMenuService.java
│ │ │ └── Preferences.java
│ │ ├── jni
│ │ ├── And64InlineHook
│ │ │ ├── And64InlineHook.cpp
│ │ │ ├── And64InlineHook.hpp
│ │ │ ├── LICENSE
│ │ │ └── README.md
│ │ ├── Android.mk
│ │ ├── Application.mk
│ │ ├── Includes
│ │ │ ├── Logger.h
│ │ │ ├── Utils.cpp
│ │ │ ├── Utils.h
│ │ │ └── obfuscate.h
│ │ ├── KittyMemory
│ │ │ ├── KittyMemory.cpp
│ │ │ ├── KittyMemory.h
│ │ │ ├── KittyUtils.cpp
│ │ │ ├── KittyUtils.h
│ │ │ ├── MemoryBackup.cpp
│ │ │ ├── MemoryBackup.h
│ │ │ ├── MemoryPatch.cpp
│ │ │ └── MemoryPatch.h
│ │ ├── Main.cpp
│ │ ├── Menu.h
│ │ ├── Substrate
│ │ │ ├── Buffer.hpp
│ │ │ ├── CydiaSubstrate.h
│ │ │ ├── SubstrateARM.hpp
│ │ │ ├── SubstrateDebug.cpp
│ │ │ ├── SubstrateDebug.hpp
│ │ │ ├── SubstrateHook.cpp
│ │ │ ├── SubstrateHook.h
│ │ │ ├── SubstrateLog.hpp
│ │ │ ├── SubstratePosixMemory.cpp
│ │ │ ├── SubstrateX86.hpp
│ │ │ ├── SymbolFinder.cpp
│ │ │ ├── SymbolFinder.h
│ │ │ ├── hde64.c
│ │ │ ├── hde64.h
│ │ │ └── table64.h
│ │ └── Toast.h
│ │ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
└── README.md
/Android-Mod-Menu-master/FloatingModMenu.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/README-MOBILE.md:
--------------------------------------------------------------------------------
1 | **This is for Android mobile users who do not have a PC. Floating apps or similar is recommended to read this page and working at the same time**
2 |
3 | **This is best viewed on mobile**
4 |
5 | # Quick links
6 | - [Softwares you need](#softwares-you-need)
7 | - [download/clone](#downloadclone)
8 | - [Setting up AIDE](#setting-up-aide)
9 | - [Files to work with and making changes](#files-to-work-with-and-making-changes)
10 | - [Implementing the menu to the target game](#implementing-the-menu-to-the-target-game)
11 | - [Loading lib without mod menu](#loading-lib-without-mod-menu)
12 | - [FAQ](#faq)
13 | - [Useful links](#useful-links)
14 | - [Credits/Acknowledgements](#creditsacknowledgements)
15 |
16 | # Softwares you need
17 | * Modded AIDE app. The official AIDE from Play Store will not work with this project: https://secufiles.com/nE9J/AIDE_CMODs_3.2.200108.apk
18 | * ndk.tar.gz for modded AIDE for NDK support: https://mega.nz/file/SR5i3ZhS#INbp_Yz0CJnvZH6ZTdXg15-2FA8QFYb18fiiMLODhqk
19 | * X-plore: https://play.google.com/store/apps/details?id=com.lonelycatgames.Xplore&hl=en
20 | * MT Manager. With build in Apktool and editors to modify APK file: https://bbs.binmt.cc/forum-2-1.html | Mirror link: https://secufiles.com/js6i/MT2.9.2.apk
21 | * Floating apps (optional). You can use it to read this page and working at the same time: https://play.google.com/store/apps/details?id=com.lwi.android.flappsfull&hl=en or a build-in feature by OEM
22 |
23 | # Download/Clone
24 |
25 | Go to releases page https://github.com/LGLTeam/Android-Mod-Menu/releases/ and download **Source code (zip)**
26 |
27 | To download latest commit, enable desktop mode on your browser then click **Code**, and click **Download ZIP**
28 |
29 | 
30 |
31 | # Setting up AIDE
32 |
33 | Now let's begin
34 |
35 | Firstly, we need to install NDK support for modded AIDE. Click on 3 dots on the right-corner. Click **More... - Settings**
36 |
37 | 
38 |
39 | Go to **Build & Run**, and click on **Manage native code support**.
40 |
41 | 
42 |
43 | A prompt will ask to input the path of NDK file.
44 |
45 | If you use X-plore, you can show details of the file and copy file path easly. We stored the ndk.tar.gz on an internal storage /storage/emulated/0/ndk_arm64.tar.gz
46 |
47 | 
48 |
49 | Paste it in the prompt box.
50 |
51 | 
52 |
53 | Click install and wait
54 |
55 | 
56 |
57 | After installiation, you can now use AIDE with NDK support
58 |
59 | # Opening project in AIDE
60 |
61 | On the main screen, it says **No open files**. We simply click on **No open files** to show file explorer. Navigate to the directory of the project and open **app** folder
62 |
63 | An option **Open Android app Project** will appear. Click on it to open
64 |
65 | 
66 |
67 | Now that the file explorer will look like this, means the project has been opened
68 |
69 | 
70 |
71 | Press play to compile the project whether it works or not
72 |
73 | If successful, it will ask you to install the APK. It may ask you to allow installation from unknown sources. Please allow when asked
74 |
75 | Open the app to test
76 |
77 | # Files to work with and making changes
78 |
79 | See: https://github.com/LGLTeam/Android-Mod-Menu#files-to-work-with-and-making-changes
80 |
81 | # Implementing the menu to the target game
82 |
83 | ### 1. Exporting to APK
84 |
85 | We need to compile the project into APK file
86 |
87 | Click on 3 dots icon on the corner. **More... - Project - Publish project**
88 |
89 | 
90 |
91 | This dialog will show but why is export greyed? Because you need to create your own keystore first. Click **Create keystore**
92 |
93 | 
94 |
95 | There is no need to put your organization info. Just your alias, password and name are fine. Don't forget your password!
96 |
97 | After you created your keystore, you can now export
98 |
99 | 
100 |
101 | Enter your keystore password
102 |
103 | 
104 |
105 | After that, it will tell you the APK has been experted
106 |
107 | 
108 |
109 | ### 2. Downloading standalone APK from apkcombo
110 |
111 | It is not a good idea to pull out installed APK from phone because sometimes it comes with splitted APKs, it's a dumb feature, we should use Apkcombo to download standalone APK
112 |
113 | Try to use armv7 standalone APK as possible. It support on all armv7, x86 and arm64 devices
114 |
115 | https://apkcombo.com/
116 |
117 | ### 3. Know the game's main activity
118 |
119 | We are looking for main activity. X-plore app can get main activity of the app so we will use that
120 |
121 | Click **Show**, check **App manager**.
122 |
123 | 
124 |
125 | Long press on an app and click **Show details**, then click **App** and expand **Activity**
126 |
127 | Here we can see the main activity. It's always on top
128 |
129 | 
130 |
131 | Note it down somewhere to remember it. We will explain this later
132 |
133 | ### 4. Adding dex and lib file
134 |
135 | We will use MT Manager to modify APK. Edit the files inside APK is pretty much straight forward, we do not need to decompile the whole APK to storage at all.
136 |
137 | Open the APK file. Click **View** to show its content
138 |
139 | 
140 |
141 | You will now see the content structure inside the APK
142 |
143 | 
144 |
145 | Do the same on compiled mod menu APK on the other pane
146 |
147 | We need to rename the dex on our mod menu APK to add dex into the game APK. We name it to classes2.dex since it contain only single dex. If the game have multiple dexes, like classes.dex, classes2.dex, classes3.dex, we would name it to classes4.dex. Mod menu dex must always be last
148 |
149 | 
150 |
151 | Press and hold on our dex, and click **+ Add**. This dialog will show. Enable **Auto Sign**, leave Update mode **Replace All**
152 |
153 | 
154 |
155 | Click OK, it will copy and auto sign.
156 |
157 | Copy your library file (.so file) too. Make sure to copy to the correct architecture
158 | armeabi-v7a is armeabi-v7a, arm64-v8a is arm64-v8a, and so on.
159 |
160 | PUTTING THE .SO file ON A WRONG ARCHITECTURE WILL RESULT IN A CRASH!
161 |
162 | 
163 |
164 | ### 5. Making corresponding changes and compile
165 |
166 | Ok, we go back to the main directory inside APK. You can press **..** to go back
167 |
168 | **GO TO THIS PAGE TO READ WHAT TO CHANGE:**
169 |
170 | https://github.com/LGLTeam/Android-Mod-Menu/blob/master/README.md#2-making-corresponding-changes-in-the-files
171 |
172 | **To open xml file**
173 |
174 | Open `androidmanifest.xml` directly. You may need to login if you edit `androidmanifest.xml`. It is free
175 |
176 | Choose **Decompile**. The editor opens
177 |
178 | 
179 |
180 | After you're done, save it
181 |
182 | 
183 |
184 | Update the changes to the game's APK file with auto sign on
185 |
186 | 
187 |
188 | **To open dex file**
189 |
190 | Open `classes.dex` directly, choose **Dex Editor Plus**
191 |
192 | 
193 |
194 | This dialog will show if it have multidex. **SELECT ALL** and click OK
195 |
196 | 
197 |
198 | The editor opens
199 |
200 | After you're done, save it
201 |
202 | 
203 |
204 | Go back and **save and exit**
205 |
206 | 
207 |
208 | Click OK to update the changes to the game's APK file with auto sign on
209 |
210 | 
211 |
212 | ### 6. Installing APK
213 |
214 | Go back outside APK. You will now see a green text which tells you that you have recently modified the file
215 |
216 | 
217 |
218 | Simple install it. You may need to uninstall original APK first
219 |
220 | If it works, congratulations!
221 |
222 | # Troubleshooting
223 |
224 | Problem with the project: click **More... - Project - Refresh Build**. This will clear the project cache
225 |
226 | Problem with AIDE: Open System Settings - Apps and clear data of AIDE app. This will reset everything and you need to install NDK again
227 |
228 | # Loading lib without mod menu
229 |
230 | See: https://github.com/LGLTeam/Android-Mod-Menu#loading-lib-without-mod-menu
231 |
232 | # FAQ
233 |
234 | See: https://github.com/LGLTeam/Android-Mod-Menu#faq
235 |
236 | # Credits/Acknowledgements
237 |
238 | * RANUAK MODS for some help in modding via phone
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/README.md:
--------------------------------------------------------------------------------
1 | **THIS TEMPLATE IS NOT FOR NEWBIES/NOOBS, IT IS FOR EXPERIENCE MODDERS AND PROGRAMMERS ONLY. YOU WILL BE EXPECTED TO READ, LEARN AND EVEN GOOGLE. THIS IS NOT A SIMPLE ONE-CLICK INSTALL SETUP. IF YOU DON'T HAVE THE KNOWLEDGE, THIS TUTORIAL WILL BE TOO HARD FOR YOU**
2 |
3 | **IF YOU ARE UPDATING THIS TEMPLATE, PLEASE CLONE IT SEPARATELY. DO NOT MERGE INTO OLD ONE UNLESS YOU KNOW WHAT YOU ARE DOING!**
4 |
5 | **This won't cover how to mod games in general, hooking functions, etc that every other online tutorial already covers, so don't ask since I won't cover them. The codes in the template simply tells you how to use them**
6 |
7 | **For mobile users who don't have a PC, please read [README-MOBILE.md](https://github.com/LGLTeam/Android-Mod-Menu/blob/master/README-MOBILE.md) how to use this project within AIDE app**
8 |
9 | # Quick links
10 | - [Prerequisites](#prerequisites)
11 | - [Softwares you need](#softwares-you-need)
12 | - [download/clone](#downloadclone)
13 | - [Setting up Android Studio](#setting-up-android-studio)
14 | - [Open the project](#open-the-project)
15 | - [Files to work with and making changes](#files-to-work-with-and-making-changes)
16 | - [Implementing the menu to the target game](#implementing-the-menu-to-the-target-game)
17 | - [Loading lib without mod menu](#loading-lib-without-mod-menu)
18 | - [FAQ](#faq)
19 | - [Credits/Acknowledgements](#creditsacknowledgements)
20 |
21 | # Introduction
22 | Floating mod menu for il2cpp and other native android games. KittyMemory, MSHook, and And64InlineHook included. This template is optimized for modders who want the faster way to implement the menu in the game without hassle. Assets are stored as base64 in cpp and does not need to be stored under assets folder.
23 |
24 | It comes with string and offset obfuscation without using any external tool and without modifying the compiler. We use AY Obfuscator
25 |
26 | Support Android 4.4.x way up to Android R. Support ARMv7, x86 and ARM64 architecture. However x86 is deprecated for Unity games so x86 is not our priority
27 |
28 | Mod menu is based on Octowolve/Escanor and Van's template.
29 |
30 | Preview:
31 |
32 | 
33 |
34 | # Prerequisites
35 | * **AN EXPERIENCED MODDER, NOT A NEWBIE/BEGINNER MODDER:** You should be able to mod any games in general (does not need to be a protected games), like modifying .so files, dll files, smali files, etc.
36 | * Basic knowledge of smali dalvik opcodes and ARM and ARM64 assembly (x86 not needed), required for patching meemory
37 | * Be able to hook function in C++ (Not really needed, but recommended if you want to do advanced modding in the future)
38 | * Basic knowledge of C++ and java
39 | * Basic awareness of how Android layout works in XML and Java. This project only uses Java for layout but you will learn it easly
40 | * Time and patience: Don't start working on this if you have deadlines or important work, only on your free time. Take your time to read, learn and get used to work with this project.
41 | * DIY (Do it yourself): Yes, you must be able to do things yourself. If we can't or won't implement some certain features, try to implement yourself. We are not the teachers, it is not our style, so don't ask us to teach or spoonfeed.
42 | * An inquisitive mind
43 |
44 | # Softwares you need
45 | * Android Studio 4 and up: https://developer.android.com/studio
46 | * Apktool: [Apktool.jar](https://ibotpeaches.github.io/Apktool/) or any 3rd party tools
47 | * APK Easy Tool. To get main activity: https://forum.xda-developers.com/android/software-hacking/tool-apk-easy-tool-v1-02-windows-gui-t3333960
48 | * Any text editor. I use [Notepad++](https://notepad-plus-plus.org/downloads/)
49 | * Any png compression to compress your png file: https://compresspng.com/
50 | * Any base64 encoding to encode your file: https://www.base64encode.org/
51 |
52 | # Download/Clone
53 | Click on the button that says Code, and click Download ZIP
54 |
55 | 
56 |
57 | Or clone through Android Studio if you know how to use Git
58 |
59 | # Setting up Android Studio
60 |
61 | ### 1. Installing NDK
62 |
63 | At the bottom-right corner, click on Configure and SDK Manager
64 |
65 | 
66 |
67 | Select **Android SDK**, check **NDK (Side by side)** and click OK. It will download and install
68 |
69 | 
70 |
71 | ### 2. Open the project
72 |
73 | Extract the template project to the folder without any spaces. If any folder has spaces, it will cause problem
74 |
75 | On the welcome screen, choose **"Open an existing Android Studio project"**
76 |
77 | Navigate to the extracted project and open it
78 |
79 | 
80 |
81 | It will index and Gradle will sync the project fir the first time. Please wait for a while, it will take around 5 minutes depending your computer performance
82 |
83 | If you encounter an error
84 |
85 | ```NDK not configured. Download it with SDK manager. Preferred NDK version is 'xx.x.xxxxxx'```
86 |
87 | Click File and Project Structure
88 |
89 | 
90 |
91 | Select default NDK version
92 |
93 | 
94 |
95 | After it's done, you can start working!
96 |
97 | # Files to work with and making changes
98 |
99 | ### Java
100 |
101 | **`MainActivity.java`**:
102 | You pretty don't need to work with it unless you are implementing something like login layout.
103 |
104 | Static method `Start()` and `LoadLibOnly()` can be called from game's `OnCreate`. `Start()` checks if device running Android 6.0 or above and if have overlay permission checked before starting menu service.
105 |
106 | **`modmenu/Preferences.java`**: Saving the menu feature preferences and calling changes via JNI
107 |
108 | **`modmenu/FloatingModMenuService.java`**: Main codes of mod menu design
109 |
110 | The codes of floating mod menu. You don't need to change much unless you want to redesign it. The codes are explained in the comments
111 |
112 | Note: In the `run()` handler method inside `initFloating()`, there is a code that checks if game lib is loaded or not before loading feature lists. If you are running the app as debug and want to test preferences, comment the if-else code out except feature list thing. Otherwise it would get stuck without a game
113 |
114 | - `GradientDrawable`
115 |
116 | A code for setting corner and stroke/inner border. Works for any View Components
117 | ```
118 | GradientDrawable gradientdrawable = new GradientDrawable();
119 | gradientdrawable.setCornerRadius(20); //Set corner
120 | gradientdrawable.setColor(Color.parseColor("#1C2A35")); //Set background color
121 | gradientdrawable.setStroke(1, Color.parseColor("#32cb00")); //Set border
122 | ```
123 |
124 | Set the gradient drawable to the view component
125 |
126 | ```
127 | [name of your view component].setBackground(gradientdrawable);
128 | ```
129 |
130 | - Resizing menu box
131 |
132 | I have added variables so you can find it easly to resize
133 | ```
134 | private final int MENU_WIDTH = 290;
135 | private final int MENU_HEIGHT = 200;
136 | ```
137 |
138 | Note: You may need to implement auto sizing due to many types of phone with different DPIs and resolutions
139 |
140 | - Color Animation: The codes can be seen in `startAnimation()`
141 |
142 | - Adding new view
143 |
144 | Normally the Android development documentation does not explain the code in java. If you read the Android development documentation and you see an example like TextView
145 |
146 | ```
147 | TextView textView = (TextView) findViewById(R.id.textView);
148 | textView.setFontVariationSettings("'wdth' 150");
149 | ```
150 |
151 | This is for xml. Instead, create an instance for java and add view to your Layout
152 |
153 | ```
154 | TextView textView = new TextView(this);
155 | textView.setFontVariationSettings("'wdth' 150");
156 | LinearLayoutExample.addView(textView);
157 |
158 | ```
159 |
160 | There are many more. While we can't explain much here, you can use Google. Search like `create a textview programmatically android`, `create a button programmatically android` etc for more infomation
161 |
162 | ### Cpp
163 |
164 | - **`Menu.h`**: Menu related with JNI calls
165 |
166 | - `Title`: Big text
167 |
168 | - `Heading`: Little text. Semi HTML is supported. Text will scroll if the text is too long
169 |
170 | - `Icon`: Compressed image that is encoded to base64
171 |
172 | - `IconWebViewData`: Use icon in Web view with GIF animation support. URL requires internet permission `android.permission.INTERNET`
173 |
174 | Examples
175 |
176 | ```From internet: (Requires android.permission.INTERNET)
177 | return env->NewStringUTF("https://i.imgur.com/SujJ85j.gif");
178 |
179 | From assets folder: (Requires android.permission.INTERNET)
180 | return env->NewStringUTF("file:///android_asset/example.gif");
181 |
182 | Base64 html:
183 | return env->NewStringUTF("data:image/png;base64, ");
184 |
185 | Nothing:
186 | return NULL
187 | ```
188 |
189 | **`Toast.h`**: Your toast
190 |
191 | **`Main.cpp`**: In this file, you will work with your mods here
192 |
193 | - `Changes`: Get values to apply mods. BE CAREFUL NOT TO ACCIDENTLY REMOVE break;
194 |
195 | You can also use if-else statement with string comparision
196 |
197 | ```
198 | if (strcmp(featureName, "The button") == 0) { //Compare with string
199 |
200 | } else if (strcmp(featureName, "The On/Off button") == 0) { //Compare with string
201 |
202 | } else if (feature == 7) {
203 |
204 | }
205 | ```
206 | - `getFeatureList`: Mod features
207 |
208 | Usage:
209 |
210 | ```
211 | Category_(text)
212 | Toggle_(feature name)
213 | SeekBar_(feature name)_(min value)_(max value)
214 | Spinner_(feature name)_(Items e.g. item1,item2,item3)
215 | Button_(feature name)
216 | ButtonLink_(feature name)_(URL/Link here)
217 | ButtonOnOff_(feature name)
218 | InputValue_(feature name)
219 | CheckBox_(feature name)
220 | RadioButton_(feature name)_(Items e.g. radio1,radio2,radio3)
221 | RichTextView_(Text with limited HTML support)
222 | RichWebView_(Full HTML support)
223 | ```
224 |
225 | Examples:
226 |
227 | ```Toggle_God mode
228 | Spinner_Weapons_AK47,9mm,Knife
229 | Button_OnOff_God mode
230 | ```
231 |
232 | Learn more about HTML https://www.w3schools.com/
233 |
234 | - `hack_thread`: Here you add your code for hacking with KittyMemory or Hooking. We will not teach, you must have learned it already
235 |
236 | KittyMemory usage:
237 | ```MemoryPatch::createWithHex([Lib Name], [offset], "[hex. With or without spaces]");
238 | [Struct].get_CurrBytes().Modify();
239 | [Struct].get_CurrBytes().Restore();
240 |
241 | [Struct].get_TargetAddress();
242 | [Struct].get_PatchSize();
243 | [Struct].get_CurrBytes().c_str();
244 | ```
245 |
246 | Example: https://github.com/MJx0/KittyMemory/blob/master/Android/test/src/main.cpp
247 |
248 | Hook usage:
249 | ARM64:
250 | ```A64HookFunction((void *) getAbsoluteAddress([Lib Name], [offset]), (void *)[function], (void **)&[old function]);```
251 |
252 | ARMv7/x86:
253 | ```MSHookFunction((void *) getAbsoluteAddress([Lib Name], [offset]), (void *)[function], (void **)&[old function]);```
254 |
255 | **`Android.mk`**
256 |
257 | The make file for the c++ compiler. In that file, you can change the lib name on the `LOCAL_MODULE` line
258 | When you change the lib name, change also on `System.loadLibrary("")` under OnCreate method on FloatingModMenuService.java
259 | Both must have same name
260 |
261 | **C++ string obfuscation**
262 |
263 | We use AY Obfuscator but the usage has changed to `OBFUSCATE("string here")` and `OBFUSCATE_KEY("string here", 'single letter here')`
264 |
265 | Example
266 | ```
267 | OBFUSCATE("Hello world")
268 | OBFUSCATE_KEY("Hello world", 'a')
269 | OBFUSCATE_KEY("Hello world", 'u')
270 | ```
271 |
272 | ### Others
273 |
274 | **`proguard-rules.pro`**
275 |
276 | See proguard rules here https://www.guardsquare.com/en/products/proguard/manual/usage
277 |
278 | Both `shrinkResources` and `minifyEnabled` MUST be `true` in `build.gradle (:app)` in order to enable proguard obfuscation
279 |
280 | `public static void Start` has been prevented from renaming
281 |
282 | Add `-dontobfuscate` to disable obfuscation
283 |
284 | **Encoding your files into base64**
285 |
286 | You can pretty much use any tools for base64 encoding.
287 |
288 | We use a simple website https://www.base64encode.org/
289 |
290 | Scroll down till you see `Encode files into Base64 format`. Click or tap on the box to select a file
291 |
292 | Click on `ENCODE` button and click on `CLICK OR TAP HERE` to download your encoded file. Now you can paste it in your code
293 |
294 | # Testing
295 |
296 | Connect your device to computer or run your emulator. Make sure you have USB-Debugging enabled in the developer option of your device. Android Studio will detect and you can click Play to run your app.
297 |
298 | 
299 |
300 | Sometimes emulators such as NOX or MEMU fail to connect to adb automatically, in order to connect them, simply reboot the emulator.
301 |
302 | On Android 4.2 and higher, the Developer options screen is hidden by default. To make it visible, go to **Settings** > **About phone** and tap Build number seven times. Return to the previous screen to find Developer options at the bottom.
303 |
304 | On some devices, the Developer options screen might be located or named differently.
305 |
306 | # Implementing the menu to the target game
307 |
308 | ### 1. Know your game's main activity
309 |
310 | Now we are looking for main activity, there are 2 ways to do
311 |
312 | 1. Decompile the game's APK file. Open `androidmanifest.xml` and search after ``.
313 |
314 | Example the game's main activity was `com.unity3d.player.UnityPlayerActivity`
315 |
316 | 
317 |
318 | Be sure to enable Word wrap so it is easier to read
319 |
320 | 
321 |
322 | 2. APK Easy Tool since it can read out location of main activity without decompiling APK
323 |
324 | 
325 |
326 | Note it somewhere so you can easly remember it
327 |
328 | ### 2. Making corresponding changes in the files
329 |
330 | Decompile the game APK
331 |
332 | Open the game's `androidmanifest.xml`
333 |
334 | Add the `SYSTEM_ALERT_WINDOW` permission besides other permissions if it doesn't exist. We only need one permission. Doesn't matter where you place it as long as it's above the application tag
335 | ```
336 |
337 | ```
338 |
339 | 
340 |
341 | Add the service above the end of application tag (change the package name of your menu if you had changed it)
342 | ```
343 |
344 | ```
345 |
346 | 
347 |
348 | Now we need to call your mod menu activity
349 |
350 | There are 2 ways to call your mod menu activity. Choose one of them you like to try. Don't know? just choose METHOD 1
351 |
352 | **METHOD 1**
353 |
354 | This simple way, we will call to `MainActivity.java`. `MainActivity.java` will never be used
355 |
356 | Locate to the game's path of main activity and open the **smali** file. If the game have multi dexes, it may be located in smali_classes2.. please check all
357 |
358 | With the path of the target game’s main activity which we determined earlier `com.unity3d.player.UnityPlayerActivity`. Think of it like a path `/com/unity3d/player/UnityPlayerActivity.smali`
359 |
360 | Open the main acitivity's smali file, search for OnCreate method and paste this code inside (change the package name if you had changed it)
361 | ```
362 | invoke-static {p0}, Luk/lgl/MainActivity;->Start(Landroid/content/Context;)V
363 | ```
364 |
365 | 
366 |
367 | Save the file
368 |
369 | **METHOD 2**
370 |
371 | You can follow this it if the first method really fails, or if you really want to use `MainActivity.java` for a reason. Since this involve changing activites, it may cause some problems.
372 |
373 | On your `MainActivity.java`, put the game's main activity to `public String GameActivity`
374 |
375 | 
376 |
377 | Uncomment this code
378 |
379 | ```
380 | Toast.makeText(MainActivity.this, "Error. Game's main activity does not exist", Toast.LENGTH_LONG).show();
381 | ```
382 |
383 | On `androidmanifest.xml`, remove `` from the game's activity, like this:
384 |
385 | 
386 |
387 | If you don't remove `` from the game's activity, your menu will not launch. `androidmanifest.xml` can ONLY contain one ``
388 |
389 | near the end of application tag ``, add your main activity above it. `uk.lgl.MainActivity` is your main activity
390 |
391 | ```xml
392 |
393 |
394 |
395 |
396 |
397 |
398 | ```
399 |
400 | 
401 |
402 | Save the file
403 |
404 | _Do NOT use both methods at the same time_
405 |
406 | ### 3. Building your project and copying files
407 |
408 | Build the project to the APK file.
409 | **Build** -> **Build Bundle(s)/APK(s)** -> **Build APK(s)**
410 |
411 | If no errors occured, you did everything right and build will succeded. You will be notified that it build successfully
412 |
413 | 
414 |
415 | Click on **locate** to show you the location of **build.apk**. It is stored at `(your-project)\app\build\outputs\apk\app-debug.apk`
416 |
417 | 
418 |
419 | Decompile your **app-debug.apk**.
420 |
421 | Copy your mod menu from decompiled app-debug.apk smali to the game's smali folder. Example ours is uk.lgl.modmenu, we copy the `uk` folder from **app-debug** `(app-debug\smali\uk)` to the game's decompiled directory `(game name)\smali`
422 |
423 | 
424 |
425 | If the game have multidexes, just add your smali to the last `smali_classes` if possible to prevent compilation errors such as `Unsigned short value out of range: xxxxx` (Smali limit error)
426 |
427 | Copy the library file (.so) from **app-debug.apk** to the target game. Make sure to copy .so to the correct architecture
428 | armeabi-v7a is armeabi-v7a, arm64-v8a is arm64-v8a, and so on.
429 |
430 | PUTTING THE .SO file ON A WRONG ARCHITECTURE WILL RESULT A CRASH!
431 |
432 | 
433 |
434 | ### 4. Compiling game apk
435 |
436 | Now compile and sign the apk, and install it on your device
437 |
438 | Congrats. You have successfully implemented a mod menu.
439 |
440 | Compile failed? read the log and look up on Google
441 |
442 | If you face any problem, please read the [FAQ](#faq)
443 |
444 | # Loading lib without mod menu
445 |
446 | Just call the `LoadLibOnly` in the `OnCreate` method if you want to load your hacks without mod menu
447 | ```
448 | invoke-static {p0}, Luk/lgl/MainActivity;->LoadLibOnly(Landroid/content/Context;)V
449 | ```
450 |
451 | Make sure to delete `modmenu` folder from the smali to avoid reaching the method limit of the smali classes (limit is 65535)
452 |
453 | # FAQ
454 | ## My game crashing or freezing/My mod menu does not work
455 | There are many reasons why, it could be your code fault, wrong offsets, bad c++ code, bad layout implementations, game protections etc.
456 |
457 | First of all, check logcat on Android Studio to see the error logs. Connect your device/reboot emulator to reconnect, open **Logcat** window from below, and select your device, process and filter to **Error** and reproduce your problem. Once you do, you can see the errors in logcat
458 |
459 | 
460 |
461 | Then search the error on Google. Contact me or report issues if you can't find the answers
462 |
463 | If the game crashes or freezing while playing, check if your patches and hooks are correct. For hooks, write down the logs such as `LOGD("whatever");` like this below:
464 |
465 | ```
466 | bool get_BoolExample(void *instance) {
467 | LOGD("BoolExample 1");
468 | if (instance != NULL && featureHookToggle) {
469 | LOGD("BoolExample 2");
470 | return true;
471 | }
472 | LOGD("BoolExample 3");
473 | return old_get_BoolExample(instance);
474 | }
475 | ```
476 |
477 | Recompile and check the logcat, to see what part of your code faced the problem.
478 |
479 | Logcat may also report `CRASH` if lib crashed, caused by hooking
480 |
481 | See more about logcat: https://developer.android.com/studio/debug/am-logcat
482 |
483 | If you believe the game has protection, try recompile APK without mod and install to see if it crash. We can't help you bypassing protections
484 |
485 | ### I have a problem decompiling or compiling APK file
486 | Check if apk is not protected. If not, search for the related issues on Google or on Apktool Github page: https://github.com/iBotPeaches/Apktool/issues
487 |
488 | ### I'm getting an error `Unsigned short value out of range: 65536` if I compile
489 | The method index can't fit into an unsigned 16-bit value, means you have too many methods in the smali due to the limit 65535. Place your code on other classes, such as smali_classes2 instead. This work for Android 5 (Lollipop) and above only.
490 |
491 | ### I'm getting an error `ERROR: executing external native build for ndkBuild Android.mk. Affected Modules: app`
492 | See: https://github.com/LGLTeam/Android-Studio-Solutions/wiki/Executing-external-native-build-for-ndkBuild-Android.mk
493 |
494 | ### I'm getting strange issues on Android Studio or Gradle
495 | See: https://github.com/LGLTeam/Android-Studio-Solutions/wiki
496 |
497 | ### How to add colored text on JNI toast?
498 | It is not implemented yet, and we don't have enough knowledge in JNI porting to do this
499 |
500 | But it is deprecated in API level 30/Android 11, means custom toast will not work, so we will not implement it
501 |
502 | See: https://developer.android.com/reference/android/widget/Toast#getView()
503 |
504 | ### How can I protect my dex and/or lib?
505 |
506 | We will not mention their names, but you can search for that on Github. Using chinese tools may inject malwares and spywares in APK. We highly suggest to not use them, and please don't ask us.
507 |
508 | There is no need to protect dex since there are nothing important in java/smali codes. All the important codes such as offsets are in the lib file and they are protected enough
509 |
510 | ### How to get older version of the template? or how to see updates/commits?
511 |
512 | Go to the commit page https://github.com/LGLTeam/Android-Mod-Menu/commits/master
513 |
514 | ### Can I compile this project on Android using AIDE?
515 |
516 | Likely yes and no, but we don't support AIDE at this time
517 |
518 | ### How can I соntact you?
519 | You can соntact me via Tеlеgram or Disсоrd.
520 |
521 |
522 | Contact:
523 | Before you contact, please make sure you have readed everything and looking on Google before contacting
524 |
525 | Newbies who do not understand anything must NOT соntact. You will be BLOCKED if you ask/beg to teach/spoonfeed. Why? Because we have gotten so many newbie kids who wouldn't know nothing about modding but attempt to try this for nothing, and come to me and begging and spamming for help. We are getting tired of this now. DON'T be that toxic kid please
526 |
527 | Speak english only please. Speaking in other language will be ignored
528 |
529 | Thanks!
530 |
531 | Tеlеgram: @ThеᒪGᒪ
532 |
533 | Disсоrd: ᒪGᒪ#6844
534 |
535 |
536 | ### Can you help me mod (name of game)?
537 |
538 | Noob, we are not spoonfeeding. Don't соntact if you don't know how to mod games.
539 |
540 | Instead, try to find a couple of tutorials to learn and mod the game yourself. It's a lot easier than you think. If you can't, search on the internet and you should find a couple of forums where you can ask your questions.
541 |
542 | ### Do you have project of someones mod menu including game codes for example MITO Team mod?
543 |
544 | No, because they used this template and they created their own mod with it, we don't support nor work with them. Ask the right owner who have them, example if mod is created by MITO Team, ask MITO Team. We are the wrong persons to ask.
545 |
546 | ### Where can I learn hooking?
547 |
548 | * https://piin.dev/basic-hooking-tutorial-t19.html
549 | * https://iosgods.com/topic/65529-instance-variables-and-function-pointers/
550 | * https://guidedhacking.com/threads/android-function-pointers-hooking-template-tutorial.14771/
551 | * http://www.cydiasubstrate.com/api/c/MSHookFunction/
552 | * https://www.cprogramming.com/tutorial/function-pointers.html
553 |
554 | # Credits/Acknowledgements
555 | Thanks to the following individuals whose code helped me develop this mod menu
556 |
557 | * Octowolve/Escanor - Mod menu: https://github.com/z3r0Sec/Substrate-Template-With-Mod-Menu and Hooking: https://github.com/z3r0Sec/Substrate-Hooking-Example
558 | * VanHoevenTR - Mod menu - https://github.com/LGLTeam/VanHoevenTR_Android_Mod_Menu
559 | * MrIkso - First mod menu template https://github.com/MrIkso/FloatingModMenu
560 | * MJx0 A.K.A Ruit - https://github.com/MJx0/KittyMemory
561 | * Rprop - https://github.com/Rprop/And64InlineHook
562 | * Some modders for suggestions and ideas :)
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | generateDebugSources
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 30
5 | defaultConfig {
6 | applicationId "uk.lgl.modmenu"
7 | minSdkVersion 19
8 | targetSdkVersion 30
9 | versionCode 1
10 | versionName "1.9"
11 | ndk {
12 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
13 | }
14 | signingConfig signingConfigs.debug
15 | }
16 | buildTypes {
17 | release {
18 | shrinkResources false
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | debug {
23 | shrinkResources false
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | externalNativeBuild {
29 | ndkBuild {
30 | path file('src/main/jni/Android.mk')
31 | }
32 | }
33 | ndkVersion = '22.0.7026061'
34 | dependencies {
35 | implementation fileTree(dir: 'libs', include: ['*.jar'])
36 | }
37 | }
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/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 uk.lgl.MainActivity
27 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/java/uk/lgl/MainActivity.java:
--------------------------------------------------------------------------------
1 | package uk.lgl;
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.Bundle;
9 | import android.os.Handler;
10 | import android.provider.Settings;
11 | import android.widget.Toast;
12 |
13 | import uk.lgl.modmenu.FloatingModMenuService;
14 | import uk.lgl.modmenu.Preferences;
15 |
16 | public class MainActivity extends Activity {
17 |
18 | public String GameActivity = "com.unity3d.player.UnityPlayerActivity";
19 |
20 | //Load lib
21 | static {
22 | // When you change the lib name, change also on Android.mk file
23 | // Both must have same name
24 | System.loadLibrary("HollowMade");
25 | }
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | Preferences.context = this;
31 | //To launch mod menu
32 | Start(this);
33 |
34 | //To load lib only
35 | //LoadLib(this);
36 |
37 | //To launch game activity
38 | try {
39 | //Start service
40 | MainActivity.this.startActivity(new Intent(MainActivity.this, Class.forName(MainActivity.this.GameActivity)));
41 | } catch (ClassNotFoundException e) {
42 | //Uncomment this if you are following METHOD 2 of CHANGING FILES
43 | //Toast.makeText(MainActivity.this, "Error. Game's main activity does not exist", Toast.LENGTH_LONG).show();
44 | e.printStackTrace();
45 | return;
46 | }
47 | }
48 |
49 | //Load mod menu
50 | public static void Start(final Context context) {
51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) {
52 | Toast.makeText(context, "Overlay permission is required in order to show mod menu", Toast.LENGTH_LONG).show();
53 | Toast.makeText(context, "Restart the game after you allow permission", Toast.LENGTH_LONG).show();
54 | context.startActivity(new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION",
55 | Uri.parse("package:" + context.getPackageName())));
56 | } else {
57 | final Handler handler = new Handler();
58 | handler.postDelayed(new Runnable() {
59 | @Override
60 | public void run() {
61 | context.startService(new Intent(context, FloatingModMenuService.class));
62 | }
63 | }, 500);
64 | }
65 | }
66 |
67 | //Call toast only without mod menu
68 | public static void LoadLibOnly(final Context context) {
69 | new Handler().postDelayed(new Runnable() {
70 | public void run() {
71 | NativeToast.makeText(context.getApplicationContext(), 0);
72 | }
73 | }, 500);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/java/uk/lgl/NativeToast.java:
--------------------------------------------------------------------------------
1 | package uk.lgl;
2 |
3 | import android.content.Context;
4 |
5 | public class NativeToast {
6 | public static native void Toast(Context context, int numOfMessage);
7 |
8 | public static void makeText(final Context context, int numOfMessage) {
9 | Toast(context, numOfMessage);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/java/uk/lgl/modmenu/Preferences.java:
--------------------------------------------------------------------------------
1 | package uk.lgl.modmenu;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.util.Log;
6 |
7 | //TODO
8 | //Write up android logcat on readme
9 |
10 | public class Preferences {
11 | private static SharedPreferences.Editor editor;
12 | public static Context context;
13 | public static boolean savePref = false, animation = false, expanded = false;
14 |
15 | public static native void Changes(Context context, int feature, int value, boolean bool, String str);
16 |
17 | public static void changeFeatureInt(String feature, int featureNum, int value) {
18 | Changes(context, featureNum, value, false, feature);
19 | editor.putInt(String.valueOf(featureNum), value).apply();
20 | }
21 |
22 | public static void changeFeatureBoolean(String feature, int featureNum, boolean value) {
23 | if (featureNum == 1001)
24 | animation = value;
25 | if (featureNum == 1002)
26 | expanded = value;
27 | if (featureNum == 9998)
28 | savePref = value;
29 | Changes(context, featureNum, 0, value, feature);
30 | editor.putBoolean(String.valueOf(featureNum), value).apply();
31 | }
32 |
33 | //TODO: changeFeatureString
34 |
35 | public static int loadPrefInt(String featureName, int featureNum) {
36 | if (savePref) {
37 | SharedPreferences preferences = context.getSharedPreferences("mod_menu", 0);
38 | editor = preferences.edit();
39 | int i = preferences.getInt(String.valueOf(featureNum), 0);
40 | Changes(context, featureNum, i, false, featureName);
41 | return i;
42 | }
43 | return 0;
44 | }
45 |
46 | public static boolean loadPrefBoolean(String featureName, int featureNum) {
47 | SharedPreferences preferences = context.getSharedPreferences("mod_menu", 0);
48 | if (featureNum >= 9998) {
49 | savePref = preferences.getBoolean(String.valueOf(featureNum), false);
50 | }
51 | if (savePref || featureNum >= 1000) {
52 | editor = preferences.edit();
53 | //if (featureNum == 1001 && !preferences.contains("1001"))
54 | // return true;
55 | boolean bool = preferences.getBoolean(String.valueOf(featureNum), false);
56 | Changes(context, featureNum, 0, bool, featureName);
57 | return bool;
58 | }
59 | return false;
60 | }
61 | }
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/And64InlineHook/And64InlineHook.cpp:
--------------------------------------------------------------------------------
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 | #define __STDC_FORMAT_MACROS
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #if defined(__aarch64__)
39 |
40 | #include "And64InlineHook.hpp"
41 |
42 | #define A64_MAX_INSTRUCTIONS 5
43 | #define A64_MAX_REFERENCES (A64_MAX_INSTRUCTIONS * 2)
44 | #define A64_NOP 0xd503201fu
45 | #define A64_JNIEXPORT __attribute__((visibility("default")))
46 | #define A64_LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "A64_HOOK", __VA_ARGS__))
47 | #ifndef NDEBUG
48 | # define A64_LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "A64_HOOK", __VA_ARGS__))
49 | #else
50 | # define A64_LOGI(...) ((void)0)
51 | #endif // NDEBUG
52 | typedef uint32_t *__restrict *__restrict instruction;
53 | typedef struct {
54 | struct fix_info {
55 | uint32_t *bp;
56 | uint32_t ls; // left-shift counts
57 | uint32_t ad; // & operand
58 | };
59 | struct insns_info {
60 | union {
61 | uint64_t insu;
62 | int64_t ins;
63 | void *insp;
64 | };
65 | fix_info fmap[A64_MAX_REFERENCES];
66 | };
67 | int64_t basep;
68 | int64_t endp;
69 | insns_info dat[A64_MAX_INSTRUCTIONS];
70 |
71 | public:
72 | inline bool is_in_fixing_range(const int64_t absolute_addr) {
73 | return absolute_addr >= this->basep && absolute_addr < this->endp;
74 | }
75 |
76 | inline intptr_t get_ref_ins_index(const int64_t absolute_addr) {
77 | return static_cast((absolute_addr - this->basep) / sizeof(uint32_t));
78 | }
79 |
80 | inline intptr_t get_and_set_current_index(uint32_t *__restrict inp, uint32_t *__restrict outp) {
81 | intptr_t current_idx = this->get_ref_ins_index(reinterpret_cast(inp));
82 | this->dat[current_idx].insp = outp;
83 | return current_idx;
84 | }
85 |
86 | inline void reset_current_ins(const intptr_t idx, uint32_t *__restrict outp) {
87 | this->dat[idx].insp = outp;
88 | }
89 |
90 | void
91 | insert_fix_map(const intptr_t idx, uint32_t *bp, uint32_t ls = 0u, uint32_t ad = 0xffffffffu) {
92 | for (auto &f : this->dat[idx].fmap) {
93 | if (f.bp == NULL) {
94 | f.bp = bp;
95 | f.ls = ls;
96 | f.ad = ad;
97 | return;
98 | } //if
99 | }
100 | // What? GGing..
101 | }
102 |
103 | void process_fix_map(const intptr_t idx) {
104 | for (auto &f : this->dat[idx].fmap) {
105 | if (f.bp == NULL) break;
106 | *(f.bp) = *(f.bp) |
107 | (((int32_t(this->dat[idx].ins - reinterpret_cast(f.bp)) >> 2)
108 | << f.ls) & f.ad);
109 | f.bp = NULL;
110 | }
111 | }
112 | } context;
113 |
114 | //-------------------------------------------------------------------------
115 |
116 | static bool __fix_branch_imm(instruction inpp, instruction outpp, context *ctxp) {
117 | static constexpr uint32_t mbits = 6u;
118 | static constexpr uint32_t mask = 0xfc000000u; // 0b11111100000000000000000000000000
119 | static constexpr uint32_t rmask = 0x03ffffffu; // 0b00000011111111111111111111111111
120 | static constexpr uint32_t op_b = 0x14000000u; // "b" ADDR_PCREL26
121 | static constexpr uint32_t op_bl = 0x94000000u; // "bl" ADDR_PCREL26
122 |
123 | const uint32_t ins = *(*inpp);
124 | const uint32_t opc = ins & mask;
125 | switch (opc) {
126 | case op_b:
127 | case op_bl: {
128 | intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp);
129 | int64_t absolute_addr = reinterpret_cast(*inpp) +
130 | (static_cast(ins << mbits)
131 | >> (mbits - 2u)); // sign-extended
132 | int64_t new_pc_offset =
133 | static_cast(absolute_addr - reinterpret_cast(*outpp))
134 | >> 2; // shifted
135 | bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr);
136 | // whether the branch should be converted to absolute jump
137 | if (!special_fix_type && llabs(new_pc_offset) >= (rmask >> 1)) {
138 | bool b_aligned = (reinterpret_cast(*outpp + 2) & 7u) == 0u;
139 | if (opc == op_b) {
140 | if (b_aligned != true) {
141 | (*outpp)[0] = A64_NOP;
142 | ctxp->reset_current_ins(current_idx, ++(*outpp));
143 | } //if
144 | (*outpp)[0] = 0x58000051u; // LDR X17, #0x8
145 | (*outpp)[1] = 0xd61f0220u; // BR X17
146 | memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr));
147 | *outpp += 4;
148 | } else {
149 | if (b_aligned == true) {
150 | (*outpp)[0] = A64_NOP;
151 | ctxp->reset_current_ins(current_idx, ++(*outpp));
152 | } //if
153 | (*outpp)[0] = 0x58000071u; // LDR X17, #12
154 | (*outpp)[1] = 0x1000009eu; // ADR X30, #16
155 | (*outpp)[2] = 0xd61f0220u; // BR X17
156 | memcpy(*outpp + 3, &absolute_addr, sizeof(absolute_addr));
157 | *outpp += 5;
158 | } //if
159 | } else {
160 | if (special_fix_type) {
161 | intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr);
162 | if (ref_idx <= current_idx) {
163 | new_pc_offset = static_cast(ctxp->dat[ref_idx].ins -
164 | reinterpret_cast(*outpp))
165 | >> 2;
166 | } else {
167 | ctxp->insert_fix_map(ref_idx, *outpp, 0u, rmask);
168 | new_pc_offset = 0;
169 | } //if
170 | } //if
171 |
172 | (*outpp)[0] = opc | (new_pc_offset & ~mask);
173 | ++(*outpp);
174 | } //if
175 |
176 | ++(*inpp);
177 | return ctxp->process_fix_map(current_idx), true;
178 | }
179 | }
180 | return false;
181 | }
182 |
183 | //-------------------------------------------------------------------------
184 |
185 | static bool __fix_cond_comp_test_branch(instruction inpp, instruction outpp, context *ctxp) {
186 | static constexpr uint32_t lsb = 5u;
187 | static constexpr uint32_t lmask01 = 0xff00001fu; // 0b11111111000000000000000000011111
188 | static constexpr uint32_t mask0 = 0xff000010u; // 0b11111111000000000000000000010000
189 | static constexpr uint32_t op_bc = 0x54000000u; // "b.c" ADDR_PCREL19
190 | static constexpr uint32_t mask1 = 0x7f000000u; // 0b01111111000000000000000000000000
191 | static constexpr uint32_t op_cbz = 0x34000000u; // "cbz" Rt, ADDR_PCREL19
192 | static constexpr uint32_t op_cbnz = 0x35000000u; // "cbnz" Rt, ADDR_PCREL19
193 | static constexpr uint32_t lmask2 = 0xfff8001fu; // 0b11111111111110000000000000011111
194 | static constexpr uint32_t mask2 = 0x7f000000u; // 0b01111111000000000000000000000000
195 | static constexpr uint32_t op_tbz = 0x36000000u; // 0b00110110000000000000000000000000 "tbz" Rt, BIT_NUM, ADDR_PCREL14
196 | static constexpr uint32_t op_tbnz = 0x37000000u; // 0b00110111000000000000000000000000 "tbnz" Rt, BIT_NUM, ADDR_PCREL14
197 |
198 | const uint32_t ins = *(*inpp);
199 | uint32_t lmask = lmask01;
200 | if ((ins & mask0) != op_bc) {
201 | uint32_t opc = ins & mask1;
202 | if (opc != op_cbz && opc != op_cbnz) {
203 | opc = ins & mask2;
204 | if (opc != op_tbz && opc != op_tbnz) {
205 | return false;
206 | } //if
207 | lmask = lmask2;
208 | } //if
209 | } //if
210 |
211 | intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp);
212 | int64_t absolute_addr = reinterpret_cast(*inpp) + ((ins & ~lmask) >> (lsb - 2u));
213 | int64_t new_pc_offset =
214 | static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; // shifted
215 | bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr);
216 | if (!special_fix_type && llabs(new_pc_offset) >= (~lmask >> (lsb + 1))) {
217 | if ((reinterpret_cast(*outpp + 4) & 7u) != 0u) {
218 | (*outpp)[0] = A64_NOP;
219 | ctxp->reset_current_ins(current_idx, ++(*outpp));
220 | } //if
221 | (*outpp)[0] = (((8u >> 2u) << lsb) & ~lmask) | (ins & lmask); // B.C #0x8
222 | (*outpp)[1] = 0x14000005u; // B #0x14
223 | (*outpp)[2] = 0x58000051u; // LDR X17, #0x8
224 | (*outpp)[3] = 0xd61f0220u; // BR X17
225 | memcpy(*outpp + 4, &absolute_addr, sizeof(absolute_addr));
226 | *outpp += 6;
227 | } else {
228 | if (special_fix_type) {
229 | intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr);
230 | if (ref_idx <= current_idx) {
231 | new_pc_offset = static_cast(ctxp->dat[ref_idx].ins -
232 | reinterpret_cast(*outpp)) >> 2;
233 | } else {
234 | ctxp->insert_fix_map(ref_idx, *outpp, lsb, ~lmask);
235 | new_pc_offset = 0;
236 | } //if
237 | } //if
238 |
239 | (*outpp)[0] = (static_cast(new_pc_offset << lsb) & ~lmask) | (ins & lmask);
240 | ++(*outpp);
241 | } //if
242 |
243 | ++(*inpp);
244 | return ctxp->process_fix_map(current_idx), true;
245 | }
246 |
247 | //-------------------------------------------------------------------------
248 |
249 | static bool __fix_loadlit(instruction inpp, instruction outpp, context *ctxp) {
250 | const uint32_t ins = *(*inpp);
251 |
252 | // memory prefetch("prfm"), just skip it
253 | // http://infocenter.arm.com/help/topic/com.arm.doc.100069_0608_00_en/pge1427897420050.html
254 | if ((ins & 0xff000000u) == 0xd8000000u) {
255 | ctxp->process_fix_map(ctxp->get_and_set_current_index(*inpp, *outpp));
256 | ++(*inpp);
257 | return true;
258 | } //if
259 |
260 | static constexpr uint32_t msb = 8u;
261 | static constexpr uint32_t lsb = 5u;
262 | static constexpr uint32_t mask_30 = 0x40000000u; // 0b01000000000000000000000000000000
263 | static constexpr uint32_t mask_31 = 0x80000000u; // 0b10000000000000000000000000000000
264 | static constexpr uint32_t lmask = 0xff00001fu; // 0b11111111000000000000000000011111
265 | static constexpr uint32_t mask_ldr = 0xbf000000u; // 0b10111111000000000000000000000000
266 | static constexpr uint32_t op_ldr = 0x18000000u; // 0b00011000000000000000000000000000 "LDR Wt/Xt, label" | ADDR_PCREL19
267 | static constexpr uint32_t mask_ldrv = 0x3f000000u; // 0b00111111000000000000000000000000
268 | static constexpr uint32_t op_ldrv = 0x1c000000u; // 0b00011100000000000000000000000000 "LDR St/Dt/Qt, label" | ADDR_PCREL19
269 | static constexpr uint32_t mask_ldrsw = 0xff000000u; // 0b11111111000000000000000000000000
270 | static constexpr uint32_t op_ldrsw = 0x98000000u; // "LDRSW Xt, label" | ADDR_PCREL19 | load register signed word
271 | // LDR S0, #0 | 0b00011100000000000000000000000000 | 32-bit
272 | // LDR D0, #0 | 0b01011100000000000000000000000000 | 64-bit
273 | // LDR Q0, #0 | 0b10011100000000000000000000000000 | 128-bit
274 | // INVALID | 0b11011100000000000000000000000000 | may be 256-bit
275 |
276 | uint32_t mask = mask_ldr;
277 | uintptr_t faligned = (ins & mask_30) ? 7u : 3u;
278 | if ((ins & mask_ldr) != op_ldr) {
279 | mask = mask_ldrv;
280 | if (faligned != 7u)
281 | faligned = (ins & mask_31) ? 15u : 3u;
282 | if ((ins & mask_ldrv) != op_ldrv) {
283 | if ((ins & mask_ldrsw) != op_ldrsw) {
284 | return false;
285 | } //if
286 | mask = mask_ldrsw;
287 | faligned = 7u;
288 | } //if
289 | } //if
290 |
291 | intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp);
292 | int64_t absolute_addr = reinterpret_cast(*inpp) +
293 | ((static_cast(ins << msb) >> (msb + lsb - 2u)) & ~3u);
294 | int64_t new_pc_offset =
295 | static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; // shifted
296 | bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr);
297 | // special_fix_type may encounter issue when there are mixed data and code
298 | if (special_fix_type || (llabs(new_pc_offset) + (faligned + 1u - 4u) / 4u) >=
299 | (~lmask >> (lsb + 1))) { // inaccurate, but it works
300 | while ((reinterpret_cast(*outpp + 2) & faligned) != 0u) {
301 | *(*outpp)++ = A64_NOP;
302 | }
303 | ctxp->reset_current_ins(current_idx, *outpp);
304 |
305 | // Note that if memory at absolute_addr is writeable (non-const), we will fail to fetch it.
306 | // And what's worse, we may unexpectedly overwrite something if special_fix_type is true...
307 | uint32_t ns = static_cast((faligned + 1) / sizeof(uint32_t));
308 | (*outpp)[0] = (((8u >> 2u) << lsb) & ~mask) | (ins & lmask); // LDR #0x8
309 | (*outpp)[1] = 0x14000001u + ns; // B #0xc
310 | memcpy(*outpp + 2, reinterpret_cast(absolute_addr), faligned + 1);
311 | *outpp += 2 + ns;
312 | } else {
313 | faligned >>= 2; // new_pc_offset is shifted and 4-byte aligned
314 | while ((new_pc_offset & faligned) != 0) {
315 | *(*outpp)++ = A64_NOP;
316 | new_pc_offset =
317 | static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2;
318 | }
319 | ctxp->reset_current_ins(current_idx, *outpp);
320 |
321 | (*outpp)[0] = (static_cast(new_pc_offset << lsb) & ~mask) | (ins & lmask);
322 | ++(*outpp);
323 | } //if
324 |
325 | ++(*inpp);
326 | return ctxp->process_fix_map(current_idx), true;
327 | }
328 |
329 | //-------------------------------------------------------------------------
330 |
331 | static bool __fix_pcreladdr(instruction inpp, instruction outpp, context *ctxp) {
332 | // Load a PC-relative address into a register
333 | // http://infocenter.arm.com/help/topic/com.arm.doc.100069_0608_00_en/pge1427897645644.html
334 | static constexpr uint32_t msb = 8u;
335 | static constexpr uint32_t lsb = 5u;
336 | static constexpr uint32_t mask = 0x9f000000u; // 0b10011111000000000000000000000000
337 | static constexpr uint32_t rmask = 0x0000001fu; // 0b00000000000000000000000000011111
338 | static constexpr uint32_t lmask = 0xff00001fu; // 0b11111111000000000000000000011111
339 | static constexpr uint32_t fmask = 0x00ffffffu; // 0b00000000111111111111111111111111
340 | static constexpr uint32_t max_val = 0x001fffffu; // 0b00000000000111111111111111111111
341 | static constexpr uint32_t op_adr = 0x10000000u; // "adr" Rd, ADDR_PCREL21
342 | static constexpr uint32_t op_adrp = 0x90000000u; // "adrp" Rd, ADDR_ADRP
343 |
344 | const uint32_t ins = *(*inpp);
345 | intptr_t current_idx;
346 | switch (ins & mask) {
347 | case op_adr: {
348 | current_idx = ctxp->get_and_set_current_index(*inpp, *outpp);
349 | int64_t lsb_bytes = static_cast(ins << 1u) >> 30u;
350 | int64_t absolute_addr = reinterpret_cast(*inpp) +
351 | (((static_cast(ins << msb) >> (msb + lsb - 2u)) &
352 | ~3u) | lsb_bytes);
353 | int64_t new_pc_offset = static_cast(absolute_addr -
354 | reinterpret_cast(*outpp));
355 | bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr);
356 | if (!special_fix_type && llabs(new_pc_offset) >= (max_val >> 1)) {
357 | if ((reinterpret_cast(*outpp + 2) & 7u) != 0u) {
358 | (*outpp)[0] = A64_NOP;
359 | ctxp->reset_current_ins(current_idx, ++(*outpp));
360 | } //if
361 |
362 | (*outpp)[0] =
363 | 0x58000000u | (((8u >> 2u) << lsb) & ~mask) | (ins & rmask); // LDR #0x8
364 | (*outpp)[1] = 0x14000003u; // B #0xc
365 | memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr));
366 | *outpp += 4;
367 | } else {
368 | if (special_fix_type) {
369 | intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr & ~3ull);
370 | if (ref_idx <= current_idx) {
371 | new_pc_offset = static_cast(ctxp->dat[ref_idx].ins -
372 | reinterpret_cast(*outpp));
373 | } else {
374 | ctxp->insert_fix_map(ref_idx, *outpp, lsb, fmask);
375 | new_pc_offset = 0;
376 | } //if
377 | } //if
378 |
379 | // the lsb_bytes will never be changed, so we can use lmask to keep it
380 | (*outpp)[0] = (static_cast(new_pc_offset << (lsb - 2u)) & fmask) |
381 | (ins & lmask);
382 | ++(*outpp);
383 | } //if
384 | }
385 | break;
386 | case op_adrp: {
387 | current_idx = ctxp->get_and_set_current_index(*inpp, *outpp);
388 | int32_t lsb_bytes = static_cast(ins << 1u) >> 30u;
389 | int64_t absolute_addr = (reinterpret_cast(*inpp) & ~0xfffll) +
390 | ((((static_cast(ins << msb) >> (msb + lsb - 2u)) &
391 | ~3u) | lsb_bytes) << 12);
392 | A64_LOGI("ins = 0x%.8X, pc = %p, abs_addr = %p",
393 | ins, *inpp, reinterpret_cast(absolute_addr));
394 | if (ctxp->is_in_fixing_range(absolute_addr)) {
395 | intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr/* & ~3ull*/);
396 | if (ref_idx > current_idx) {
397 | // the bottom 12 bits of absolute_addr are masked out,
398 | // so ref_idx must be less than or equal to current_idx!
399 | A64_LOGE("ref_idx must be less than or equal to current_idx!");
400 | } //if
401 |
402 | // *absolute_addr may be changed due to relocation fixing
403 | A64_LOGI("What is the correct way to fix this?");
404 | *(*outpp)++ = ins; // 0x90000000u;
405 | } else {
406 | if ((reinterpret_cast(*outpp + 2) & 7u) != 0u) {
407 | (*outpp)[0] = A64_NOP;
408 | ctxp->reset_current_ins(current_idx, ++(*outpp));
409 | } //if
410 |
411 | (*outpp)[0] =
412 | 0x58000000u | (((8u >> 2u) << lsb) & ~mask) | (ins & rmask); // LDR #0x8
413 | (*outpp)[1] = 0x14000003u; // B #0xc
414 | memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr)); // potential overflow?
415 | *outpp += 4;
416 | } //if
417 | }
418 | break;
419 | default:
420 | return false;
421 | }
422 |
423 | ctxp->process_fix_map(current_idx);
424 | ++(*inpp);
425 | return true;
426 | }
427 |
428 | //-------------------------------------------------------------------------
429 | #define __flush_cache(c, n) __builtin___clear_cache(reinterpret_cast(c), reinterpret_cast(c) + n)
430 |
431 | static void __fix_instructions(uint32_t *__restrict inp, int32_t count, uint32_t *__restrict outp) {
432 | context ctx;
433 | ctx.basep = reinterpret_cast(inp);
434 | ctx.endp = reinterpret_cast(inp + count);
435 | memset(ctx.dat, 0, sizeof(ctx.dat));
436 | static_assert(sizeof(ctx.dat) / sizeof(ctx.dat[0]) == A64_MAX_INSTRUCTIONS,
437 | "please use A64_MAX_INSTRUCTIONS!");
438 | #ifndef NDEBUG
439 | if (count > A64_MAX_INSTRUCTIONS) {
440 | A64_LOGE("too many fixing instructions!");
441 | } //if
442 | #endif // NDEBUG
443 |
444 | uint32_t *const outp_base = outp;
445 |
446 | while (--count >= 0) {
447 | if (__fix_branch_imm(&inp, &outp, &ctx)) continue;
448 | if (__fix_cond_comp_test_branch(&inp, &outp, &ctx)) continue;
449 | if (__fix_loadlit(&inp, &outp, &ctx)) continue;
450 | if (__fix_pcreladdr(&inp, &outp, &ctx)) continue;
451 |
452 | // without PC-relative offset
453 | ctx.process_fix_map(ctx.get_and_set_current_index(inp, outp));
454 | *(outp++) = *(inp++);
455 | }
456 |
457 | static constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111
458 | auto callback = reinterpret_cast(inp);
459 | auto pc_offset = static_cast(callback - reinterpret_cast(outp)) >> 2;
460 | if (llabs(pc_offset) >= (mask >> 1)) {
461 | if ((reinterpret_cast(outp + 2) & 7u) != 0u) {
462 | outp[0] = A64_NOP;
463 | ++outp;
464 | } //if
465 | outp[0] = 0x58000051u; // LDR X17, #0x8
466 | outp[1] = 0xd61f0220u; // BR X17
467 | *reinterpret_cast(outp + 2) = callback;
468 | outp += 4;
469 | } else {
470 | outp[0] = 0x14000000u | (pc_offset & mask); // "B" ADDR_PCREL26
471 | ++outp;
472 | } //if
473 |
474 | const uintptr_t total = (outp - outp_base) * sizeof(uint32_t);
475 | __flush_cache(outp_base, total); // necessary
476 | }
477 |
478 | //-------------------------------------------------------------------------
479 |
480 | extern "C" {
481 | #define __attribute __attribute__
482 | #define aligned(x) __aligned__(x)
483 | #define __intval(p) reinterpret_cast(p)
484 | #define __uintval(p) reinterpret_cast(p)
485 | #define __ptr(p) reinterpret_cast(p)
486 | #define __page_size 4096
487 | #define __page_align(n) __align_up(static_cast(n), __page_size)
488 | #define __ptr_align(x) __ptr(__align_down(reinterpret_cast(x), __page_size))
489 | #define __align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1))
490 | #define __align_down(x, n) ((x) & -(n))
491 | #define __countof(x) static_cast(sizeof(x) / sizeof((x)[0])) // must be signed
492 | #define __atomic_increase(p) __sync_add_and_fetch(p, 1)
493 | #define __sync_cmpswap(p, v, n) __sync_bool_compare_and_swap(p, v, n)
494 | #define __predict_true(exp) __builtin_expect((exp) != 0, 1)
495 | #define __make_rwx(p, n) ::mprotect(__ptr_align(p), \
496 | __page_align(__uintval(p) + n) != __page_align(__uintval(p)) ? __page_align(n) + __page_size : __page_align(n), \
497 | PROT_READ | PROT_WRITE | PROT_EXEC)
498 |
499 | //-------------------------------------------------------------------------
500 |
501 | static __attribute((aligned(__page_size))) uint32_t __insns_pool[A64_MAX_BACKUPS][
502 | A64_MAX_INSTRUCTIONS * 10];
503 |
504 | //-------------------------------------------------------------------------
505 |
506 | class A64HookInit {
507 | public:
508 | A64HookInit() {
509 | __make_rwx(__insns_pool, sizeof(__insns_pool));
510 | A64_LOGI("insns pool initialized.");
511 | }
512 | };
513 | static A64HookInit __init;
514 |
515 | //-------------------------------------------------------------------------
516 |
517 | static uint32_t *FastAllocateTrampoline() {
518 | static_assert((A64_MAX_INSTRUCTIONS * 10 * sizeof(uint32_t)) % 8 == 0, "8-byte align");
519 | static volatile int32_t __index = -1;
520 |
521 | int32_t i = __atomic_increase(&__index);
522 | if (__predict_true(i >= 0 && i < __countof(__insns_pool))) {
523 | return __insns_pool[i];
524 | } //if
525 |
526 | A64_LOGE("failed to allocate trampoline!");
527 | return NULL;
528 | }
529 |
530 | //-------------------------------------------------------------------------
531 |
532 | A64_JNIEXPORT void *A64HookFunctionV(void *const symbol, void *const replace,
533 | void *const rwx, const uintptr_t rwx_size) {
534 | static constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111
535 |
536 | uint32_t *trampoline = static_cast(rwx), *original = static_cast(symbol);
537 |
538 | static_assert(A64_MAX_INSTRUCTIONS >= 5, "please fix A64_MAX_INSTRUCTIONS!");
539 | auto pc_offset = static_cast(__intval(replace) - __intval(symbol)) >> 2;
540 | if (llabs(pc_offset) >= (mask >> 1)) {
541 | int32_t count = (reinterpret_cast(original + 2) & 7u) != 0u ? 5 : 4;
542 | if (trampoline) {
543 | if (rwx_size < count * 10u) {
544 | A64_LOGI("rwx size is too small to hold %u bytes backup instructions!",
545 | count * 10u);
546 | return NULL;
547 | } //if
548 | __fix_instructions(original, count, trampoline);
549 | } //if
550 |
551 | if (__make_rwx(original, 5 * sizeof(uint32_t)) == 0) {
552 | if (count == 5) {
553 | original[0] = A64_NOP;
554 | ++original;
555 | } //if
556 | original[0] = 0x58000051u; // LDR X17, #0x8
557 | original[1] = 0xd61f0220u; // BR X17
558 | *reinterpret_cast(original + 2) = __intval(replace);
559 | __flush_cache(symbol, 5 * sizeof(uint32_t));
560 |
561 | A64_LOGI("inline hook %p->%p successfully! %zu bytes overwritten",
562 | symbol, replace, 5 * sizeof(uint32_t));
563 | } else {
564 | A64_LOGE("mprotect failed with errno = %d, p = %p, size = %zu",
565 | errno, original, 5 * sizeof(uint32_t));
566 | trampoline = NULL;
567 | } //if
568 | } else {
569 | if (trampoline) {
570 | if (rwx_size < 1u * 10u) {
571 | A64_LOGI("rwx size is too small to hold %u bytes backup instructions!", 1u * 10u);
572 | return NULL;
573 | } //if
574 | __fix_instructions(original, 1, trampoline);
575 | } //if
576 |
577 | if (__make_rwx(original, 1 * sizeof(uint32_t)) == 0) {
578 | __sync_cmpswap(original, *original,
579 | 0x14000000u | (pc_offset & mask)); // "B" ADDR_PCREL26
580 | __flush_cache(symbol, 1 * sizeof(uint32_t));
581 |
582 | A64_LOGI("inline hook %p->%p successfully! %zu bytes overwritten",
583 | symbol, replace, 1 * sizeof(uint32_t));
584 | } else {
585 | A64_LOGE("mprotect failed with errno = %d, p = %p, size = %zu",
586 | errno, original, 1 * sizeof(uint32_t));
587 | trampoline = NULL;
588 | } //if
589 | } //if
590 |
591 | return trampoline;
592 | }
593 |
594 | //-------------------------------------------------------------------------
595 |
596 | A64_JNIEXPORT void A64HookFunction(void *const symbol, void *const replace, void **result) {
597 | void *trampoline = NULL;
598 | if (result != NULL) {
599 | trampoline = FastAllocateTrampoline();
600 | *result = trampoline;
601 | if (trampoline == NULL) return;
602 | } //if
603 |
604 | trampoline = A64HookFunctionV(symbol, replace, trampoline, A64_MAX_INSTRUCTIONS * 10u);
605 | if (trampoline == NULL && result != NULL) {
606 | *result = NULL;
607 | } //if
608 | }
609 | }
610 |
611 | #endif // defined(__aarch64__)
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/And64InlineHook/And64InlineHook.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * @date : 2018/04/18
3 | * @author : Rprop (r_prop@outlook.com)
4 | * https://github.com/Rprop/And64InlineHook
5 | */
6 | /*
7 | MIT License
8 |
9 | Copyright (c) 2018 Rprop (r_prop@outlook.com)
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all
19 | copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | SOFTWARE.
28 | */
29 | #pragma once
30 | #define A64_MAX_BACKUPS 256
31 |
32 | #ifdef __cplusplus
33 | extern "C" {
34 | #endif
35 |
36 | void A64HookFunction(void *const symbol, void *const replace, void **result);
37 | void *A64HookFunctionV(void *const symbol, void *const replace,
38 | void *const rwx, const uintptr_t rwx_size);
39 |
40 | #ifdef __cplusplus
41 | }
42 | #endif
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/And64InlineHook/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 RLib
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/And64InlineHook/README.md:
--------------------------------------------------------------------------------
1 | # And64InlineHook
2 | Lightweight ARMv8-A(ARM64, AArch64, Little-Endian) Inline Hook Library for Android C/C++
3 |
4 | # References
5 | [Arm Compiler armasm User Guide](http://infocenter.arm.com/help/topic/com.arm.doc.100069_0610_00_en/pge1427898258836.html)
6 | [Procedure Call Standard for the Arm® 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst)
7 |
8 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | # Here is the name of your lib.
6 | # When you change the lib name, change also on System.loadLibrary("") under OnCreate method on StaticActivity.java
7 | # Both must have same name
8 | LOCAL_MODULE := HollowMade
9 |
10 | # Code optimization
11 | # -std=c++17 is required to support AIDE app with NDK support
12 | LOCAL_CFLAGS += -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w
13 | LOCAL_CPPFLAGS += -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -Werror -s -std=c++17 -Wno-error=c++11-narrowing -fms-extensions
14 | LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all
15 | LOCAL_ARM_MODE := arm
16 |
17 | # Here you add the cpp file
18 | LOCAL_SRC_FILES := Main.cpp \
19 | Includes/Utils.cpp \
20 | Substrate/hde64.c \
21 | Substrate/SubstrateDebug.cpp \
22 | Substrate/SubstrateHook.cpp \
23 | Substrate/SubstratePosixMemory.cpp \
24 | Substrate/SymbolFinder.cpp \
25 | KittyMemory/KittyMemory.cpp \
26 | KittyMemory/MemoryPatch.cpp \
27 | KittyMemory/MemoryBackup.cpp \
28 | KittyMemory/KittyUtils.cpp \
29 | And64InlineHook/And64InlineHook.cpp \
30 |
31 | LOCAL_LDLIBS := -llog -landroid
32 | #LOCAL_STATIC_LIBRARIES := android_native_app_glue
33 | include $(BUILD_SHARED_LIBRARY)
34 | #$(call import-module,android/native_app_glue)
35 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := armeabi-v7a arm64-v8a x86
2 | APP_PLATFORM := android-18
3 | APP_STL := c++_static
4 | APP_OPTIM := release
5 | APP_LDFLAGS := -llog
6 | APP_THIN_ARCHIVE := true
7 | APP_PIE := true
8 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Includes/Logger.h:
--------------------------------------------------------------------------------
1 | #ifndef DAWN_LOGGER_H
2 | #define DAWN_LOGGER_H
3 |
4 | #include
5 |
6 | enum daLogType {
7 | daDEBUG = 3,
8 | daERROR = 6,
9 | daINFO = 4,
10 | daWARN = 5
11 | };
12 |
13 | //Change this to another Log Tag if ya want. IN the batch script I provide you change the log tag then too
14 | #define TAG OBFUSCATE("Mod_Menu")
15 |
16 | #define LOGD(...) ((void)__android_log_print(daDEBUG, TAG, __VA_ARGS__))
17 | #define LOGE(...) ((void)__android_log_print(daERROR, TAG, __VA_ARGS__))
18 | #define LOGI(...) ((void)__android_log_print(daINFO, TAG, __VA_ARGS__))
19 | #define LOGW(...) ((void)__android_log_print(daWARN, TAG, __VA_ARGS__))
20 |
21 | #endif //DAWN_LOGGER_H
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Includes/Utils.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "Includes/Utils.h"
4 | #include
5 |
6 | bool isGameLibLoaded = false;
7 |
8 | namespace base64 {
9 | inline std::string get_base64_chars() {
10 | static std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
11 | "abcdefghijklmnopqrstuvwxyz"
12 | "0123456789+/";
13 | return base64_chars;
14 | }
15 |
16 | inline std::string from_base64(std::string const &data) {
17 | int counter = 0;
18 | uint32_t bit_stream = 0;
19 | std::string decoded;
20 | int offset = 0;
21 | const std::string base64_chars = get_base64_chars();
22 | for (auto const &c : data) {
23 | auto num_val = base64_chars.find(c);
24 | if (num_val != std::string::npos) {
25 | offset = 18 - counter % 4 * 6;
26 | bit_stream += num_val << offset;
27 | if (offset == 12) {
28 | decoded += static_cast(bit_stream >> 16 & 0xff);
29 | }
30 | if (offset == 6) {
31 | decoded += static_cast(bit_stream >> 8 & 0xff);
32 | }
33 | if (offset == 0 && counter != 4) {
34 | decoded += static_cast(bit_stream & 0xff);
35 | bit_stream = 0;
36 | }
37 | } else if (c != '=') {
38 | return std::string();
39 | }
40 | counter++;
41 | }
42 | return decoded;
43 | }
44 | }
45 |
46 | DWORD findLibrary(const char *library) {
47 | char filename[0xFF] = {0},
48 | buffer[1024] = {0};
49 | FILE *fp = NULL;
50 | DWORD address = 0;
51 |
52 | sprintf(filename, OBFUSCATE("/proc/self/maps"));
53 |
54 | fp = fopen(filename, OBFUSCATE("rt"));
55 | if (fp == NULL) {
56 | perror(OBFUSCATE("fopen"));
57 | goto done;
58 | }
59 |
60 | while (fgets(buffer, sizeof(buffer), fp)) {
61 | if (strstr(buffer, library)) {
62 | address = (DWORD) strtoul(buffer, NULL, 16);
63 | goto done;
64 | }
65 | }
66 |
67 | done:
68 |
69 | if (fp) {
70 | fclose(fp);
71 | }
72 |
73 | return address;
74 | }
75 |
76 | DWORD getAbsoluteAddress(const char *libraryName, DWORD relativeAddr) {
77 | libBase = findLibrary(libraryName);
78 | if (libBase == 0)
79 | return 0;
80 | return (reinterpret_cast(libBase + relativeAddr));
81 | }
82 |
83 | extern "C" {
84 | JNIEXPORT jboolean JNICALL
85 | Java_uk_lgl_modmenu_FloatingModMenuService_isGameLibLoaded(JNIEnv *env, jobject thiz) {
86 | return isGameLibLoaded;
87 | }
88 | }
89 |
90 | bool isLibraryLoaded(const char *libraryName) {
91 | //isGameLibLoaded = true;
92 | char line[512] = {0};
93 | FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt"));
94 | if (fp != NULL) {
95 | while (fgets(line, sizeof(line), fp)) {
96 | std::string a = line;
97 | if (a.find(base64::from_base64("bGliYm10LnNv")) != std::string::npos) {
98 | int *i = (int *) 0x0;
99 | *i = 1;
100 | }
101 | if (strstr(line, libraryName)) {
102 | isGameLibLoaded = true;
103 | return true;
104 | }
105 | }
106 | fclose(fp);
107 | }
108 | return false;
109 | }
110 |
111 | //Credit: Octowolve
112 | void MakeToast(JNIEnv *env, jobject thiz, const char *text, int length) {
113 | //Add our toast in here so it wont be easy to change by simply editing the smali and cant
114 | //be cut out because this method is needed to start the hack (Octowolve is smart)
115 | jstring jstr = env->NewStringUTF(text); //Edit this text to your desired toast message!
116 | jclass toast = env->FindClass(OBFUSCATE("android/widget/Toast"));
117 | jmethodID methodMakeText =
118 | env->GetStaticMethodID(
119 | toast,
120 | OBFUSCATE("makeText"),
121 | OBFUSCATE(
122 | "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;"));
123 | if (methodMakeText == NULL) {
124 | LOGE(OBFUSCATE("toast.makeText not Found"));
125 | return;
126 | }
127 | //The last int is the length on how long the toast should be displayed
128 | //0 = Short, 1 = Long
129 | jobject toastobj = env->CallStaticObjectMethod(toast, methodMakeText,
130 | thiz, jstr, length);
131 |
132 | jmethodID methodShow = env->GetMethodID(toast, OBFUSCATE("show"), OBFUSCATE("()V"));
133 | if (methodShow == NULL) {
134 | LOGE(OBFUSCATE("toast.show not Found"));
135 | return;
136 | }
137 | env->CallVoidMethod(toastobj, methodShow);
138 | }
139 |
140 | uintptr_t string2Offset(const char *c) {
141 | int base = 16;
142 | // See if this function catches all possibilities.
143 | // If it doesn't, the function would have to be amended
144 | // whenever you add a combination of architecture and
145 | // compiler that is not yet addressed.
146 | static_assert(sizeof(uintptr_t) == sizeof(unsigned long)
147 | || sizeof(uintptr_t) == sizeof(unsigned long long),
148 | "Please add string to handle conversion for this architecture.");
149 |
150 | // Now choose the correct function ...
151 | if (sizeof(uintptr_t) == sizeof(unsigned long)) {
152 | return strtoul(c, nullptr, base);
153 | }
154 |
155 | // All other options exhausted, sizeof(uintptr_t) == sizeof(unsigned long long))
156 | return strtoull(c, nullptr, base);
157 | }
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/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 |
17 | DWORD getAbsoluteAddress(const char *libraryName, DWORD relativeAddr);
18 |
19 | bool isLibraryLoaded(const char *libraryName);
20 |
21 | void MakeToast(JNIEnv *env, jobject thiz, const char *text, int length);
22 |
23 | std::string s(const std::string &str);
24 |
25 | uintptr_t string2Offset(const char *c);
26 |
27 | namespace Toast {
28 | inline const int LENGTH_LONG = 1;
29 | inline const int LENGTH_SHORT = 0;
30 | }
31 |
32 | #endif
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Includes/obfuscate.h:
--------------------------------------------------------------------------------
1 | /* --------------------------------- ABOUT -------------------------------------
2 |
3 | Original Author: Adam Yaxley
4 | Website: https://github.com/adamyaxley
5 | License: See end of file
6 |
7 | Obfuscate
8 | Guaranteed compile-time string literal obfuscation library for C++14
9 |
10 | Usage:
11 | Pass string literals into the AY_OBFUSCATE macro to obfuscate them at compile
12 | time. AY_OBFUSCATE returns a reference to an ay::OBFUSCATE_data object with the
13 | following traits:
14 | - Guaranteed obfuscation of string
15 | The passed string is encrypted with a simple XOR cipher at compile-time to
16 | prevent it being viewable in the binary image
17 | - Global lifetime
18 | The actual instantiation of the ay::OBFUSCATE_data takes place inside a
19 | lambda as a function level static
20 | - Implicitly convertable to a char*
21 | This means that you can pass it directly into functions that would normally
22 | take a char* or a const char*
23 |
24 | Example:
25 | const char* OBFUSCATE_string = AY_OBFUSCATE("Hello World");
26 | std::cout << OBFUSCATE_string << std::endl;
27 |
28 | ----------------------------------------------------------------------------- */
29 |
30 | #include
31 | #include
32 | namespace ay
33 | {
34 | // Obfuscates a string at compile time
35 | template
36 | class obfuscator
37 | {
38 | public:
39 | // Obfuscates the string 'data' on construction
40 | constexpr obfuscator(const char* data)
41 | {
42 | static_assert(KEY != '\0', "KEY must not be the null character.");
43 |
44 | // On construction each of the characters in the string is
45 | // OBFUSCATE with an XOR cipher based on KEY
46 | for (std::size_t i = 0; i < N; i++)
47 | {
48 | m_data[i] = data[i] ^ KEY;
49 | }
50 | }
51 |
52 | constexpr const char* getData() const
53 | {
54 | return &m_data[0];
55 | }
56 |
57 | constexpr std::size_t getSize() const
58 | {
59 | return N;
60 | }
61 |
62 | constexpr char getKey() const
63 | {
64 | return KEY;
65 | }
66 |
67 | private:
68 |
69 | char m_data[N]{};
70 | };
71 |
72 | // Handles decryption and re-encryption of an encrypted string at runtime
73 | template
74 | class OBFUSCATE_data
75 | {
76 | public:
77 | OBFUSCATE_data(const obfuscator& obfuscator)
78 | {
79 | for (std::size_t i = 0; i < N; i++)
80 | {
81 | m_data[i] = obfuscator.getData()[i];
82 | }
83 | }
84 |
85 | ~OBFUSCATE_data()
86 | {
87 | // Zero m_data to remove it from memory
88 | for (std::size_t i = 0; i < N; i++)
89 | {
90 | m_data[i] = 0;
91 | }
92 | }
93 |
94 | // Returns a pointer to the plain text string, decrypting it if
95 | // necessary
96 | operator char*()
97 | {
98 | decrypt();
99 | return m_data;
100 | }
101 | operator std::string()
102 | {
103 | decrypt();
104 | return m_data;
105 | }
106 | // Manually decrypt the string
107 | void decrypt()
108 | {
109 | if (is_encrypted())
110 | {
111 | for (std::size_t i = 0; i < N; i++)
112 | {
113 | m_data[i] ^= KEY;
114 | }
115 | }
116 | }
117 |
118 | // Manually re-encrypt the string
119 | void encrypt()
120 | {
121 | if (!is_encrypted())
122 | {
123 | for (std::size_t i = 0; i < N; i++)
124 | {
125 | m_data[i] ^= KEY;
126 | }
127 | }
128 | }
129 |
130 | // Returns true if this string is currently encrypted, false otherwise.
131 | bool is_encrypted() const
132 | {
133 | return m_data[N - 1] != '\0';
134 | }
135 |
136 | private:
137 |
138 | // Local storage for the string. Call is_encrypted() to check whether or
139 | // not the string is currently OBFUSCATE.
140 | char m_data[N];
141 | };
142 |
143 | // This function exists purely to extract the number of elements 'N' in the
144 | // array 'data'
145 | template
146 | constexpr auto make_obfuscator(const char(&data)[N])
147 | {
148 | return obfuscator(data);
149 | }
150 | }
151 |
152 | // Obfuscates the string 'data' at compile-time and returns a reference to a
153 | // ay::OBFUSCATE_data object with global lifetime that has functions for
154 | // decrypting the string and is also implicitly convertable to a char*
155 | #define OBFUSCATE(data) OBFUSCATE_KEY(data, '.')
156 |
157 | // Obfuscates the string 'data' with 'key' at compile-time and returns a
158 | // reference to a ay::OBFUSCATE_data object with global lifetime that has
159 | // functions for decrypting the string and is also implicitly convertable to a
160 | // char*
161 | #define OBFUSCATE_KEY(data, key) \
162 | []() -> ay::OBFUSCATE_data& { \
163 | constexpr auto n = sizeof(data)/sizeof(data[0]); \
164 | static_assert(data[n - 1] == '\0', "String must be null terminated"); \
165 | constexpr auto obfuscator = ay::make_obfuscator(data); \
166 | static auto OBFUSCATE_data = ay::OBFUSCATE_data(obfuscator); \
167 | return OBFUSCATE_data; \
168 | }()
169 |
170 | /* -------------------------------- LICENSE ------------------------------------
171 |
172 | Public Domain (http://www.unlicense.org)
173 |
174 | This is free and unencumbered software released into the public domain.
175 |
176 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
177 | software, either in source code form or as a compiled binary, for any purpose,
178 | commercial or non-commercial, and by any means.
179 |
180 | In jurisdictions that recognize copyright laws, the author or authors of this
181 | software dedicate any and all copyright interest in the software to the public
182 | domain. We make this dedication for the benefit of the public at large and to
183 | the detriment of our heirs and successors. We intend this dedication to be an
184 | overt act of relinquishment in perpetuity of all present and future rights to
185 | this software under copyright law.
186 |
187 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
189 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
190 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
191 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
192 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
193 |
194 | ----------------------------------------------------------------------------- */
195 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/KittyMemory.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // KittyMemory.cpp
3 | //
4 | // Created by MJ (Ruit) on 1/1/19.
5 | //
6 |
7 | #include
8 | #include "KittyMemory.h"
9 |
10 | using KittyMemory::Memory_Status;
11 | using KittyMemory::ProcMap;
12 |
13 |
14 | struct mapsCache {
15 | std::string identifier;
16 | ProcMap map;
17 | };
18 |
19 | static std::vector __mapsCache;
20 | static ProcMap findMapInCache(std::string id){
21 | ProcMap ret;
22 | for(int i = 0; i < __mapsCache.size(); i++){
23 | if(__mapsCache[i].identifier.compare(id) == 0){
24 | ret = __mapsCache[i].map;
25 | break;
26 | }
27 | }
28 | return ret;
29 | }
30 |
31 |
32 | bool KittyMemory::ProtectAddr(void *addr, size_t length, int protection) {
33 | uintptr_t pageStart = _PAGE_START_OF_(addr);
34 | uintptr_t pageLen = _PAGE_LEN_OF_(addr, length);
35 | return (
36 | mprotect(reinterpret_cast(pageStart), pageLen, protection) != -1
37 | );
38 | }
39 |
40 |
41 | Memory_Status KittyMemory::memWrite(void *addr, const void *buffer, size_t len) {
42 | if (addr == NULL)
43 | return INV_ADDR;
44 |
45 | if (buffer == NULL)
46 | return INV_BUF;
47 |
48 | if (len < 1 || len > INT_MAX)
49 | return INV_LEN;
50 |
51 | if (!ProtectAddr(addr, len, _PROT_RWX_))
52 | return INV_PROT;
53 |
54 | if (memcpy(addr, buffer, len) != NULL && ProtectAddr(addr, len, _PROT_RX_))
55 | return SUCCESS;
56 |
57 | return FAILED;
58 | }
59 |
60 |
61 | Memory_Status KittyMemory::memRead(void *buffer, const void *addr, size_t len) {
62 | if (addr == NULL)
63 | return INV_ADDR;
64 |
65 | if (buffer == NULL)
66 | return INV_BUF;
67 |
68 | if (len < 1 || len > INT_MAX)
69 | return INV_LEN;
70 |
71 | if (memcpy(buffer, addr, len) != NULL)
72 | return SUCCESS;
73 |
74 | return FAILED;
75 | }
76 |
77 |
78 | std::string KittyMemory::read2HexStr(const void *addr, size_t len) {
79 | char temp[len];
80 | memset(temp, 0, len);
81 |
82 | const size_t bufferLen = len * 2 + 1;
83 | char buffer[bufferLen];
84 | memset(buffer, 0, bufferLen);
85 |
86 | std::string ret;
87 |
88 | if (memRead(temp, addr, len) != SUCCESS)
89 | return ret;
90 |
91 | for (int i = 0; i < len; i++) {
92 | sprintf(&buffer[i * 2], "%02X", (unsigned char) temp[i]);
93 | }
94 |
95 | ret += buffer;
96 | return ret;
97 | }
98 |
99 | ProcMap KittyMemory::getLibraryMap(const char *libraryName) {
100 | ProcMap retMap;
101 | char line[512] = {0};
102 |
103 | FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt"));
104 | if (fp != NULL) {
105 | while (fgets(line, sizeof(line), fp)) {
106 | if (strstr(line, libraryName)) {
107 | char tmpPerms[5] = {0}, tmpDev[12] = {0}, tmpPathname[444] = {0};
108 | // parse a line in maps file
109 | // (format) startAddress-endAddress perms offset dev inode pathname
110 | sscanf(line, "%llx-%llx %s %ld %s %d %s",
111 | (long long unsigned *) &retMap.startAddr,
112 | (long long unsigned *) &retMap.endAddr,
113 | tmpPerms, &retMap.offset, tmpDev, &retMap.inode, tmpPathname);
114 |
115 | retMap.length = (uintptr_t) retMap.endAddr - (uintptr_t) retMap.startAddr;
116 | retMap.perms = tmpPerms;
117 | retMap.dev = tmpDev;
118 | retMap.pathname = tmpPathname;
119 |
120 | break;
121 | }
122 | }
123 | fclose(fp);
124 | }
125 | return retMap;
126 | }
127 |
128 | uintptr_t KittyMemory::getAbsoluteAddress(const char *libraryName, uintptr_t relativeAddr, bool useCache) {
129 | ProcMap libMap;
130 |
131 | if(useCache){
132 | libMap = findMapInCache(libraryName);
133 | if(libMap.isValid())
134 | return (reinterpret_cast(libMap.startAddr) + relativeAddr);
135 | }
136 |
137 | libMap = getLibraryMap(libraryName);
138 | if (!libMap.isValid())
139 | return 0;
140 |
141 | if(useCache){
142 | mapsCache cachedMap;
143 | cachedMap.identifier = libraryName;
144 | cachedMap.map = libMap;
145 | __mapsCache.push_back(cachedMap);
146 | }
147 |
148 | return (reinterpret_cast(libMap.startAddr) + relativeAddr);
149 | }
150 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/KittyMemory.h:
--------------------------------------------------------------------------------
1 | //
2 | // KittyMemory.hpp
3 | //
4 | // Created by MJ (Ruit) on 1/1/19.
5 | //
6 |
7 | #pragma once
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 |
16 | #define _SYS_PAGE_SIZE_ (sysconf(_SC_PAGE_SIZE))
17 |
18 | #define _PAGE_START_OF_(x) ((uintptr_t)x & ~(uintptr_t)(_SYS_PAGE_SIZE_ - 1))
19 | #define _PAGE_END_OF_(x, len) (_PAGE_START_OF_((uintptr_t)x + len - 1))
20 | #define _PAGE_LEN_OF_(x, len) (_PAGE_END_OF_(x, len) - _PAGE_START_OF_(x) + _SYS_PAGE_SIZE_)
21 | #define _PAGE_OFFSET_OF_(x) ((uintptr_t)x - _PAGE_START_OF_(x))
22 |
23 | #define _PROT_RWX_ (PROT_READ | PROT_WRITE | PROT_EXEC)
24 | #define _PROT_RX_ (PROT_READ | PROT_EXEC)
25 |
26 |
27 | #define EMPTY_VEC_OFFSET std::vector()
28 |
29 |
30 | namespace KittyMemory {
31 |
32 | typedef enum {
33 | FAILED = 0,
34 | SUCCESS = 1,
35 | INV_ADDR = 2,
36 | INV_LEN = 3,
37 | INV_BUF = 4,
38 | INV_PROT = 5
39 | } Memory_Status;
40 |
41 |
42 | struct ProcMap {
43 | void *startAddr;
44 | void *endAddr;
45 | size_t length;
46 | std::string perms;
47 | long offset;
48 | std::string dev;
49 | int inode;
50 | std::string pathname;
51 |
52 | bool isValid() { return (startAddr != NULL && endAddr != NULL && !pathname.empty()); }
53 | };
54 |
55 | /*
56 | * Changes protection of an address with given length
57 | */
58 | bool ProtectAddr(void *addr, size_t length, int protection);
59 |
60 | /*
61 | * Writes buffer content to an address
62 | */
63 | Memory_Status memWrite(void *addr, const void *buffer, size_t len);
64 |
65 | /*
66 | * Reads an address content into a buffer
67 | */
68 | Memory_Status memRead(void *buffer, const void *addr, size_t len);
69 |
70 | /*
71 | * Reads an address content and returns hex string
72 | */
73 | std::string read2HexStr(const void *addr, size_t len);
74 |
75 |
76 | /*
77 | * Wrapper to dereference & get value of a multi level pointer
78 | * Make sure to use the correct data type!
79 | */
80 | template
81 | Type readMultiPtr(void *ptr, std::vector offsets) {
82 | Type defaultVal = {};
83 | if (ptr == NULL)
84 | return defaultVal;
85 |
86 | uintptr_t finalPtr = reinterpret_cast(ptr);
87 | int offsetsSize = offsets.size();
88 | if (offsetsSize > 0) {
89 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) {
90 | if (i == (offsetsSize - 1))
91 | return *reinterpret_cast(finalPtr + offsets[i]);
92 |
93 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]);
94 | }
95 | }
96 |
97 | if (finalPtr == 0)
98 | return defaultVal;
99 |
100 | return *reinterpret_cast(finalPtr);
101 | }
102 |
103 |
104 | /*
105 | * Wrapper to dereference & set value of a multi level pointer
106 | * Make sure to use the correct data type!, const objects won't work
107 | */
108 | template
109 | bool writeMultiPtr(void *ptr, std::vector offsets, Type val) {
110 | if (ptr == NULL)
111 | return false;
112 |
113 | uintptr_t finalPtr = reinterpret_cast(ptr);
114 | int offsetsSize = offsets.size();
115 | if (offsetsSize > 0) {
116 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) {
117 | if (i == (offsetsSize - 1)) {
118 | *reinterpret_cast(finalPtr + offsets[i]) = val;
119 | return true;
120 | }
121 |
122 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]);
123 | }
124 | }
125 |
126 | if (finalPtr == 0)
127 | return false;
128 |
129 | *reinterpret_cast(finalPtr) = val;
130 | return true;
131 | }
132 |
133 | /*
134 | * Wrapper to dereference & get value of a pointer
135 | * Make sure to use the correct data type!
136 | */
137 | template
138 | Type readPtr(void *ptr) {
139 | Type defaultVal = {};
140 | if (ptr == NULL)
141 | return defaultVal;
142 |
143 | return *reinterpret_cast(ptr);
144 | }
145 |
146 | /*
147 | * Wrapper to dereference & set value of a pointer
148 | * Make sure to use the correct data type!, const objects won't work
149 | */
150 | template
151 | bool writePtr(void *ptr, Type val) {
152 | if (ptr == NULL)
153 | return false;
154 |
155 | *reinterpret_cast(ptr) = val;
156 | return true;
157 | }
158 |
159 | /*
160 | * Gets info of a mapped library in self process
161 | */
162 | ProcMap getLibraryMap(const char *libraryName);
163 |
164 | /*
165 | * Expects a relative address in a library
166 | * Returns final absolute address
167 | */
168 | uintptr_t
169 | getAbsoluteAddress(const char *libraryName, uintptr_t relativeAddr, bool useCache = false);
170 | };
171 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/KittyUtils.cpp:
--------------------------------------------------------------------------------
1 | #include "KittyUtils.h"
2 |
3 | static void xtrim(std::string &hex){
4 | if(hex.compare(0, 2, "0x") == 0){
5 | hex.erase(0, 2);
6 | }
7 |
8 | // https://www.techiedelight.com/remove-whitespaces-string-cpp/
9 | hex.erase(std::remove_if(hex.begin(), hex.end(), [](char c){
10 | return (c == ' ' || c == '\n' || c == '\r' ||
11 | c == '\t' || c == '\v' || c == '\f');
12 | }),
13 | hex.end());
14 | }
15 |
16 |
17 | bool KittyUtils::validateHexString(std::string &xstr){
18 | if(xstr.length() < 2) return false;
19 | xtrim(xstr); // first remove spaces
20 | if(xstr.length() % 2 != 0) return false;
21 | for(size_t i = 0; i < xstr.length(); i++){
22 | if(!std::isxdigit((unsigned char)xstr[i])){
23 | return false;
24 | }
25 | }
26 | return true;
27 | }
28 |
29 |
30 | // https://tweex.net/post/c-anything-tofrom-a-hex-string/
31 | #include
32 | #include
33 |
34 |
35 | // ------------------------------------------------------------------
36 | /*!
37 | Convert a block of data to a hex string
38 | */
39 | void KittyUtils::toHex(
40 | void *const data, //!< Data to convert
41 | const size_t dataLength, //!< Length of the data to convert
42 | std::string &dest //!< Destination string
43 | )
44 | {
45 | unsigned char *byteData = reinterpret_cast(data);
46 | std::stringstream hexStringStream;
47 |
48 | hexStringStream << std::hex << std::setfill('0');
49 | for(size_t index = 0; index < dataLength; ++index)
50 | hexStringStream << std::setw(2) << static_cast(byteData[index]);
51 | dest = hexStringStream.str();
52 | }
53 |
54 |
55 | // ------------------------------------------------------------------
56 | /*!
57 | Convert a hex string to a block of data
58 | */
59 | void KittyUtils::fromHex(
60 | const std::string &in, //!< Input hex string
61 | void *const data //!< Data store
62 | )
63 | {
64 | size_t length = in.length();
65 | unsigned char *byteData = reinterpret_cast(data);
66 |
67 | std::stringstream hexStringStream; hexStringStream >> std::hex;
68 | for(size_t strIndex = 0, dataIndex = 0; strIndex < length; ++dataIndex)
69 | {
70 | // Read out and convert the string two characters at a time
71 | const char tmpStr[3] = { in[strIndex++], in[strIndex++], 0 };
72 |
73 | // Reset and fill the string stream
74 | hexStringStream.clear();
75 | hexStringStream.str(tmpStr);
76 |
77 | // Do the conversion
78 | int tmpValue = 0;
79 | hexStringStream >> tmpValue;
80 | byteData[dataIndex] = static_cast(tmpValue);
81 | }
82 | }
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/KittyUtils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace KittyUtils {
7 |
8 | bool validateHexString(std::string &xstr);
9 | void toHex(void *const data, const size_t dataLength, std::string &dest);
10 | void fromHex(const std::string &in, void *const data);
11 |
12 | }
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/MemoryBackup.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // MemoryBackup.cpp
3 | //
4 | // Created by MJ (Ruit) on 4/19/20.
5 | //
6 |
7 | #include
8 | #include "MemoryBackup.h"
9 |
10 |
11 | MemoryBackup::MemoryBackup() {
12 | _address = 0;
13 | _size = 0;
14 | _orig_code.clear();
15 | }
16 |
17 | MemoryBackup::MemoryBackup(const char *libraryName, uintptr_t address, size_t backup_size, bool useMapCache) {
18 | MemoryBackup();
19 |
20 | if (libraryName == NULL || address == 0 || backup_size < 1)
21 | return;
22 |
23 | _address = KittyMemory::getAbsoluteAddress(libraryName, address, useMapCache);
24 | if(_address == 0) return;
25 |
26 | _size = backup_size;
27 |
28 | _orig_code.resize(backup_size);
29 |
30 | // backup current content
31 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size);
32 | }
33 |
34 |
35 | MemoryBackup::MemoryBackup(uintptr_t absolute_address, size_t backup_size) {
36 | MemoryBackup();
37 |
38 | if (absolute_address == 0 || backup_size < 1)
39 | return;
40 |
41 | _address = absolute_address;
42 |
43 | _size = backup_size;
44 |
45 | _orig_code.resize(backup_size);
46 |
47 | // backup current content
48 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size);
49 | }
50 |
51 | MemoryBackup::~MemoryBackup() {
52 | // clean up
53 | _orig_code.clear();
54 | }
55 |
56 |
57 | bool MemoryBackup::isValid() const {
58 | return (_address != 0 && _size > 0
59 | && _orig_code.size() == _size);
60 | }
61 |
62 | size_t MemoryBackup::get_BackupSize() const{
63 | return _size;
64 | }
65 |
66 | uintptr_t MemoryBackup::get_TargetAddress() const{
67 | return _address;
68 | }
69 |
70 | bool MemoryBackup::Restore() {
71 | if (!isValid()) return false;
72 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == Memory_Status::SUCCESS;
73 | }
74 |
75 | std::string MemoryBackup::get_CurrBytes() {
76 | if (!isValid())
77 | _hexString = std::string(OBFUSCATE("0xInvalid"));
78 | else
79 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size);
80 |
81 | return _hexString;
82 | }
83 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/MemoryBackup.h:
--------------------------------------------------------------------------------
1 | //
2 | // MemoryBackup.h
3 | //
4 | // Created by MJ (Ruit) on 4/19/20.
5 | //
6 |
7 | #pragma once
8 |
9 | #include
10 |
11 | #include "KittyMemory.h"
12 | using KittyMemory::Memory_Status;
13 | using KittyMemory::ProcMap;
14 |
15 |
16 | class MemoryBackup {
17 | private:
18 | uintptr_t _address;
19 | size_t _size;
20 |
21 | std::vector _orig_code;
22 |
23 | std::string _hexString;
24 |
25 | public:
26 | MemoryBackup();
27 |
28 | /*
29 | * expects library name and relative address
30 | */
31 | MemoryBackup(const char *libraryName, uintptr_t address, size_t backup_size, bool useMapCache=true);
32 |
33 | /*
34 | * expects absolute address
35 | */
36 | MemoryBackup(uintptr_t absolute_address, size_t backup_size);
37 |
38 |
39 | ~MemoryBackup();
40 |
41 |
42 | /*
43 | * Validate patch
44 | */
45 | bool isValid() const;
46 |
47 |
48 | size_t get_BackupSize() const;
49 |
50 | /*
51 | * Returns pointer to the target address
52 | */
53 | uintptr_t get_TargetAddress() const;
54 |
55 |
56 | /*
57 | * Restores backup code
58 | */
59 | bool Restore();
60 |
61 |
62 | /*
63 | * Returns current target address bytes as hex string
64 | */
65 | std::string get_CurrBytes();
66 | };
67 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/MemoryPatch.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // MemoryPatch.cpp
3 | //
4 | // Created by MJ (Ruit) on 1/1/19.
5 | //
6 |
7 | #include
8 | #include "MemoryPatch.h"
9 |
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 |
39 | MemoryPatch::MemoryPatch(uintptr_t absolute_address,
40 | const void *patch_code, size_t patch_size) {
41 | MemoryPatch();
42 |
43 | if (absolute_address == 0 || patch_code == NULL || patch_size < 1)
44 | return;
45 |
46 | _address = absolute_address;
47 | _size = patch_size;
48 |
49 | _orig_code.resize(patch_size);
50 | _patch_code.resize(patch_size);
51 |
52 | // initialize patch & backup current content
53 | KittyMemory::memRead(&_patch_code[0], patch_code, patch_size);
54 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), patch_size);
55 | }
56 |
57 | MemoryPatch::~MemoryPatch() {
58 | // clean up
59 | _orig_code.clear();
60 | _patch_code.clear();
61 | }
62 |
63 |
64 | MemoryPatch MemoryPatch::createWithHex(const char *libraryName, uintptr_t address,
65 | std::string hex, bool useMapCache) {
66 | MemoryPatch patch;
67 |
68 | if (libraryName == NULL || address == 0 || !KittyUtils::validateHexString(hex))
69 | return patch;
70 |
71 | patch._address = KittyMemory::getAbsoluteAddress(libraryName, address, useMapCache);
72 | if(patch._address == 0) return patch;
73 |
74 | patch._size = hex.length() / 2;
75 |
76 | patch._orig_code.resize(patch._size);
77 | patch._patch_code.resize(patch._size);
78 |
79 | // initialize patch
80 | KittyUtils::fromHex(hex, &patch._patch_code[0]);
81 |
82 | // backup current content
83 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), patch._size);
84 | return patch;
85 | }
86 |
87 | MemoryPatch MemoryPatch::createWithHex(uintptr_t absolute_address, std::string hex) {
88 | MemoryPatch patch;
89 |
90 | if (absolute_address == 0 || !KittyUtils::validateHexString(hex))
91 | return patch;
92 |
93 | patch._address = absolute_address;
94 | patch._size = hex.length() / 2;
95 |
96 | patch._orig_code.resize(patch._size);
97 | patch._patch_code.resize(patch._size);
98 |
99 | // initialize patch
100 | KittyUtils::fromHex(hex, &patch._patch_code[0]);
101 |
102 | // backup current content
103 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), patch._size);
104 | return patch;
105 | }
106 |
107 |
108 | bool MemoryPatch::isValid() const {
109 | return (_address != 0 && _size > 0
110 | && _orig_code.size() == _size && _patch_code.size() == _size);
111 | }
112 |
113 | size_t MemoryPatch::get_PatchSize() const{
114 | return _size;
115 | }
116 |
117 | uintptr_t MemoryPatch::get_TargetAddress() const{
118 | return _address;
119 | }
120 |
121 | bool MemoryPatch::Restore() {
122 | if (!isValid()) return false;
123 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == Memory_Status::SUCCESS;
124 | }
125 |
126 | bool MemoryPatch::Modify() {
127 | if (!isValid()) return false;
128 | return (KittyMemory::memWrite(reinterpret_cast(_address), &_patch_code[0], _size) == Memory_Status::SUCCESS);
129 | }
130 |
131 | std::string MemoryPatch::get_CurrBytes() {
132 | if (!isValid())
133 | _hexString = std::string(OBFUSCATE("0xInvalid"));
134 | else
135 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size);
136 |
137 | return _hexString;
138 | }
139 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/KittyMemory/MemoryPatch.h:
--------------------------------------------------------------------------------
1 | //
2 | // MemoryPatch.h
3 | //
4 | // Created by MJ (Ruit) on 1/1/19.
5 | //
6 |
7 | #pragma once
8 |
9 | #include
10 |
11 | #include "KittyUtils.h"
12 |
13 | #include "KittyMemory.h"
14 | using KittyMemory::Memory_Status;
15 | using KittyMemory::ProcMap;
16 |
17 |
18 | class MemoryPatch {
19 | private:
20 | uintptr_t _address;
21 | size_t _size;
22 |
23 | std::vector _orig_code;
24 | std::vector _patch_code;
25 |
26 | std::string _hexString;
27 |
28 | public:
29 | MemoryPatch();
30 |
31 | /*
32 | * expects library name and relative address
33 | */
34 | MemoryPatch(const char *libraryName, uintptr_t address,
35 | const void *patch_code, size_t patch_size, bool useMapCache=true);
36 |
37 |
38 | /*
39 | * expects absolute address
40 | */
41 | MemoryPatch(uintptr_t absolute_address,
42 | const void *patch_code, size_t patch_size);
43 |
44 |
45 | ~MemoryPatch();
46 |
47 | /*
48 | * compatible hex format (0xffff & ffff & ff ff)
49 | */
50 | static MemoryPatch createWithHex(const char *libraryName, uintptr_t address, std::string hex, bool useMapCache=true);
51 | static MemoryPatch createWithHex(uintptr_t absolute_address, std::string hex);
52 |
53 | /*
54 | * Validate patch
55 | */
56 | bool isValid() const;
57 |
58 |
59 | size_t get_PatchSize() const;
60 |
61 | /*
62 | * Returns pointer to the target address
63 | */
64 | uintptr_t get_TargetAddress() const;
65 |
66 |
67 | /*
68 | * Restores patch to original value
69 | */
70 | bool Restore();
71 |
72 |
73 | /*
74 | * Applies patch modifications to target address
75 | */
76 | bool Modify();
77 |
78 |
79 | /*
80 | * Returns current patch target address bytes as hex string
81 | */
82 | std::string get_CurrBytes();
83 | };
84 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "KittyMemory/MemoryPatch.h"
10 | #include "Includes/Logger.h"
11 | #include "Includes/Utils.h"
12 | #include "Includes/obfuscate.h"
13 |
14 | #include "Menu.h"
15 |
16 | #include "Toast.h"
17 |
18 | #if defined(__aarch64__) //Compile for arm64 lib only
19 | #include
20 | #else //Compile for armv7 lib only. Do not worry about greyed out highlighting code, it still works
21 |
22 | #include
23 | #include
24 |
25 | #endif
26 |
27 | // fancy struct for patches for kittyMemory
28 | struct My_Patches {
29 | MemoryPatch GodMode, GodMode2, SliderExample;
30 | } hexPatches;
31 |
32 |
33 | bool feature1 = false;
34 | bool feature2 = false;
35 | bool featureHookToggle = false;
36 |
37 |
38 | int sliderValue = 1;
39 | int dmgmul = 1;
40 | int defmul = 1;
41 | void *instanceBtn;
42 |
43 |
44 | // See https://guidedhacking.com/threads/android-function-pointers-hooking-template-tutorial.14771/
45 | void (*AddMoneyExample)(void *instance, int amount);
46 |
47 | //Target lib here
48 | #define targetLibName OBFUSCATE("libil2cpp.so")
49 |
50 | extern "C" {
51 | JNIEXPORT void JNICALL
52 | Java_uk_lgl_modmenu_Preferences_Changes(JNIEnv *env, jclass clazz, jobject obj,
53 | jint feature, jint value, jboolean boolean, jstring str) {
54 |
55 | const char *featureName = env->GetStringUTFChars(str, 0);
56 | feature += 1; // No need to count from 0 anymore. yaaay :)))
57 |
58 | LOGD(OBFUSCATE("Feature name: %d - %s | Value: = %d | Bool: = %d"), feature, featureName, value,
59 | boolean);
60 |
61 | //!!! BE CAREFUL NOT TO ACCIDENTLY REMOVE break; !!!//
62 |
63 | switch (feature) {
64 | case 1:
65 | // The category was 1 so is not used
66 | break;
67 | case 2:
68 | feature2 = boolean;
69 | if (feature2) {
70 | hexPatches.GodMode.Modify();
71 | hexPatches.GodMode2.Modify();
72 | } else {
73 | hexPatches.GodMode.Restore();
74 | hexPatches.GodMode2.Restore();
75 | }
76 | break;
77 | case 3:
78 | if (value >= 1) {
79 | sliderValue = value;
80 | }
81 | break;
82 | case 4:
83 | switch (value) {
84 | case 0:
85 | hexPatches.SliderExample = MemoryPatch::createWithHex(
86 | targetLibName, string2Offset(
87 | OBFUSCATE_KEY("0x100000", 't')),
88 | OBFUSCATE(
89 | "00 00 A0 E3 1E FF 2F E1"));
90 | hexPatches.SliderExample.Modify();
91 | break;
92 | case 1:
93 | hexPatches.SliderExample = MemoryPatch::createWithHex(
94 | targetLibName, string2Offset(
95 | OBFUSCATE_KEY("0x100000",
96 | 'b')),
97 | OBFUSCATE(
98 | "01 00 A0 E3 1E FF 2F E1"));
99 | hexPatches.SliderExample.Modify();
100 | break;
101 | case 2:
102 | hexPatches.SliderExample = MemoryPatch::createWithHex(
103 | targetLibName,
104 | string2Offset(
105 | OBFUSCATE_KEY("0x100000",
106 | 'q')),
107 | OBFUSCATE(
108 | "02 00 A0 E3 1E FF 2F E1"));
109 | hexPatches.SliderExample.Modify();
110 | break;
111 | }
112 | break;
113 | case 5:
114 | switch (value) {
115 | case 0:
116 | LOGD(OBFUSCATE("Selected item 1"));
117 | break;
118 | case 1:
119 | LOGD(OBFUSCATE("Selected item 2"));
120 | break;
121 | case 2:
122 | LOGD(OBFUSCATE("Selected item 3"));
123 | break;
124 | }
125 | break;
126 | case 6:
127 | LOGD(OBFUSCATE("Feature 6 Called"));
128 | // See more https://guidedhacking.com/threads/android-function-pointers-hooking-template-tutorial.14771/
129 | if (instanceBtn != NULL)
130 | AddMoneyExample(instanceBtn, 999999);
131 | //MakeToast(env, obj, OBFUSCATE("Button pressed"), Toast::LENGTH_SHORT); //When the button is pressed it shows a message
132 | break;
133 | case 8:
134 | LOGD(OBFUSCATE("Feature 8 Called"));
135 | featureHookToggle = boolean;
136 | break;
137 | }
138 | }
139 | }
140 |
141 | // ---------- Hooking ---------- //
142 |
143 | bool (*old_get_BoolExample)(void *instance);
144 |
145 | bool get_BoolExample(void *instance) {
146 | if (instance != NULL && featureHookToggle) {
147 | return true;
148 | }
149 | return old_get_BoolExample(instance);
150 | }
151 |
152 | float (*old_get_FloatExample)(void *instance);
153 |
154 | float get_FloatExample(void *instance) {
155 | if (instance != NULL && sliderValue > 1) {
156 | return (float) sliderValue;
157 | }
158 | return old_get_FloatExample(instance);
159 | }
160 |
161 | void (*old_Update)(void *instance);
162 |
163 | void Update(void *instance) {
164 | instanceBtn = instance;
165 | old_Update(instance);
166 | }
167 |
168 | void *hack_thread(void *) {
169 | LOGI(OBFUSCATE("pthread called"));
170 |
171 | //Check if target lib is loaded
172 | do {
173 | sleep(1);
174 | } while (!isLibraryLoaded(targetLibName));
175 |
176 | LOGI(OBFUSCATE("%s has been loaded"), (const char *) targetLibName);
177 |
178 | #if defined(__aarch64__) //Compile for arm64 lib only.
179 | // New way to patch hex via KittyMemory without need to specify len. Spaces or without spaces are fine
180 | hexPatches.GodMode = MemoryPatch::createWithHex(targetLibName,
181 | string2Offset(OBFUSCATE_KEY("0x123456", '3')),
182 | OBFUSCATE("00 00 A0 E3 1E FF 2F E1"));
183 |
184 | // Offset Hook example
185 | A64HookFunction((void *) getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE_KEY("0x123456", 'l'))), (void *) get_BoolExample,
186 | (void **) &old_get_BoolExample);
187 |
188 | // Function pointer splitted because we want to avoid crash when the il2cpp lib isn't loaded.
189 | // See https://guidedhacking.com/threads/android-function-pointers-hooking-template-tutorial.14771/
190 | AddMoneyExample = (void(*)(void *,int))getAbsoluteAddress(targetLibName, 0x123456);
191 |
192 | #else //Compile for armv7 lib only.
193 |
194 | hexPatches.GodMode = MemoryPatch::createWithHex(targetLibName,
195 | string2Offset(OBFUSCATE_KEY("0x123456", '-')),
196 | OBFUSCATE("00 00 A0 E3 1E FF 2F E1"));
197 |
198 | //hexPatches.GodMode.Modify(); //Activates Automatically
199 |
200 |
201 | hexPatches.GodMode2 = MemoryPatch::createWithHex("libtargetLibHere.so", //The lib you want
202 | string2Offset(OBFUSCATE_KEY("0x222222", 'g')),
203 | OBFUSCATE("00 00 A0 E3 1E FF 2F E1"));
204 |
205 | //hexPatches.GodMode2.Modify(); //Activates Automatically
206 |
207 |
208 | MSHookFunction(
209 | (void *) getAbsoluteAddress(targetLibName,
210 | string2Offset(OBFUSCATE_KEY("0x123456", '?'))),
211 | (void *) get_BoolExample,
212 | (void **) &old_get_BoolExample);
213 |
214 | // Symbol hook example (untested). Symbol/function names can be found in IDA if the lib are not stripped. This is not for il2cpp games
215 | MSHookFunction((void *) ("__SymbolNameExample"), (void *) get_BoolExample,
216 | (void **) &old_get_BoolExample);
217 |
218 |
219 | AddMoneyExample = (void (*)(void *, int)) getAbsoluteAddress(targetLibName, 0x123456);
220 |
221 | LOGI(OBFUSCATE("Hooked"));
222 | #endif
223 |
224 | return NULL;
225 | }
226 | __attribute__((constructor))
227 | void lib_main() {
228 | // Create a new thread so it does not block the main thread, means the game would not freeze
229 | pthread_t ptid;
230 | pthread_create(&ptid, NULL, hack_thread, NULL);
231 | }
232 |
233 | /*
234 | JNIEXPORT jint JNICALL
235 | JNI_OnLoad(JavaVM *vm, void *reserved) {
236 | JNIEnv *globalEnv;
237 | vm->GetEnv((void **) &globalEnv, JNI_VERSION_1_6);
238 |
239 | return JNI_VERSION_1_6;
240 | }
241 | */
242 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/Buffer.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_BUFFER_HPP
23 | #define SUBSTRATE_BUFFER_HPP
24 |
25 | #include
26 |
27 | template
28 | _disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) {
29 | *reinterpret_cast(buffer) = value;
30 | buffer += sizeof(Type_);
31 | }
32 |
33 | _disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) {
34 | memcpy(buffer, data, size);
35 | buffer += size;
36 | }
37 |
38 | #endif//SUBSTRATE_BUFFER_HPP
39 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/CydiaSubstrate.h:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_H_
23 | #define SUBSTRATE_H_
24 |
25 | #ifdef __APPLE__
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif
29 | #include
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
34 | #include
35 | #include
36 | #endif
37 |
38 | #include
39 | #include
40 |
41 | #define _finline \
42 | inline __attribute__((__always_inline__))
43 | #define _disused \
44 | __attribute__((__unused__))
45 |
46 | #define _extern \
47 | extern "C" __attribute__((__visibility__("default")))
48 |
49 | #ifdef __cplusplus
50 | #define _default(value) = value
51 | #else
52 | #define _default(value)
53 | #endif
54 |
55 | #ifdef __cplusplus
56 | extern "C" {
57 | #endif
58 |
59 | bool MSHookProcess(pid_t pid, const char *library);
60 |
61 | typedef const void *MSImageRef;
62 |
63 | MSImageRef MSGetImageByName(const char *file);
64 | void *MSFindSymbol(MSImageRef image, const char *name);
65 |
66 | void MSHookFunction(void *symbol, void *replace, void **result);
67 |
68 | #ifdef __APPLE__
69 | #ifdef __arm__
70 | __attribute__((__deprecated__))
71 | IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL));
72 | #endif
73 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result);
74 | #endif
75 |
76 | #ifdef SubstrateInternal
77 | typedef void *SubstrateAllocatorRef;
78 | typedef struct __SubstrateProcess *SubstrateProcessRef;
79 | typedef struct __SubstrateMemory *SubstrateMemoryRef;
80 |
81 | SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid);
82 | void SubstrateProcessRelease(SubstrateProcessRef process);
83 |
84 | SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size);
85 | void SubstrateMemoryRelease(SubstrateMemoryRef memory);
86 | #endif
87 |
88 | #ifdef __cplusplus
89 | }
90 | #endif
91 |
92 | #ifdef __cplusplus
93 |
94 | #ifdef SubstrateInternal
95 | struct SubstrateHookMemory {
96 | SubstrateMemoryRef handle_;
97 |
98 | SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) :
99 | handle_(SubstrateMemoryCreate(NULL, NULL, data, size))
100 | {
101 | }
102 |
103 | ~SubstrateHookMemory() {
104 | if (handle_ != NULL)
105 | SubstrateMemoryRelease(handle_);
106 | }
107 | };
108 | #endif
109 |
110 |
111 | template
112 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) {
113 | MSHookFunction(
114 | reinterpret_cast(symbol),
115 | reinterpret_cast(replace),
116 | reinterpret_cast(result)
117 | );
118 | }
119 |
120 | template
121 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) {
122 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL));
123 | }
124 |
125 | template
126 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) {
127 | value = reinterpret_cast(MSFindSymbol(image, name));
128 | }
129 |
130 | template
131 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) {
132 | Type_ *symbol;
133 | MSHookSymbol(symbol, name);
134 | return MSHookFunction(symbol, replace, result);
135 | }
136 |
137 | #endif
138 |
139 | #define MSHook(type, name, args...) \
140 | _disused static type (*_ ## name)(args); \
141 | static type $ ## name(args)
142 |
143 | #ifdef __cplusplus
144 | #define MSHake(name) \
145 | &$ ## name, &_ ## name
146 | #else
147 | #define MSHake(name) \
148 | &$ ## name, (void **) &_ ## name
149 | #endif
150 |
151 |
152 | #endif//SUBSTRATE_H_
153 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateARM.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_ARM_HPP
23 | #define SUBSTRATE_ARM_HPP
24 |
25 | enum A$r {
26 | A$r0, A$r1, A$r2, A$r3,
27 | A$r4, A$r5, A$r6, A$r7,
28 | A$r8, A$r9, A$r10, A$r11,
29 | A$r12, A$r13, A$r14, A$r15,
30 | A$sp = A$r13,
31 | A$lr = A$r14,
32 | A$pc = A$r15
33 | };
34 |
35 | enum A$c {
36 | A$eq, A$ne, A$cs, A$cc,
37 | A$mi, A$pl, A$vs, A$vc,
38 | A$hi, A$ls, A$ge, A$lt,
39 | A$gt, A$le, A$al,
40 | A$hs = A$cs,
41 | A$lo = A$cc
42 | };
43 |
44 | #define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \
45 | (0xe10f0000 | ((rd) << 12))
46 | #define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \
47 | (0xe128f000 | (rm))
48 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \
49 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs((int)(im)))
50 | #define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \
51 | (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im))
52 | #define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \
53 | (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff))
54 | #define A$blx_rm(rm) /* blx rm */ \
55 | (0xe12fff30 | (rm))
56 | #define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \
57 | (0xe1a00000 | ((rd) << 12) | (rm))
58 | #define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \
59 | (0xe8b00000 | (A$sp << 16) | (rs))
60 | #define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \
61 | (0xe9200000 | (A$sp << 16) | (rs))
62 | #define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */
63 | #define A$bx_r0 0xe12fff10 /* bx r0 */
64 |
65 | #endif//SUBSTRATE_ARM_HPP
66 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateDebug.cpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #include "SubstrateHook.h"
23 | #include "SubstrateDebug.hpp"
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | _extern bool MSDebug;
31 | bool MSDebug = false;
32 |
33 | static char _MSHexChar(uint8_t value) {
34 | return value < 0x20 || value >= 0x80 ? '.' : value;
35 | }
36 |
37 | #define HexWidth_ 16
38 | #define HexDepth_ 4
39 |
40 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) {
41 | const uint8_t *data((const uint8_t *) vdata);
42 |
43 | size_t i(0), j;
44 |
45 | char d[256];
46 | size_t b(0);
47 | d[0] = '\0';
48 |
49 | while (i != size) {
50 | if (i % HexWidth_ == 0) {
51 | if (mark != NULL)
52 | b += sprintf(d + b, OBFUSCATE("\n[%s] "), mark);
53 | b += sprintf(d + b, OBFUSCATE("0x%.3zx:"), i);
54 | }
55 |
56 | b += sprintf(d + b, " ");
57 |
58 | for (size_t q(0); q != stride; ++q)
59 | b += sprintf(d + b, OBFUSCATE("%.2x"), data[i + stride - q - 1]);
60 |
61 | i += stride;
62 |
63 | for (size_t q(1); q != stride; ++q)
64 | b += sprintf(d + b, " ");
65 |
66 | if (i % HexDepth_ == 0)
67 | b += sprintf(d + b, " ");
68 |
69 | if (i % HexWidth_ == 0) {
70 | b += sprintf(d + b, " ");
71 | for (j = i - HexWidth_; j != i; ++j)
72 | b += sprintf(d + b, "%c", _MSHexChar(data[j]));
73 |
74 | lprintf("%s", d);
75 | b = 0;
76 | d[0] = '\0';
77 | }
78 | }
79 |
80 | if (i % HexWidth_ != 0) {
81 | for (j = i % HexWidth_; j != HexWidth_; ++j)
82 | b += sprintf(d + b, " ");
83 | for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j)
84 | b += sprintf(d + b, " ");
85 | b += sprintf(d + b, " ");
86 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j)
87 | b += sprintf(d + b, OBFUSCATE("%c"), _MSHexChar(data[j]));
88 |
89 | // lprintf("%s", d);
90 | b = 0;
91 | d[0] = '\0';
92 | }
93 | }
94 |
95 | void MSLogHex(const void *vdata, size_t size, const char *mark) {
96 | return MSLogHexEx(vdata, size, 1, mark);
97 | }
98 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateDebug.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_DEBUG_HPP
23 | #define SUBSTRATE_DEBUG_HPP
24 |
25 | #include "SubstrateLog.hpp"
26 | #define lprintf(format, ...) \
27 | MSLog(MSLogLevelNotice, format, ## __VA_ARGS__)
28 |
29 | extern "C" bool MSDebug;
30 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0);
31 | void MSLogHex(const void *vdata, size_t size, const char *mark = 0);
32 |
33 | #endif//SUBSTRATE_DEBUG_HPP
34 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateHook.h:
--------------------------------------------------------------------------------
1 | #ifndef __SUBSTRATEHOOK_H__
2 | #define __SUBSTRATEHOOK_H__
3 |
4 |
5 | #include
6 |
7 | #define _extern extern "C" __attribute__((__visibility__("default")))
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 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateLog.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_LOG_HPP
23 | #define SUBSTRATE_LOG_HPP
24 |
25 | #if 0
26 | #include
27 |
28 | #define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__))
29 |
30 | #define MSLogLevelNotice ANDROID_LOG_INFO
31 | #define MSLogLevelWarning ANDROID_LOG_WARN
32 | #define MSLogLevelError ANDROID_LOG_ERROR
33 |
34 | #else
35 |
36 | #define MSLog(level, format, ...) printf(format, __VA_ARGS__)
37 |
38 | #endif
39 |
40 | #endif//SUBSTRATE_LOG_HPP
41 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstratePosixMemory.cpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #define SubstrateInternal
23 | #include "CydiaSubstrate.h"
24 | #include "SubstrateLog.hpp"
25 |
26 | #include
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | extern "C" void __clear_cache (void *beg, void *end);
34 |
35 | struct __SubstrateMemory {
36 | void *address_;
37 | size_t width_;
38 |
39 | __SubstrateMemory(void *address, size_t width) :
40 | address_(address),
41 | width_(width)
42 | {
43 | }
44 | };
45 |
46 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) {
47 | if (allocator != NULL) {
48 | MSLog(MSLogLevelError, OBFUSCATE("MS:Error:allocator != %d"), 0);
49 | return NULL;
50 | }
51 |
52 | if (size == 0)
53 | return NULL;
54 |
55 | int page(getpagesize());
56 |
57 | uintptr_t base(reinterpret_cast(data) / page * page);
58 | size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base);
59 | void *address(reinterpret_cast(base));
60 |
61 | if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
62 | MSLog(MSLogLevelError, OBFUSCATE("MS:Error:mprotect() = %d"), errno);
63 | return NULL;
64 | }
65 |
66 | return new __SubstrateMemory(address, width);
67 | }
68 |
69 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) {
70 | if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
71 | MSLog(MSLogLevelError, "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 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SubstrateX86.hpp:
--------------------------------------------------------------------------------
1 | /* Cydia Substrate - Powerful Code Insertion Platform
2 | * Copyright (C) 2008-2011 Jay Freeman (saurik)
3 | */
4 |
5 | /* GNU Lesser General Public License, Version 3 {{{ */
6 | /*
7 | * Substrate is free software: you can redistribute it and/or modify it under
8 | * the terms of the GNU Lesser General Public License as published by the
9 | * Free Software Foundation, either version 3 of the License, or (at your
10 | * option) any later version.
11 | *
12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 | * License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with Substrate. If not, see .
19 | **/
20 | /* }}} */
21 |
22 | #ifndef SUBSTRATE_X86_HPP
23 | #define SUBSTRATE_X86_HPP
24 |
25 | #include "Buffer.hpp"
26 |
27 | #ifdef __LP64__
28 | static const bool ia32 = false;
29 | #else
30 | static const bool ia32 = true;
31 | #endif
32 |
33 | enum I$r {
34 | I$rax, I$rcx, I$rdx, I$rbx,
35 | I$rsp, I$rbp, I$rsi, I$rdi,
36 | I$r8, I$r9, I$r10, I$r11,
37 | I$r12, I$r13, I$r14, I$r15,
38 | };
39 |
40 | _disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) {
41 | intptr_t offset(target - source);
42 | return int32_t(offset) == offset;
43 | }
44 |
45 | _disused static size_t MSSizeOfSkip() {
46 | return 5;
47 | }
48 |
49 | _disused static size_t MSSizeOfPushPointer(uintptr_t target) {
50 | return uint64_t(target) >> 32 == 0 ? 5 : 13;
51 | }
52 |
53 | _disused static size_t MSSizeOfPushPointer(void *target) {
54 | return MSSizeOfPushPointer(reinterpret_cast(target));
55 | }
56 |
57 | _disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) {
58 | if (ia32 || !blind && MSIs32BitOffset(target, source + 5))
59 | return MSSizeOfSkip();
60 | else
61 | return MSSizeOfPushPointer(target) + 1;
62 | }
63 |
64 | _disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) {
65 | return MSSizeOfJump(false, target, source);
66 | }
67 |
68 | _disused static size_t MSSizeOfJump(uintptr_t target) {
69 | return MSSizeOfJump(true, target);
70 | }
71 |
72 | _disused static size_t MSSizeOfJump(void *target, void *source) {
73 | return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source));
74 | }
75 |
76 | _disused static size_t MSSizeOfJump(void *target) {
77 | return MSSizeOfJump(reinterpret_cast(target));
78 | }
79 |
80 | _disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) {
81 | MSWrite(current, 0xe9);
82 | MSWrite(current, size);
83 | }
84 |
85 | _disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) {
86 | MSWrite(current, 0x68);
87 | MSWrite(current, target);
88 |
89 | if (uint32_t high = uint64_t(target) >> 32) {
90 | MSWrite(current, 0xc7);
91 | MSWrite(current, 0x44);
92 | MSWrite(current, 0x24);
93 | MSWrite(current, 0x04);
94 | MSWrite(current, high);
95 | }
96 | }
97 |
98 | _disused static void MSPushPointer(uint8_t *¤t, void *target) {
99 | return MSPushPointer(current, reinterpret_cast(target));
100 | }
101 |
102 | _disused static void MSWriteCall(uint8_t *¤t, I$r target) {
103 | if (target >> 3 != 0)
104 | MSWrite(current, 0x40 | (target & 0x08) >> 3);
105 | MSWrite(current, 0xff);
106 | MSWrite(current, 0xd0 | target & 0x07);
107 | }
108 |
109 | _disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) {
110 | uintptr_t source(reinterpret_cast(current));
111 |
112 | if (ia32 || MSIs32BitOffset(target, source + 5)) {
113 | MSWrite(current, 0xe8);
114 | MSWrite(current, target - (source + 5));
115 | } else {
116 | MSPushPointer(current, target);
117 |
118 | MSWrite(current, 0x83);
119 | MSWrite(current, 0xc4);
120 | MSWrite(current, 0x08);
121 |
122 | MSWrite(current, 0x67);
123 | MSWrite(current, 0xff);
124 | MSWrite(current, 0x54);
125 | MSWrite(current, 0x24);
126 | MSWrite(current, 0xf8);
127 | }
128 | }
129 |
130 | template
131 | _disused static void MSWriteCall(uint8_t *¤t, Type_ *target) {
132 | return MSWriteCall(current, reinterpret_cast(target));
133 | }
134 |
135 | _disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) {
136 | uintptr_t source(reinterpret_cast(current));
137 |
138 | if (ia32 || MSIs32BitOffset(target, source + 5))
139 | MSWriteSkip(current, target - (source + 5));
140 | else {
141 | MSPushPointer(current, target);
142 | MSWrite(current, 0xc3);
143 | }
144 | }
145 |
146 | _disused static void MSWriteJump(uint8_t *¤t, void *target) {
147 | return MSWriteJump(current, reinterpret_cast(target));
148 | }
149 |
150 | _disused static void MSWriteJump(uint8_t *¤t, I$r target) {
151 | if (target >> 3 != 0)
152 | MSWrite(current, 0x40 | (target & 0x08) >> 3);
153 | MSWrite(current, 0xff);
154 | MSWrite(current, 0xe0 | target & 0x07);
155 | }
156 |
157 | _disused static void MSWritePop(uint8_t *¤t, uint8_t target) {
158 | if (target >> 3 != 0)
159 | MSWrite(current, 0x40 | (target & 0x08) >> 3);
160 | MSWrite(current, 0x58 | target & 0x07);
161 | }
162 |
163 | _disused static size_t MSSizeOfPop(uint8_t target) {
164 | return target >> 3 != 0 ? 2 : 1;
165 | }
166 |
167 | _disused static void MSWritePush(uint8_t *¤t, I$r target) {
168 | if (target >> 3 != 0)
169 | MSWrite(current, 0x40 | (target & 0x08) >> 3);
170 | MSWrite(current, 0x50 | target & 0x07);
171 | }
172 |
173 | _disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) {
174 | MSWrite(current, 0x83);
175 | MSWrite(current, 0xc4 | target & 0x07);
176 | MSWrite(current, source);
177 | }
178 |
179 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) {
180 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2);
181 | MSWrite(current, 0xb8 | target & 0x7);
182 | MSWrite(current, source);
183 | }
184 |
185 | template
186 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) {
187 | return MSWriteSet64(current, target, reinterpret_cast(source));
188 | }
189 |
190 | _disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) {
191 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3);
192 | MSWrite(current, 0x8b);
193 | MSWrite(current, (target & 0x07) << 3 | source & 0x07);
194 | }
195 |
196 | _disused static size_t MSSizeOfMove64() {
197 | return 3;
198 | }
199 |
200 | #endif//SUBSTRATE_X86_HPP
201 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/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 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/SymbolFinder.h:
--------------------------------------------------------------------------------
1 | #ifndef SYMBOL_FINDER
2 | #define SYMBOL_FINDER
3 |
4 | #include
5 |
6 | extern int find_name(pid_t pid, const char *name,const char *libn, unsigned long *addr);
7 | extern int find_libbase(pid_t pid, const char *libn, unsigned long *addr);
8 | #endif
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/hde64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include "hde64.h"
12 | #include "table64.h"
13 |
14 | unsigned int hde64_disasm(const void *code, hde64s *hs)
15 | {
16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
17 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
18 | uint8_t op64 = 0;
19 |
20 | memset(hs,0,sizeof(hde64s));
21 | char *tmp=(char*)hs;
22 |
23 | for (x = 16; x; x--)
24 | switch (c = *p++) {
25 | case 0xf3:
26 | hs->p_rep = c;
27 | pref |= PRE_F3;
28 | break;
29 | case 0xf2:
30 | hs->p_rep = c;
31 | pref |= PRE_F2;
32 | break;
33 | case 0xf0:
34 | hs->p_lock = c;
35 | pref |= PRE_LOCK;
36 | break;
37 | case 0x26: case 0x2e: case 0x36:
38 | case 0x3e: case 0x64: case 0x65:
39 | hs->p_seg = c;
40 | pref |= PRE_SEG;
41 | break;
42 | case 0x66:
43 | hs->p_66 = c;
44 | pref |= PRE_66;
45 | break;
46 | case 0x67:
47 | hs->p_67 = c;
48 | pref |= PRE_67;
49 | break;
50 | default:
51 | goto pref_done;
52 | }
53 | pref_done:
54 |
55 | hs->flags = (uint32_t)pref << 23;
56 |
57 | if (!pref)
58 | pref |= PRE_NONE;
59 |
60 | if ((c & 0xf0) == 0x40) {
61 | hs->flags |= F_PREFIX_REX;
62 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
63 | op64++;
64 | hs->rex_r = (c & 7) >> 2;
65 | hs->rex_x = (c & 3) >> 1;
66 | hs->rex_b = c & 1;
67 | if (((c = *p++) & 0xf0) == 0x40) {
68 | opcode = c;
69 | goto error_opcode;
70 | }
71 | }
72 |
73 | if ((hs->opcode = c) == 0x0f) {
74 | hs->opcode2 = c = *p++;
75 | ht += DELTA_OPCODES;
76 | } else if (c >= 0xa0 && c <= 0xa3) {
77 | op64++;
78 | if (pref & PRE_67)
79 | pref |= PRE_66;
80 | else
81 | pref &= ~PRE_66;
82 | }
83 |
84 | opcode = c;
85 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
86 |
87 | if (cflags == C_ERROR) {
88 | error_opcode:
89 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
90 | cflags = 0;
91 | if ((opcode & -3) == 0x24)
92 | cflags++;
93 | }
94 |
95 | x = 0;
96 | if (cflags & C_GROUP) {
97 | uint16_t t;
98 | t = *(uint16_t *)(ht + (cflags & 0x7f));
99 | cflags = (uint8_t)t;
100 | x = (uint8_t)(t >> 8);
101 | }
102 |
103 | if (hs->opcode2) {
104 | ht = hde64_table + DELTA_PREFIXES;
105 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
106 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
107 | }
108 |
109 | if (cflags & C_MODRM) {
110 | hs->flags |= F_MODRM;
111 | hs->modrm = c = *p++;
112 | hs->modrm_mod = m_mod = c >> 6;
113 | hs->modrm_rm = m_rm = c & 7;
114 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
115 |
116 | if (x && ((x << m_reg) & 0x80))
117 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
118 |
119 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
120 | uint8_t t = opcode - 0xd9;
121 | if (m_mod == 3) {
122 | ht = hde64_table + DELTA_FPU_MODRM + t*8;
123 | t = ht[m_reg] << m_rm;
124 | } else {
125 | ht = hde64_table + DELTA_FPU_REG;
126 | t = ht[t] << m_reg;
127 | }
128 | if (t & 0x80)
129 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
130 | }
131 |
132 | if (pref & PRE_LOCK) {
133 | if (m_mod == 3) {
134 | hs->flags |= F_ERROR | F_ERROR_LOCK;
135 | } else {
136 | uint8_t *table_end, op = opcode;
137 | if (hs->opcode2) {
138 | ht = hde64_table + DELTA_OP2_LOCK_OK;
139 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
140 | } else {
141 | ht = hde64_table + DELTA_OP_LOCK_OK;
142 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
143 | op &= -2;
144 | }
145 | for (; ht != table_end; ht++)
146 | if (*ht++ == op) {
147 | if (!((*ht << m_reg) & 0x80))
148 | goto no_lock_error;
149 | else
150 | break;
151 | }
152 | hs->flags |= F_ERROR | F_ERROR_LOCK;
153 | no_lock_error:
154 | ;
155 | }
156 | }
157 |
158 | if (hs->opcode2) {
159 | switch (opcode) {
160 | case 0x20: case 0x22:
161 | m_mod = 3;
162 | if (m_reg > 4 || m_reg == 1)
163 | goto error_operand;
164 | else
165 | goto no_error_operand;
166 | case 0x21: case 0x23:
167 | m_mod = 3;
168 | if (m_reg == 4 || m_reg == 5)
169 | goto error_operand;
170 | else
171 | goto no_error_operand;
172 | }
173 | } else {
174 | switch (opcode) {
175 | case 0x8c:
176 | if (m_reg > 5)
177 | goto error_operand;
178 | else
179 | goto no_error_operand;
180 | case 0x8e:
181 | if (m_reg == 1 || m_reg > 5)
182 | goto error_operand;
183 | else
184 | goto no_error_operand;
185 | }
186 | }
187 |
188 | if (m_mod == 3) {
189 | uint8_t *table_end;
190 | if (hs->opcode2) {
191 | ht = hde64_table + DELTA_OP2_ONLY_MEM;
192 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
193 | } else {
194 | ht = hde64_table + DELTA_OP_ONLY_MEM;
195 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
196 | }
197 | for (; ht != table_end; ht += 2)
198 | if (*ht++ == opcode) {
199 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
200 | goto error_operand;
201 | else
202 | break;
203 | }
204 | goto no_error_operand;
205 | } else if (hs->opcode2) {
206 | switch (opcode) {
207 | case 0x50: case 0xd7: case 0xf7:
208 | if (pref & (PRE_NONE | PRE_66))
209 | goto error_operand;
210 | break;
211 | case 0xd6:
212 | if (pref & (PRE_F2 | PRE_F3))
213 | goto error_operand;
214 | break;
215 | case 0xc5:
216 | goto error_operand;
217 | }
218 | goto no_error_operand;
219 | } else
220 | goto no_error_operand;
221 |
222 | error_operand:
223 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
224 | no_error_operand:
225 |
226 | c = *p++;
227 | if (m_reg <= 1) {
228 | if (opcode == 0xf6)
229 | cflags |= C_IMM8;
230 | else if (opcode == 0xf7)
231 | cflags |= C_IMM_P66;
232 | }
233 |
234 | switch (m_mod) {
235 | case 0:
236 | if (pref & PRE_67) {
237 | if (m_rm == 6)
238 | disp_size = 2;
239 | } else
240 | if (m_rm == 5)
241 | disp_size = 4;
242 | break;
243 | case 1:
244 | disp_size = 1;
245 | break;
246 | case 2:
247 | disp_size = 2;
248 | if (!(pref & PRE_67))
249 | disp_size <<= 1;
250 | }
251 |
252 | if (m_mod != 3 && m_rm == 4) {
253 | hs->flags |= F_SIB;
254 | p++;
255 | hs->sib = c;
256 | hs->sib_scale = c >> 6;
257 | hs->sib_index = (c & 0x3f) >> 3;
258 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
259 | disp_size = 4;
260 | }
261 |
262 | p--;
263 | switch (disp_size) {
264 | case 1:
265 | hs->flags |= F_DISP8;
266 | hs->disp.disp8 = *p;
267 | break;
268 | case 2:
269 | hs->flags |= F_DISP16;
270 | hs->disp.disp16 = *(uint16_t *)p;
271 | break;
272 | case 4:
273 | hs->flags |= F_DISP32;
274 | hs->disp.disp32 = *(uint32_t *)p;
275 | }
276 | p += disp_size;
277 | } else if (pref & PRE_LOCK)
278 | hs->flags |= F_ERROR | F_ERROR_LOCK;
279 |
280 | if (cflags & C_IMM_P66) {
281 | if (cflags & C_REL32) {
282 | if (pref & PRE_66) {
283 | hs->flags |= F_IMM16 | F_RELATIVE;
284 | hs->imm.imm16 = *(uint16_t *)p;
285 | p += 2;
286 | goto disasm_done;
287 | }
288 | goto rel32_ok;
289 | }
290 | if (op64) {
291 | hs->flags |= F_IMM64;
292 | hs->imm.imm64 = *(uint64_t *)p;
293 | p += 8;
294 | } else if (!(pref & PRE_66)) {
295 | hs->flags |= F_IMM32;
296 | hs->imm.imm32 = *(uint32_t *)p;
297 | p += 4;
298 | } else
299 | goto imm16_ok;
300 | }
301 |
302 |
303 | if (cflags & C_IMM16) {
304 | imm16_ok:
305 | hs->flags |= F_IMM16;
306 | hs->imm.imm16 = *(uint16_t *)p;
307 | p += 2;
308 | }
309 | if (cflags & C_IMM8) {
310 | hs->flags |= F_IMM8;
311 | hs->imm.imm8 = *p++;
312 | }
313 |
314 | if (cflags & C_REL32) {
315 | rel32_ok:
316 | hs->flags |= F_IMM32 | F_RELATIVE;
317 | hs->imm.imm32 = *(uint32_t *)p;
318 | p += 4;
319 | } else if (cflags & C_REL8) {
320 | hs->flags |= F_IMM8 | F_RELATIVE;
321 | hs->imm.imm8 = *p++;
322 | }
323 |
324 | disasm_done:
325 |
326 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
327 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
328 | hs->len = 15;
329 | }
330 |
331 | return (unsigned int)hs->len;
332 | }
333 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/hde64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | * hde64.h: C/C++ header file
7 | *
8 | */
9 |
10 | #ifndef _HDE64_H_
11 | #define _HDE64_H_
12 |
13 | /* stdint.h - C99 standard header
14 | * http://en.wikipedia.org/wiki/stdint.h
15 | *
16 | * if your compiler doesn't contain "stdint.h" header (for
17 | * example, Microsoft Visual C++), you can download file:
18 | * http://www.azillionmonkeys.com/qed/pstdint.h
19 | * and change next line to:
20 | * #include "pstdint.h"
21 | */
22 | #include
23 |
24 | #define F_MODRM 0x00000001
25 | #define F_SIB 0x00000002
26 | #define F_IMM8 0x00000004
27 | #define F_IMM16 0x00000008
28 | #define F_IMM32 0x00000010
29 | #define F_IMM64 0x00000020
30 | #define F_DISP8 0x00000040
31 | #define F_DISP16 0x00000080
32 | #define F_DISP32 0x00000100
33 | #define F_RELATIVE 0x00000200
34 | #define F_ERROR 0x00001000
35 | #define F_ERROR_OPCODE 0x00002000
36 | #define F_ERROR_LENGTH 0x00004000
37 | #define F_ERROR_LOCK 0x00008000
38 | #define F_ERROR_OPERAND 0x00010000
39 | #define F_PREFIX_REPNZ 0x01000000
40 | #define F_PREFIX_REPX 0x02000000
41 | #define F_PREFIX_REP 0x03000000
42 | #define F_PREFIX_66 0x04000000
43 | #define F_PREFIX_67 0x08000000
44 | #define F_PREFIX_LOCK 0x10000000
45 | #define F_PREFIX_SEG 0x20000000
46 | #define F_PREFIX_REX 0x40000000
47 | #define F_PREFIX_ANY 0x7f000000
48 |
49 | #define PREFIX_SEGMENT_CS 0x2e
50 | #define PREFIX_SEGMENT_SS 0x36
51 | #define PREFIX_SEGMENT_DS 0x3e
52 | #define PREFIX_SEGMENT_ES 0x26
53 | #define PREFIX_SEGMENT_FS 0x64
54 | #define PREFIX_SEGMENT_GS 0x65
55 | #define PREFIX_LOCK 0xf0
56 | #define PREFIX_REPNZ 0xf2
57 | #define PREFIX_REPX 0xf3
58 | #define PREFIX_OPERAND_SIZE 0x66
59 | #define PREFIX_ADDRESS_SIZE 0x67
60 |
61 | #pragma pack(push,1)
62 |
63 | typedef struct {
64 | uint8_t len;
65 | uint8_t p_rep;
66 | uint8_t p_lock;
67 | uint8_t p_seg;
68 | uint8_t p_66;
69 | uint8_t p_67;
70 | uint8_t rex;
71 | uint8_t rex_w;
72 | uint8_t rex_r;
73 | uint8_t rex_x;
74 | uint8_t rex_b;
75 | uint8_t opcode;
76 | uint8_t opcode2;
77 | uint8_t modrm;
78 | uint8_t modrm_mod;
79 | uint8_t modrm_reg;
80 | uint8_t modrm_rm;
81 | uint8_t sib;
82 | uint8_t sib_scale;
83 | uint8_t sib_index;
84 | uint8_t sib_base;
85 | union {
86 | uint8_t imm8;
87 | uint16_t imm16;
88 | uint32_t imm32;
89 | uint64_t imm64;
90 | } imm;
91 | union {
92 | uint8_t disp8;
93 | uint16_t disp16;
94 | uint32_t disp32;
95 | } disp;
96 | uint32_t flags;
97 | } hde64s;
98 |
99 | #pragma pack(pop)
100 |
101 | #ifdef __cplusplus
102 | extern "C" {
103 | #endif
104 |
105 | /* __cdecl */
106 | unsigned int hde64_disasm(const void *code, hde64s *hs);
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* _HDE64_H_ */
113 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Substrate/table64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #define C_NONE 0x00
9 | #define C_MODRM 0x01
10 | #define C_IMM8 0x02
11 | #define C_IMM16 0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8 0x20
14 | #define C_REL32 0x40
15 | #define C_GROUP 0x80
16 | #define C_ERROR 0xff
17 |
18 | #define PRE_ANY 0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2 0x02
21 | #define PRE_F3 0x04
22 | #define PRE_66 0x08
23 | #define PRE_67 0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG 0x40
26 | #define PRE_ALL 0xff
27 |
28 | #define DELTA_OPCODES 0x4a
29 | #define DELTA_FPU_REG 0xfd
30 | #define DELTA_FPU_MODRM 0x104
31 | #define DELTA_PREFIXES 0x13c
32 | #define DELTA_OP_LOCK_OK 0x1ae
33 | #define DELTA_OP2_LOCK_OK 0x1c6
34 | #define DELTA_OP_ONLY_MEM 0x1d8
35 | #define DELTA_OP2_ONLY_MEM 0x1e7
36 |
37 | unsigned char hde64_table[] = {
38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
73 | 0x00,0xf0,0x02,0x00
74 | };
75 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/jni/Toast.h:
--------------------------------------------------------------------------------
1 | #ifndef LGL_IL2CPP_MENU_TOAST_H
2 | #define LGL_IL2CPP_MENU_TOAST_H
3 |
4 | extern "C" {
5 | JNIEXPORT void JNICALL
6 | Java_uk_lgl_NativeToast_Toast(JNIEnv *env, jclass obj, jobject context, jint numOfMessage) {
7 | if (numOfMessage == 0){
8 | MakeToast(env, context, OBFUSCATE("Modded by Hollow Modz"), Toast::LENGTH_LONG);
9 | }
10 | if (numOfMessage == 0){
11 | MakeToast(env, context, OBFUSCATE("Polarmods.com | for top tier mods"), Toast::LENGTH_LONG);
12 | }
13 | if (numOfMessage == 0){
14 | MakeToast(env, context, OBFUSCATE("Check out my channel"), Toast::LENGTH_LONG);
15 | }
16 | if (numOfMessage == 1){
17 | MakeToast(env, context, OBFUSCATE("Icon hidden. Remember the hidden icon position"), Toast::LENGTH_LONG);
18 | }
19 | if (numOfMessage == 2){
20 | MakeToast(env, context, OBFUSCATE("Menu service killed"), Toast::LENGTH_LONG);
21 | }
22 | }
23 | }
24 |
25 | #endif //LGL_IL2CPP_MENU_TOAST_H
26 |
--------------------------------------------------------------------------------
/Android-Mod-Menu-master/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |