├── @@PROJECTNAME@@.plist ├── LICENSE ├── Lib ├── Keystone │ ├── arm64 │ │ └── libkeystone.a │ ├── arm64e │ │ └── libkeystone.a │ ├── arm64e_old │ │ └── libkeystone.a │ └── includes │ │ ├── arm.h │ │ ├── arm64.h │ │ ├── evm.h │ │ ├── hexagon.h │ │ ├── keystone.h │ │ ├── mips.h │ │ ├── ppc.h │ │ ├── riscv.h │ │ ├── sparc.h │ │ ├── systemz.h │ │ └── x86.h ├── Obfuscation │ └── Obfuscate.h └── Resolver │ ├── API │ ├── Class.hpp │ ├── Domain.hpp │ ├── Image.hpp │ ├── ResolveCall.hpp │ ├── String.hpp │ └── Thread.hpp │ ├── Data.hpp │ ├── Defines.hpp │ ├── IL2CPP_Resolver.hpp │ ├── SystemTypeCache.hpp │ ├── Unity │ ├── API │ │ ├── Camera.hpp │ │ ├── Component.hpp │ │ ├── GameObject.hpp │ │ ├── LayerMask.hpp │ │ ├── Object.hpp │ │ ├── Rigidbody.hpp │ │ └── Transform.hpp │ ├── Defines.hpp │ ├── Obfuscators.hpp │ └── Structures │ │ ├── Engine.hpp │ │ ├── System_String.hpp │ │ ├── il2cpp.hpp │ │ ├── il2cppArray.hpp │ │ └── il2cppDictionary.hpp │ └── Utils │ ├── Hash.hpp │ ├── Helper.hpp │ ├── MemoryInfo.hpp │ └── Types │ ├── Quaternion.hpp │ ├── Vector2.hpp │ └── Vector3.hpp ├── Makefile ├── NIC ├── control └── control.pl ├── README.md ├── Source ├── Config.h ├── Framework │ ├── Framework.h │ └── Framework.mm ├── Memory │ ├── Helper.h │ ├── Helper.mm │ ├── Hook │ │ ├── Hook.h │ │ └── Hook.mm │ ├── Kitty │ │ ├── KittyArm64.cpp │ │ ├── KittyArm64.hpp │ │ ├── KittyInclude.hpp │ │ ├── KittyMemory.cpp │ │ ├── KittyMemory.hpp │ │ ├── KittyScanner.cpp │ │ ├── KittyScanner.hpp │ │ ├── KittyUtils.cpp │ │ ├── KittyUtils.hpp │ │ ├── MemoryBackup.cpp │ │ ├── MemoryBackup.hpp │ │ ├── MemoryPatch.cpp │ │ ├── MemoryPatch.hpp │ │ └── writeData.hpp │ ├── Memory.h │ ├── Patch │ │ ├── Patch.h │ │ └── Patch.mm │ └── Thread │ │ ├── Thread.h │ │ └── Thread.mm └── UI │ ├── Icons.h │ ├── Icons.mm │ ├── Menu.h │ ├── Menu.mm │ └── UI.h ├── Tweak.mm ├── Upload.sh └── control /@@PROJECTNAME@@.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | @@FILTER@@ 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Lib/Keystone/arm64/libkeystone.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Batchhh/SilentPwn/77a882ca714794605926c088282140eadd13a20e/Lib/Keystone/arm64/libkeystone.a -------------------------------------------------------------------------------- /Lib/Keystone/arm64e/libkeystone.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Batchhh/SilentPwn/77a882ca714794605926c088282140eadd13a20e/Lib/Keystone/arm64e/libkeystone.a -------------------------------------------------------------------------------- /Lib/Keystone/arm64e_old/libkeystone.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Batchhh/SilentPwn/77a882ca714794605926c088282140eadd13a20e/Lib/Keystone/arm64e_old/libkeystone.a -------------------------------------------------------------------------------- /Lib/Keystone/includes/arm.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_ARM_H 5 | #define KEYSTONE_ARM_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_arm { 14 | KS_ERR_ASM_ARM_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_ARM_MISSINGFEATURE, 16 | KS_ERR_ASM_ARM_MNEMONICFAIL, 17 | } ks_err_asm_arm; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/arm64.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_ARM64_H 5 | #define KEYSTONE_ARM64_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_arm64 { 14 | KS_ERR_ASM_ARM64_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_ARM64_MISSINGFEATURE, 16 | KS_ERR_ASM_ARM64_MNEMONICFAIL, 17 | } ks_err_asm_arm64; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/evm.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016-2018 */ 3 | 4 | #ifndef KEYSTONE_EVM_H 5 | #define KEYSTONE_EVM_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_evm { 14 | KS_ERR_ASM_EVM_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_EVM_MISSINGFEATURE, 16 | KS_ERR_ASM_EVM_MNEMONICFAIL, 17 | } ks_err_asm_evm; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/hexagon.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_HEXAGON_H 5 | #define KEYSTONE_HEXAGON_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_hexagon { 14 | KS_ERR_ASM_HEXAGON_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_HEXAGON_MISSINGFEATURE, 16 | KS_ERR_ASM_HEXAGON_MNEMONICFAIL, 17 | } ks_err_asm_hexagon; 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/keystone.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine (www.keystone-engine.org) */ 2 | /* By Nguyen Anh Quynh , 2016 */ 3 | 4 | #ifndef KEYSTONE_ENGINE_H 5 | #define KEYSTONE_ENGINE_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #ifndef _STDINT_H_ 12 | #include 13 | #endif 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef _MSC_VER // MSVC compiler 19 | #pragma warning(disable:4201) 20 | #pragma warning(disable:4100) 21 | #ifndef KEYSTONE_STATIC 22 | #define KEYSTONE_EXPORT __declspec(dllexport) 23 | #else 24 | #define KEYSTONE_EXPORT 25 | #endif 26 | #else 27 | #ifdef __GNUC__ 28 | #include 29 | #ifndef KEYSTONE_STATIC 30 | #define KEYSTONE_EXPORT __attribute__((visibility("default"))) 31 | #else 32 | #define KEYSTONE_EXPORT 33 | #endif 34 | #else 35 | #define KEYSTONE_EXPORT 36 | #endif 37 | #endif 38 | 39 | 40 | struct ks_struct; 41 | typedef struct ks_struct ks_engine; 42 | 43 | // Keystone API version 44 | #define KS_API_MAJOR 0 45 | #define KS_API_MINOR 9 46 | 47 | // Package version 48 | #define KS_VERSION_MAJOR KS_API_MAJOR 49 | #define KS_VERSION_MINOR KS_API_MINOR 50 | #define KS_VERSION_EXTRA 2 51 | 52 | /* 53 | Macro to create combined version which can be compared to 54 | result of ks_version() API. 55 | */ 56 | #define KS_MAKE_VERSION(major, minor) ((major << 8) + minor) 57 | 58 | // Architecture type 59 | typedef enum ks_arch { 60 | KS_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) 61 | KS_ARCH_ARM64, // ARM-64, also called AArch64 62 | KS_ARCH_MIPS, // Mips architecture 63 | KS_ARCH_X86, // X86 architecture (including x86 & x86-64) 64 | KS_ARCH_PPC, // PowerPC architecture (currently unsupported) 65 | KS_ARCH_SPARC, // Sparc architecture 66 | KS_ARCH_SYSTEMZ, // SystemZ architecture (S390X) 67 | KS_ARCH_HEXAGON, // Hexagon architecture 68 | KS_ARCH_EVM, // Ethereum Virtual Machine architecture 69 | KS_ARCH_RISCV, // RISC-V architecture 70 | KS_ARCH_MAX, 71 | } ks_arch; 72 | 73 | // Mode type 74 | typedef enum ks_mode { 75 | KS_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) 76 | KS_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode 77 | // arm / arm64 78 | KS_MODE_ARM = 1 << 0, // ARM mode 79 | KS_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) 80 | KS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM 81 | // mips 82 | KS_MODE_MICRO = 1 << 4, // MicroMips mode 83 | KS_MODE_MIPS3 = 1 << 5, // Mips III ISA 84 | KS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA 85 | KS_MODE_MIPS32 = 1 << 2, // Mips32 ISA 86 | KS_MODE_MIPS64 = 1 << 3, // Mips64 ISA 87 | // x86 / x64 88 | KS_MODE_16 = 1 << 1, // 16-bit mode 89 | KS_MODE_32 = 1 << 2, // 32-bit mode 90 | KS_MODE_64 = 1 << 3, // 64-bit mode 91 | // ppc 92 | KS_MODE_PPC32 = 1 << 2, // 32-bit mode 93 | KS_MODE_PPC64 = 1 << 3, // 64-bit mode 94 | KS_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode 95 | //riscv 96 | KS_MODE_RISCV32 = 1 << 2, // 32-bit mode 97 | KS_MODE_RISCV64 = 1 << 3, // 64-bit mode 98 | // sparc 99 | KS_MODE_SPARC32 = 1 << 2, // 32-bit mode 100 | KS_MODE_SPARC64 = 1 << 3, // 64-bit mode 101 | KS_MODE_V9 = 1 << 4, // SparcV9 mode 102 | } ks_mode; 103 | 104 | // All generic errors related to input assembly >= KS_ERR_ASM 105 | #define KS_ERR_ASM 128 106 | 107 | // All architecture-specific errors related to input assembly >= KS_ERR_ASM_ARCH 108 | #define KS_ERR_ASM_ARCH 512 109 | 110 | // All type of errors encountered by Keystone API. 111 | typedef enum ks_err { 112 | KS_ERR_OK = 0, // No error: everything was fine 113 | KS_ERR_NOMEM, // Out-Of-Memory error: ks_open(), ks_emulate() 114 | KS_ERR_ARCH, // Unsupported architecture: ks_open() 115 | KS_ERR_HANDLE, // Invalid handle 116 | KS_ERR_MODE, // Invalid/unsupported mode: ks_open() 117 | KS_ERR_VERSION, // Unsupported version (bindings) 118 | KS_ERR_OPT_INVALID, // Unsupported option 119 | 120 | // generic input assembly errors - parser specific 121 | KS_ERR_ASM_EXPR_TOKEN = KS_ERR_ASM, // unknown token in expression 122 | KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, // literal value out of range for directive 123 | KS_ERR_ASM_DIRECTIVE_ID, // expected identifier in directive 124 | KS_ERR_ASM_DIRECTIVE_TOKEN, // unexpected token in directive 125 | KS_ERR_ASM_DIRECTIVE_STR, // expected string in directive 126 | KS_ERR_ASM_DIRECTIVE_COMMA, // expected comma in directive 127 | KS_ERR_ASM_DIRECTIVE_RELOC_NAME, // expected relocation name in directive 128 | KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, // unexpected token in .reloc directive 129 | KS_ERR_ASM_DIRECTIVE_FPOINT, // invalid floating point in directive 130 | KS_ERR_ASM_DIRECTIVE_UNKNOWN, // unknown directive 131 | KS_ERR_ASM_DIRECTIVE_EQU, // invalid equal directive 132 | KS_ERR_ASM_DIRECTIVE_INVALID, // (generic) invalid directive 133 | KS_ERR_ASM_VARIANT_INVALID, // invalid variant 134 | KS_ERR_ASM_EXPR_BRACKET, // brackets expression not supported on this target 135 | KS_ERR_ASM_SYMBOL_MODIFIER, // unexpected symbol modifier following '@' 136 | KS_ERR_ASM_SYMBOL_REDEFINED, // invalid symbol redefinition 137 | KS_ERR_ASM_SYMBOL_MISSING, // cannot find a symbol 138 | KS_ERR_ASM_RPAREN, // expected ')' in parentheses expression 139 | KS_ERR_ASM_STAT_TOKEN, // unexpected token at start of statement 140 | KS_ERR_ASM_UNSUPPORTED, // unsupported token yet 141 | KS_ERR_ASM_MACRO_TOKEN, // unexpected token in macro instantiation 142 | KS_ERR_ASM_MACRO_PAREN, // unbalanced parentheses in macro argument 143 | KS_ERR_ASM_MACRO_EQU, // expected '=' after formal parameter identifier 144 | KS_ERR_ASM_MACRO_ARGS, // too many positional arguments 145 | KS_ERR_ASM_MACRO_LEVELS_EXCEED, // macros cannot be nested more than 20 levels deep 146 | KS_ERR_ASM_MACRO_STR, // invalid macro string 147 | KS_ERR_ASM_MACRO_INVALID, // invalid macro (generic error) 148 | KS_ERR_ASM_ESC_BACKSLASH, // unexpected backslash at end of escaped string 149 | KS_ERR_ASM_ESC_OCTAL, // invalid octal escape sequence (out of range) 150 | KS_ERR_ASM_ESC_SEQUENCE, // invalid escape sequence (unrecognized character) 151 | KS_ERR_ASM_ESC_STR, // broken escape string 152 | KS_ERR_ASM_TOKEN_INVALID, // invalid token 153 | KS_ERR_ASM_INSN_UNSUPPORTED, // this instruction is unsupported in this mode 154 | KS_ERR_ASM_FIXUP_INVALID, // invalid fixup 155 | KS_ERR_ASM_LABEL_INVALID, // invalid label 156 | KS_ERR_ASM_FRAGMENT_INVALID, // invalid fragment 157 | 158 | // generic input assembly errors - architecture specific 159 | KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH, 160 | KS_ERR_ASM_MISSINGFEATURE, 161 | KS_ERR_ASM_MNEMONICFAIL, 162 | } ks_err; 163 | 164 | // Resolver callback to provide value for a missing symbol in @symbol. 165 | // To handle a symbol, the resolver must put value of the symbol in @value, 166 | // then returns True. 167 | // If we do not resolve a missing symbol, this function must return False. 168 | // In that case, ks_asm() would eventually return with error KS_ERR_ASM_SYMBOL_MISSING. 169 | 170 | // To register the resolver, pass its function address to ks_option(), using 171 | // option KS_OPT_SYM_RESOLVER. For example, see samples/sample.c. 172 | typedef bool (*ks_sym_resolver)(const char *symbol, uint64_t *value); 173 | 174 | // Runtime option for the Keystone engine 175 | typedef enum ks_opt_type { 176 | KS_OPT_SYNTAX = 1, // Choose syntax for input assembly 177 | KS_OPT_SYM_RESOLVER, // Set symbol resolver callback 178 | } ks_opt_type; 179 | 180 | 181 | // Runtime option value (associated with ks_opt_type above) 182 | typedef enum ks_opt_value { 183 | KS_OPT_SYNTAX_INTEL = 1 << 0, // X86 Intel syntax - default on X86 (KS_OPT_SYNTAX). 184 | KS_OPT_SYNTAX_ATT = 1 << 1, // X86 ATT asm syntax (KS_OPT_SYNTAX). 185 | KS_OPT_SYNTAX_NASM = 1 << 2, // X86 Nasm syntax (KS_OPT_SYNTAX). 186 | KS_OPT_SYNTAX_MASM = 1 << 3, // X86 Masm syntax (KS_OPT_SYNTAX) - unsupported yet. 187 | KS_OPT_SYNTAX_GAS = 1 << 4, // X86 GNU GAS syntax (KS_OPT_SYNTAX). 188 | KS_OPT_SYNTAX_RADIX16 = 1 << 5, // All immediates are in hex format (i.e 12 is 0x12) 189 | } ks_opt_value; 190 | 191 | 192 | #include "arm64.h" 193 | #include "arm.h" 194 | #include "evm.h" 195 | #include "hexagon.h" 196 | #include "mips.h" 197 | #include "ppc.h" 198 | #include "riscv.h" 199 | #include "sparc.h" 200 | #include "systemz.h" 201 | #include "x86.h" 202 | 203 | /* 204 | Return combined API version & major and minor version numbers. 205 | 206 | @major: major number of API version 207 | @minor: minor number of API version 208 | 209 | @return hexical number as (major << 8 | minor), which encodes both 210 | major & minor versions. 211 | NOTE: This returned value can be compared with version number made 212 | with macro KS_MAKE_VERSION 213 | 214 | For example, second API version would return 1 in @major, and 1 in @minor 215 | The return value would be 0x0101 216 | 217 | NOTE: if you only care about returned value, but not major and minor values, 218 | set both @major & @minor arguments to NULL. 219 | */ 220 | KEYSTONE_EXPORT 221 | unsigned int ks_version(unsigned int *major, unsigned int *minor); 222 | 223 | 224 | /* 225 | Determine if the given architecture is supported by this library. 226 | 227 | @arch: architecture type (KS_ARCH_*) 228 | 229 | @return True if this library supports the given arch. 230 | */ 231 | KEYSTONE_EXPORT 232 | bool ks_arch_supported(ks_arch arch); 233 | 234 | 235 | /* 236 | Create new instance of Keystone engine. 237 | 238 | @arch: architecture type (KS_ARCH_*) 239 | @mode: hardware mode. This is combined of KS_MODE_* 240 | @ks: pointer to ks_engine, which will be updated at return time 241 | 242 | @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum 243 | for detailed error). 244 | */ 245 | KEYSTONE_EXPORT 246 | ks_err ks_open(ks_arch arch, int mode, ks_engine **ks); 247 | 248 | 249 | /* 250 | Close KS instance: MUST do to release the handle when it is not used anymore. 251 | NOTE: this must be called only when there is no longer usage of Keystone. 252 | The reason is the this API releases some cached memory, thus access to any 253 | Keystone API after ks_close() might crash your application. 254 | After this, @ks is invalid, and nolonger usable. 255 | 256 | @ks: pointer to a handle returned by ks_open() 257 | 258 | @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum 259 | for detailed error). 260 | */ 261 | KEYSTONE_EXPORT 262 | ks_err ks_close(ks_engine *ks); 263 | 264 | 265 | /* 266 | Report the last error number when some API function fail. 267 | Like glibc's errno, ks_errno might not retain its old error once accessed. 268 | 269 | @ks: handle returned by ks_open() 270 | 271 | @return: error code of ks_err enum type (KS_ERR_*, see above) 272 | */ 273 | KEYSTONE_EXPORT 274 | ks_err ks_errno(ks_engine *ks); 275 | 276 | 277 | /* 278 | Return a string describing given error code. 279 | 280 | @code: error code (see KS_ERR_* above) 281 | 282 | @return: returns a pointer to a string that describes the error code 283 | passed in the argument @code 284 | */ 285 | KEYSTONE_EXPORT 286 | const char *ks_strerror(ks_err code); 287 | 288 | 289 | /* 290 | Set option for Keystone engine at runtime 291 | 292 | @ks: handle returned by ks_open() 293 | @type: type of option to be set. See ks_opt_type 294 | @value: option value corresponding with @type 295 | 296 | @return: KS_ERR_OK on success, or other value on failure. 297 | Refer to ks_err enum for detailed error. 298 | */ 299 | KEYSTONE_EXPORT 300 | ks_err ks_option(ks_engine *ks, ks_opt_type type, size_t value); 301 | 302 | 303 | /* 304 | Assemble a string given its the buffer, size, start address and number 305 | of instructions to be decoded. 306 | This API dynamically allocate memory to contain assembled instruction. 307 | Resulted array of bytes containing the machine code is put into @*encoding 308 | 309 | NOTE 1: this API will automatically determine memory needed to contain 310 | output bytes in *encoding. 311 | 312 | NOTE 2: caller must free the allocated memory itself to avoid memory leaking. 313 | 314 | @ks: handle returned by ks_open() 315 | @str: NULL-terminated assembly string. Use ; or \n to separate statements. 316 | @address: address of the first assembly instruction, or 0 to ignore. 317 | @encoding: array of bytes containing encoding of input assembly string. 318 | NOTE: *encoding will be allocated by this function, and should be freed 319 | with ks_free() function. 320 | @encoding_size: size of *encoding 321 | @stat_count: number of statements successfully processed 322 | 323 | @return: 0 on success, or -1 on failure. 324 | 325 | On failure, call ks_errno() for error code. 326 | */ 327 | KEYSTONE_EXPORT 328 | int ks_asm(ks_engine *ks, 329 | const char *string, 330 | uint64_t address, 331 | unsigned char **encoding, size_t *encoding_size, 332 | size_t *stat_count); 333 | 334 | 335 | /* 336 | Free memory allocated by ks_asm() 337 | 338 | @p: memory allocated in @encoding argument of ks_asm() 339 | */ 340 | KEYSTONE_EXPORT 341 | void ks_free(unsigned char *p); 342 | 343 | 344 | #ifdef __cplusplus 345 | } 346 | #endif 347 | 348 | #endif 349 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/mips.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_MIPS_H 5 | #define KEYSTONE_MIPS_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_mips { 14 | KS_ERR_ASM_MIPS_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_MIPS_MISSINGFEATURE, 16 | KS_ERR_ASM_MIPS_MNEMONICFAIL, 17 | } ks_err_asm_mips; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/ppc.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_PPC_H 5 | #define KEYSTONE_PPC_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_ppc { 14 | KS_ERR_ASM_PPC_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_PPC_MISSINGFEATURE, 16 | KS_ERR_ASM_PPC_MNEMONICFAIL, 17 | } ks_err_asm_ppc; 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/riscv.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | /* Added by Mark Juvan, 2023*/ 4 | #ifndef KEYSTONE_RISCV_H 5 | #define KEYSTONE_RISCV_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_riscv { 14 | KS_ERR_ASM_RISCV_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_RISCV_MISSINGFEATURE, 16 | KS_ERR_ASM_RISCV_MNEMONICFAIL, 17 | } ks_err_asm_riscv; 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/sparc.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_SPARC_H 5 | #define KEYSTONE_SPARC_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_sparc { 14 | KS_ERR_ASM_SPARC_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_SPARC_MISSINGFEATURE, 16 | KS_ERR_ASM_SPARC_MNEMONICFAIL, 17 | } ks_err_asm_sparc; 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/systemz.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_SYSTEMZ_H 5 | #define KEYSTONE_SYSTEMZ_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_systemz { 14 | KS_ERR_ASM_SYSTEMZ_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_SYSTEMZ_MISSINGFEATURE, 16 | KS_ERR_ASM_SYSTEMZ_MNEMONICFAIL, 17 | } ks_err_asm_systemz; 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Lib/Keystone/includes/x86.h: -------------------------------------------------------------------------------- 1 | /* Keystone Assembler Engine */ 2 | /* By Nguyen Anh Quynh, 2016 */ 3 | 4 | #ifndef KEYSTONE_X86_H 5 | #define KEYSTONE_X86_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "keystone.h" 12 | 13 | typedef enum ks_err_asm_x86 { 14 | KS_ERR_ASM_X86_INVALIDOPERAND = KS_ERR_ASM_ARCH, 15 | KS_ERR_ASM_X86_MISSINGFEATURE, 16 | KS_ERR_ASM_X86_MNEMONICFAIL, 17 | } ks_err_asm_x86; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Lib/Obfuscation/Obfuscate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Obfuscate.h 3 | * Project: SilentPwn 4 | * Author: LeFF && Batchh (Edited version) 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 LeFF && Batchh. All rights reserved. 8 | * 9 | * Description: Obfuscation header for SilentPwn 10 | */ 11 | 12 | // http://www.rohitab.com/discuss/topic/39611-malware-related-compile-time-hacks-with-c11/ 13 | // https://github.com/Rednick16/cpp11-compile-time-string-obfuscation 14 | 15 | #include 16 | #include 17 | 18 | //-------------------------------------------------------------// 19 | // "Malware related compile-time hacks with C++11" by LeFF // 20 | // You can use this code however you like, I just don't really // 21 | // give a shit, but if you feel some respect for me, please // 22 | // don't cut off this comment when copy-pasting... ;-) // 23 | //-------------------------------------------------------------// 24 | 25 | #if defined(_MSC_VER) 26 | #define ALWAYS_INLINE __forceinline 27 | #else 28 | #define ALWAYS_INLINE __attribute__((always_inline)) 29 | #endif 30 | 31 | // Usage examples: 32 | void setup() __attribute__((noinline)); 33 | void startAuthentication() __attribute__((noinline)); 34 | 35 | #ifndef seed 36 | // I use current (compile time) as a seed 37 | // Convert time string (hh:mm:ss) into a number 38 | constexpr int seedToInt(char c) { return c - '0'; } 39 | const int seed = seedToInt(__TIME__[7]) + 40 | seedToInt(__TIME__[6]) * 10 + 41 | seedToInt(__TIME__[4]) * 60 + 42 | seedToInt(__TIME__[3]) * 600 + 43 | seedToInt(__TIME__[1]) * 3600 + 44 | seedToInt(__TIME__[0]) * 36000; 45 | #endif 46 | 47 | // The constantify template is used to make sure that the result of constexpr 48 | // function will be computed at compile-time instead of run-time 49 | template struct 50 | vxCplConstantify { enum { Value = Const }; }; 51 | 52 | // Compile-time mod of a linear congruential pseudorandom number generator, 53 | // the actual algorithm was taken from "Numerical Recipes" book 54 | constexpr uintptr_t vxCplRandom(uintptr_t Id) 55 | { return (1013904223 + 1664525 * ((Id > 0) ? (vxCplRandom(Id - 1)) : (/*vxCPLSEED*/seed))) & 0xFFFFFFFF; } 56 | 57 | // Compile-time random macros, can be used to randomize execution 58 | // path for separate builds, or compile-time trash code generation 59 | #define vxRANDOM(Min, Max) (Min + (vxRAND() % (Max - Min + 1))) 60 | #define vxRAND() (vxCplConstantify::Value) 61 | 62 | // Compile-time recursive mod of string hashing algorithm, 63 | // the actual algorithm was taken from Qt library (this 64 | // function isn't case sensitive due to vxCplTolower) 65 | constexpr char vxCplTolower(char Ch) { return (Ch >= 'A' && Ch <= 'Z') ? (Ch - 'A' + 'a') : (Ch); } 66 | constexpr uintptr_t vxCplHashPart3(char Ch, uintptr_t Hash) { return ((Hash << 4) + vxCplTolower(Ch)); } 67 | constexpr uintptr_t vxCplHashPart2(char Ch, uintptr_t Hash) { return (vxCplHashPart3(Ch, Hash) ^ ((vxCplHashPart3(Ch, Hash) & 0xF0000000) >> 23)); } 68 | constexpr uintptr_t vxCplHashPart1(char Ch, uintptr_t Hash) { return (vxCplHashPart2(Ch, Hash) & 0x0FFFFFFF); } 69 | constexpr uintptr_t vxCplHash(const char* Str) { return (*Str) ? (vxCplHashPart1(*Str, vxCplHash(Str + 1))) : (0); } 70 | 71 | // Compile-time hashing macro, hash values changes using the first pseudorandom number in sequence 72 | #define HASH(Str) (uintptr_t)(vxCplConstantify::Value ^ vxCplConstantify::Value) 73 | 74 | // Compile-time generator for list of indexes (0, 1, 2, ...) 75 | template struct vxCplIndexList {}; 76 | template struct vxCplAppend; 77 | template struct vxCplAppend, Right> { typedef vxCplIndexList Result; }; 78 | template struct vxCplIndexes { typedef typename vxCplAppend::Result, N - 1>::Result Result; }; 79 | template <> struct vxCplIndexes<0> { typedef vxCplIndexList<> Result; }; 80 | 81 | // Compile-time string encryption of a single character 82 | const char vxCplEncryptCharKey = (const char)vxRANDOM(0, 0xFF); 83 | constexpr char ALWAYS_INLINE vxCplEncryptChar(const char Ch, uintptr_t Idx) { return Ch ^ (vxCplEncryptCharKey + Idx); } 84 | 85 | // Compile-time string encryption class 86 | template struct vxCplEncryptedString; 87 | template struct vxCplEncryptedString > 88 | { 89 | char Value[sizeof...(Idx) + 1]; // Buffer for a string 90 | 91 | // Compile-time constructor 92 | constexpr ALWAYS_INLINE vxCplEncryptedString(const char* const Str) 93 | : Value{ vxCplEncryptChar(Str[Idx], Idx)... } {} 94 | 95 | // Run-time decryption 96 | inline const char* decrypt() 97 | { 98 | for(uintptr_t t = 0; t < sizeof...(Idx); t++) 99 | { this->Value[t] = this->Value[t] ^ (vxCplEncryptCharKey + t); } 100 | this->Value[sizeof...(Idx)] = '\0'; return this->Value; 101 | } 102 | }; 103 | 104 | // Compile-time string encryption macro 105 | #define ENCRYPT(Str) (vxCplEncryptedString::Result>(Str).decrypt()) 106 | 107 | // Compile-time NSNumber encryption class for hex values 108 | template 109 | struct vxCplEncryptedHexNumber { 110 | uintptr_t EncryptedValue; 111 | 112 | // Compile-time constructor 113 | constexpr ALWAYS_INLINE vxCplEncryptedHexNumber() 114 | : EncryptedValue(Value ^ (seed)) {} 115 | 116 | // Run-time decryption 117 | inline uintptr_t decrypt() { 118 | return EncryptedValue ^ (seed); 119 | } 120 | }; 121 | 122 | #ifdef __APPLE__ 123 | // Compile-time Objective-c string encryption macro 124 | #define NSStringEncrypt(Str) @(ENCRYPT(Str)) 125 | // Compile-time NSNumber encryption macro for hex values 126 | #define NSNumberEncrypt(Value) ([NSNumber numberWithUnsignedLong:vxCplEncryptedHexNumber<(uintptr_t)Value>().decrypt()]) 127 | #endif 128 | 129 | // Compile-time offset string encryption macro, converts back to uint64_t. 130 | #define IGSecretHexInt(Str) strtoull(ENCRYPT(Str), NULL, 0) 131 | // Compile-time NSNumber hex string encryption macro 132 | #define IGSecretHexNumber(Str) ([NSNumber numberWithUnsignedLongLong:strtoull(ENCRYPT(Str), NULL, 0)]) 133 | // Compile-time hex string encryption macro, does same as ENCRYPT, but the naming is just more clear. 134 | #define IGSecretHexData(Str) ENCRYPT(Str) 135 | -------------------------------------------------------------------------------- /Lib/Resolver/API/Domain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace Domain 6 | { 7 | void* Get() 8 | { 9 | return reinterpret_cast(Functions.m_DomainGet)(); 10 | } 11 | 12 | Unity::il2cppAssembly** GetAssemblies(size_t* m_Size) 13 | { 14 | return reinterpret_cast(Functions.m_DomainGetAssemblies)(Get(), m_Size); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Lib/Resolver/API/Image.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace Image 6 | { 7 | Unity::il2cppImage* GetByName(const char *image) 8 | { 9 | // Retrieve the assemblies in the current domain 10 | size_t assemblyCount = 0; 11 | Unity::il2cppAssembly **assemblies = Domain::GetAssemblies(&assemblyCount); 12 | 13 | // Iterate over each assembly 14 | for (size_t i = 0; i < assemblyCount; ++i) 15 | { 16 | // Get the image from the current assembly 17 | void *img = reinterpret_cast(Functions.m_AssembliesGetImage)(assemblies[i]); 18 | 19 | // Get the image name 20 | const char *imgName = reinterpret_cast(Functions.m_ImageGetName)(img); 21 | 22 | // Compare the image name with the one we are looking for 23 | if (strcmp(imgName, image) == 0) 24 | { 25 | return reinterpret_cast(img); // Return the image cast to il2cppImage* 26 | } 27 | } 28 | 29 | // If no match is found, return nullptr 30 | return nullptr; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Lib/Resolver/API/ResolveCall.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | // Without this function, you're pretty much fucked up. 6 | void* ResolveCall(const char* m_Name) 7 | { 8 | return reinterpret_cast(Functions.m_ResolveFunction)(m_Name); 9 | } 10 | } -------------------------------------------------------------------------------- /Lib/Resolver/API/String.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace String 6 | { 7 | Unity::System_String* New(const char* m_String) 8 | { 9 | return reinterpret_cast(Functions.m_StringNew)(m_String); 10 | } 11 | 12 | Unity::System_String* New(std::string m_String) 13 | { 14 | return New(&m_String[0]); 15 | } 16 | 17 | namespace NoGC 18 | { 19 | Unity::System_String* New(const char* m_String) 20 | { 21 | Unity::System_String* m_NewString = new Unity::System_String; 22 | m_NewString->m_pClass = IL2CPP::Class::Find(IL2CPP_RStr("System.String")); 23 | m_NewString->m_iLength = swprintf(m_NewString->m_wString, (sizeof(Unity::System_String::m_wString) / 4), L"%hs", m_String); 24 | 25 | return m_NewString; 26 | } 27 | 28 | Unity::System_String* New(std::string m_String) 29 | { 30 | return New(&m_String[0]); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Lib/Resolver/API/Thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace Thread 6 | { 7 | void* Attach(void* m_Domain) 8 | { 9 | return reinterpret_cast(Functions.m_ThreadAttach)(m_Domain); 10 | } 11 | 12 | void Detach(void* m_Thread) 13 | { 14 | reinterpret_cast(Functions.m_ThreadDetach)(m_Thread); 15 | } 16 | } 17 | 18 | // Our Stuff 19 | class CThread 20 | { 21 | public: 22 | void* m_OnStart = nullptr; 23 | void* m_OnEnd = nullptr; 24 | 25 | static void Handler(void* m_Reserved) 26 | { 27 | void* m_IL2CPPThread = Thread::Attach(Domain::Get()); 28 | 29 | CThread* m_Thread = reinterpret_cast(m_Reserved); 30 | void* m_ThreadStart = m_Thread->m_OnStart; 31 | void* m_ThreadEnd = m_Thread->m_OnEnd; 32 | delete m_Thread; 33 | 34 | reinterpret_cast(m_ThreadStart)(); 35 | if (m_ThreadEnd) 36 | reinterpret_cast(m_ThreadEnd)(); 37 | 38 | Thread::Detach(m_IL2CPPThread); 39 | } 40 | 41 | CThread() { /* Why would you even do this? */ } 42 | CThread(void* m_OnStartFunc, void* m_OnEndFunc) 43 | { 44 | m_OnStart = m_OnStartFunc; 45 | m_OnEnd = m_OnEndFunc; 46 | 47 | if (!m_OnStart) 48 | { 49 | IL2CPP_ASSERT("IL2CPP::CThread - m_OnStart is nullptr"); 50 | return; 51 | } 52 | 53 | std::thread (Handler, this).detach(); 54 | } 55 | }; 56 | 57 | namespace Thread 58 | { 59 | void Create(void* m_OnStartFunc, void* m_OnEndFunc = nullptr) 60 | { 61 | CThread* m_Thread = new CThread(m_OnStartFunc, m_OnEndFunc); 62 | IL2CPP_ASSERT(m_Thread && "IL2CPP::Thread::Create - Failed!"); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Lib/Resolver/Data.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | struct Globals_t 6 | { 7 | void* m_GameFramework = nullptr; 8 | }; 9 | Globals_t Globals; 10 | 11 | struct Functions_t 12 | { 13 | void* m_ClassFromName = nullptr; 14 | void* m_ClassGetFields = nullptr; 15 | void* m_ClassGetFieldFromName = nullptr; 16 | void* m_ClassGetMethods = nullptr; 17 | void* m_ClassGetMethodFromName = nullptr; 18 | void* m_ClassGetPropertyFromName = nullptr; 19 | void* m_ClassGetType = nullptr; 20 | 21 | void* m_DomainGet = nullptr; 22 | void* m_DomainGetAssemblies = nullptr; 23 | 24 | void* m_AssembliesGetImage = nullptr; 25 | void* m_ImageGetName = nullptr; 26 | 27 | void* m_Free = nullptr; 28 | 29 | void* m_ImageGetClass = nullptr; 30 | void* m_ImageGetClassCount = nullptr; 31 | 32 | void* m_ResolveFunction = nullptr; 33 | 34 | void* m_StringNew = nullptr; 35 | 36 | void* m_ThreadAttach = nullptr; 37 | void* m_ThreadDetach = nullptr; 38 | 39 | void* m_TypeGetObject = nullptr; 40 | 41 | void* m_pObjectNew = nullptr; 42 | void* m_MethodGetParamName = nullptr; 43 | void* m_MethodGetParam = nullptr; 44 | void* m_ClassFromIl2cppType = nullptr; 45 | 46 | void* m_FieldStaticGetValue = nullptr; 47 | void* m_FieldStaticSetValue = nullptr; 48 | }; 49 | Functions_t Functions; 50 | } 51 | -------------------------------------------------------------------------------- /Lib/Resolver/Defines.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define IL2CPP_INIT_EXPORT IL2CPP_RStr("il2cpp_init") 4 | #define IL2CPP_CLASS_FROM_NAME_EXPORT IL2CPP_RStr("il2cpp_class_from_name") 5 | #define IL2CPP_CLASS_GET_FIELDS IL2CPP_RStr("il2cpp_class_get_fields") 6 | #define IL2CPP_CLASS_GET_FIELD_FROM_NAME_EXPORT IL2CPP_RStr("il2cpp_class_get_field_from_name") 7 | #define IL2CPP_CLASS_GET_METHODS IL2CPP_RStr("il2cpp_class_get_methods") 8 | #define IL2CPP_CLASS_GET_METHOD_FROM_NAME_EXPORT IL2CPP_RStr("il2cpp_class_get_method_from_name") 9 | #define IL2CPP_CLASS_GET_PROPERTY_FROM_NAME_EXPORT IL2CPP_RStr("il2cpp_class_get_property_from_name") 10 | #define IL2CPP_CLASS_GET_TYPE_EXPORT IL2CPP_RStr("il2cpp_class_get_type") 11 | #define IL2CPP_DOMAIN_GET_EXPORT IL2CPP_RStr("il2cpp_domain_get") 12 | #define IL2CPP_DOMAIN_GET_ASSEMBLIES_EXPORT IL2CPP_RStr("il2cpp_domain_get_assemblies") 13 | #define IL2CPP_FREE_EXPORT IL2CPP_RStr("il2cpp_free") 14 | #define IL2CPP_IMAGE_GET_CLASS_EXPORT IL2CPP_RStr("il2cpp_image_get_class") 15 | #define IL2CPP_IMAGE_GET_CLASS_COUNT_EXPORT IL2CPP_RStr("il2cpp_image_get_class_count") 16 | #define IL2CPP_RESOLVE_FUNC_EXPORT IL2CPP_RStr("il2cpp_resolve_icall") 17 | #define IL2CPP_STRING_NEW_EXPORT IL2CPP_RStr("il2cpp_string_new") 18 | #define IL2CPP_THREAD_ATTACH_EXPORT IL2CPP_RStr("il2cpp_thread_attach") 19 | #define IL2CPP_THREAD_DETACH_EXPORT IL2CPP_RStr("il2cpp_thread_detach") 20 | #define IL2CPP_TYPE_GET_OBJECT_EXPORT IL2CPP_RStr("il2cpp_type_get_object") 21 | #define IL2CPP_OBJECT_NEW IL2CPP_RStr("il2cpp_object_new") 22 | #define IL2CPP_METHOD_GET_PARAM_NAME IL2CPP_RStr("il2cpp_method_get_param_name") 23 | #define IL2CPP_METHOD_GET_PARAM IL2CPP_RStr("il2cpp_method_get_param") 24 | #define IL2CPP_CLASS_FROM_IL2CPP_TYPE IL2CPP_RStr("il2cpp_class_from_il2cpp_type") 25 | #define IL2CPP_FIELD_STATIC_GET_VALUE IL2CPP_RStr("il2cpp_field_static_get_value") 26 | #define IL2CPP_FIELD_STATIC_SET_VALUE IL2CPP_RStr("il2cpp_field_static_set_value") 27 | 28 | #define IL2CPP_ASSEMBLY_GET_IMAGE IL2CPP_RStr("il2cpp_assembly_get_image") 29 | #define IL2CPP_IMAGE_GET_NAME IL2CPP_RStr("il2cpp_image_get_name") 30 | 31 | // Calling Convention 32 | #define IL2CPP_CALLING_CONVENTION * 33 | -------------------------------------------------------------------------------- /Lib/Resolver/IL2CPP_Resolver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // C Headers 4 | #include 5 | #include 6 | #include 7 | 8 | // C++ Headers 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | //#include 17 | #include 18 | 19 | // Application Defines 20 | #ifndef UNITY_VERSION_2022_3_8F1 21 | // If Unity version is equal or greater than 2022.3.8f1 uncomment this define. 22 | // #define UNITY_VERSION_2022_3_8F1 23 | #endif 24 | 25 | // IL2CPP Defines 26 | 27 | // Disable Asserts 28 | //#define IL2CPP_ASSERT(x) assert(0) 29 | #ifndef IL2CPP_ASSERT 30 | #include 31 | #define IL2CPP_ASSERT(x) assert(x) 32 | #endif 33 | 34 | 35 | #ifndef IL2CPP_RStr 36 | // If you wanna forward to some string encryption just define before including this file. 37 | #define IL2CPP_RStr(x) x 38 | #endif 39 | 40 | #include "Defines.hpp" 41 | 42 | #include "Utils/MemoryInfo.hpp" 43 | 44 | 45 | // Vector2, Vector3 && Quaternion 46 | #include "Utils/Types/Vector2.hpp" 47 | #include "Utils/Types/Vector3.hpp" 48 | #include "Utils/Types/Quaternion.hpp" 49 | 50 | // IL2CPP Headers 51 | #include "Data.hpp" 52 | 53 | // Unity Headers 54 | #include "Unity/Obfuscators.hpp" 55 | #include "Unity/Defines.hpp" 56 | #include "Unity/Structures/il2cpp.hpp" 57 | #include "Unity/Structures/il2cppArray.hpp" 58 | #include "Unity/Structures/il2cppDictionary.hpp" 59 | #include "Unity/Structures/Engine.hpp" 60 | #include "Unity/Structures/System_String.hpp" 61 | 62 | // IL2CPP Utils 63 | #include "Utils/Hash.hpp" 64 | 65 | // IL2CPP API Headers 66 | #include "API/Domain.hpp" 67 | #include "API/Image.hpp" 68 | #include "API/Class.hpp" 69 | #include "API/ResolveCall.hpp" 70 | #include "API/String.hpp" 71 | #include "API/Thread.hpp" 72 | 73 | // IL2CPP Headers before Unity API 74 | #include "SystemTypeCache.hpp" 75 | 76 | // Unity Class APIs - So they're accessible everywhere 77 | namespace Unity 78 | { 79 | class CCamera; 80 | class CComponent; 81 | class CGameObject; 82 | class CLayerMask; 83 | class CObject; 84 | class CRigidbody; 85 | class CTransform; 86 | } 87 | 88 | // Unity API 89 | #include "Unity/API/Object.hpp" 90 | #include "Unity/API/GameObject.hpp" 91 | #include "Unity/API/Camera.hpp" 92 | #include "Unity/API/Component.hpp" 93 | #include "Unity/API/LayerMask.hpp" 94 | #include "Unity/API/Rigidbody.hpp" 95 | #include "Unity/API/Transform.hpp" 96 | 97 | // IL2CPP Headers after Unity API 98 | #include "Utils/Helper.hpp" 99 | 100 | namespace IL2CPP 101 | { 102 | namespace UnityAPI 103 | { 104 | enum m_eExportObfuscationType 105 | { 106 | None = 0, 107 | ROT = 1, 108 | MAX = 2, 109 | }; 110 | 111 | m_eExportObfuscationType m_ExportObfuscation = m_eExportObfuscationType::None; 112 | 113 | int m_ROTObfuscationValue = -1; 114 | 115 | void* ResolveExport(const char* m_Name) 116 | { 117 | switch (m_ExportObfuscation) 118 | { 119 | case m_eExportObfuscationType::ROT: 120 | { 121 | if (m_ROTObfuscationValue == -1) // Bruteforce 122 | { 123 | for (int i = 1; 26 > i; ++i) 124 | { 125 | void* m_Return = dlsym(Globals.m_GameFramework, &Unity::Obfuscators::ROT_String(m_Name, i)[0]); 126 | if (m_Return) 127 | { 128 | m_ROTObfuscationValue = i; 129 | return m_Return; 130 | } 131 | } 132 | 133 | return nullptr; 134 | } 135 | 136 | return dlsym(Globals.m_GameFramework, &Unity::Obfuscators::ROT_String(m_Name, m_ROTObfuscationValue)[0]); 137 | } 138 | default: 139 | return dlsym(Globals.m_GameFramework, m_Name); 140 | } 141 | 142 | return nullptr; 143 | } 144 | 145 | bool ResolveExport_Boolean(void** m_Address, const char* m_Name) 146 | { 147 | *m_Address = ResolveExport(m_Name); 148 | IL2CPP_ASSERT(*m_Address != nullptr && "Couldn't resolve export!"); 149 | return (*m_Address); 150 | } 151 | 152 | bool Initialize() 153 | { 154 | bool m_InitExportResolved = false; 155 | for (int i = 0; m_eExportObfuscationType::MAX > i; ++i) 156 | { 157 | m_ExportObfuscation = static_cast(i); 158 | if (ResolveExport(IL2CPP_INIT_EXPORT)) 159 | { 160 | m_InitExportResolved = true; 161 | break; 162 | } 163 | } 164 | 165 | IL2CPP_ASSERT(m_InitExportResolved && "Couldn't resolve il2cpp_init!"); 166 | if (!m_InitExportResolved) 167 | return false; 168 | 169 | std::unordered_map m_ExportMap = 170 | { 171 | { IL2CPP_CLASS_FROM_NAME_EXPORT, &Functions.m_ClassFromName }, 172 | { IL2CPP_CLASS_GET_FIELDS, &Functions.m_ClassGetFields }, 173 | { IL2CPP_CLASS_GET_FIELD_FROM_NAME_EXPORT, &Functions.m_ClassGetFieldFromName }, 174 | { IL2CPP_CLASS_GET_METHODS, &Functions.m_ClassGetMethods }, 175 | { IL2CPP_CLASS_GET_METHOD_FROM_NAME_EXPORT, &Functions.m_ClassGetMethodFromName }, 176 | { IL2CPP_CLASS_GET_PROPERTY_FROM_NAME_EXPORT, &Functions.m_ClassGetPropertyFromName }, 177 | { IL2CPP_CLASS_GET_TYPE_EXPORT, &Functions.m_ClassGetType }, 178 | { IL2CPP_DOMAIN_GET_EXPORT, &Functions.m_DomainGet }, 179 | { IL2CPP_DOMAIN_GET_ASSEMBLIES_EXPORT, &Functions.m_DomainGetAssemblies }, 180 | { IL2CPP_FREE_EXPORT, &Functions.m_Free }, 181 | { IL2CPP_IMAGE_GET_CLASS_EXPORT, &Functions.m_ImageGetClass }, 182 | { IL2CPP_IMAGE_GET_CLASS_COUNT_EXPORT, &Functions.m_ImageGetClassCount }, 183 | { IL2CPP_RESOLVE_FUNC_EXPORT, &Functions.m_ResolveFunction }, 184 | { IL2CPP_STRING_NEW_EXPORT, &Functions.m_StringNew }, 185 | { IL2CPP_THREAD_ATTACH_EXPORT, &Functions.m_ThreadAttach }, 186 | { IL2CPP_THREAD_DETACH_EXPORT, &Functions.m_ThreadDetach }, 187 | { IL2CPP_TYPE_GET_OBJECT_EXPORT, &Functions.m_TypeGetObject }, 188 | { IL2CPP_OBJECT_NEW, &Functions.m_pObjectNew }, 189 | { IL2CPP_METHOD_GET_PARAM_NAME, &Functions.m_MethodGetParamName }, 190 | { IL2CPP_METHOD_GET_PARAM, &Functions.m_MethodGetParam }, 191 | { IL2CPP_CLASS_FROM_IL2CPP_TYPE, &Functions.m_ClassFromIl2cppType }, 192 | { IL2CPP_FIELD_STATIC_GET_VALUE, &Functions.m_FieldStaticGetValue }, 193 | { IL2CPP_FIELD_STATIC_SET_VALUE, &Functions.m_FieldStaticSetValue }, 194 | { IL2CPP_ASSEMBLY_GET_IMAGE, &Functions.m_AssembliesGetImage }, 195 | { IL2CPP_IMAGE_GET_NAME, &Functions.m_ImageGetName }, 196 | }; 197 | 198 | for (auto& m_ExportPair : m_ExportMap) 199 | { 200 | if (!ResolveExport_Boolean(m_ExportPair.second, &m_ExportPair.first[0])) 201 | return false; 202 | } 203 | 204 | // Unity APIs 205 | Unity::Camera::Initialize(); 206 | Unity::Component::Initialize(); 207 | Unity::GameObject::Initialize(); 208 | Unity::LayerMask::Initialize(); 209 | Unity::Object::Initialize(); 210 | Unity::RigidBody::Initialize(); 211 | Unity::Transform::Initialize(); 212 | 213 | // Caches 214 | IL2CPP::SystemTypeCache::Initializer::PreCache(); 215 | 216 | return true; 217 | } 218 | } 219 | 220 | /* 221 | * You need to call this, before using any IL2CPP/Unity Functions! 222 | * Args: 223 | * m_WaitForModule - Will wait for main module if you're loading your dll earlier than the main module. 224 | * m_MaxSecondsWait - Max seconds it will wait for main module to load otherwise will return false to prevent infinite loop. 225 | */ 226 | bool Initialize(bool m_WaitForModule = false, const char *dir = "UnityFramework", int m_MaxSecondsWait = 60) 227 | { 228 | 229 | if (m_WaitForModule) 230 | { 231 | int m_SecondsWaited = 0; 232 | while (!Globals.m_GameFramework) 233 | { 234 | if (m_SecondsWaited >= m_MaxSecondsWait) 235 | return false; 236 | 237 | Globals.m_GameFramework = dlopen(dir, RTLD_LAZY); 238 | ++m_SecondsWaited; 239 | std::this_thread::sleep_for(std::chrono::seconds(1)); 240 | } 241 | } 242 | else 243 | Globals.m_GameFramework = dlopen(dir, RTLD_LAZY); 244 | 245 | if (Globals.m_GameFramework == nullptr) 246 | return false; 247 | 248 | if (!UnityAPI::Initialize()) 249 | return false; 250 | 251 | return true; 252 | } 253 | 254 | bool Initialize(void* GameAssemblyHandle) 255 | { 256 | if (GameAssemblyHandle != nullptr) 257 | Globals.m_GameFramework = GameAssemblyHandle; 258 | else 259 | return false; 260 | 261 | if (!UnityAPI::Initialize()) 262 | return false; 263 | 264 | return true; 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /Lib/Resolver/SystemTypeCache.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace SystemTypeCache 6 | { 7 | std::unordered_map m_Map; 8 | 9 | void Add(uint32_t m_Hash, Unity::il2cppObject* m_SystemType) 10 | { 11 | m_Map[m_Hash] = m_SystemType; 12 | } 13 | 14 | void Add(const char* m_Name, Unity::il2cppObject* m_SystemType) 15 | { 16 | Add(Utils::Hash::Get(m_Name), m_SystemType); 17 | } 18 | 19 | Unity::il2cppObject* Get(uint32_t m_Hash) 20 | { 21 | return m_Map[m_Hash]; 22 | } 23 | 24 | Unity::il2cppObject* Get(const char* m_Name) 25 | { 26 | return Get(Utils::Hash::Get(m_Name)); 27 | } 28 | 29 | // Legacy Naming 30 | Unity::il2cppObject* Find(uint32_t m_Hash) 31 | { 32 | return Get(m_Hash); 33 | } 34 | 35 | Unity::il2cppObject* Find(const char* m_Name) 36 | { 37 | return Get(m_Name); 38 | } 39 | 40 | namespace Initializer 41 | { 42 | std::vector m_List; 43 | 44 | void Add(const char* m_Name) 45 | { 46 | m_List.emplace_back(m_Name); 47 | } 48 | 49 | void PreCache() 50 | { 51 | for (const char* m_Name : m_List) 52 | SystemTypeCache::Add(m_Name, IL2CPP::Class::GetSystemType(m_Name)); 53 | 54 | m_List.clear(); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/Camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct CameraFunctions_t 6 | { 7 | void* m_GetCurrent = nullptr; 8 | void* m_GetMain = nullptr; 9 | void* m_GetDepth = nullptr; 10 | void* m_SetDepth = nullptr; 11 | void* m_GetFieldOfView = nullptr; 12 | void* m_SetFieldOfView = nullptr; 13 | void* m_WorldToScreen = nullptr; 14 | }; 15 | CameraFunctions_t m_CameraFunctions; 16 | 17 | class CCamera : public CGameObject 18 | { 19 | public: 20 | float GetDepth() 21 | { 22 | return reinterpret_cast(m_CameraFunctions.m_GetDepth)(this); 23 | } 24 | 25 | void SetDepth(float m_fValue) 26 | { 27 | reinterpret_cast(m_CameraFunctions.m_SetDepth)(this, m_fValue); 28 | } 29 | 30 | float GetFieldOfView() 31 | { 32 | return reinterpret_cast(m_CameraFunctions.m_GetFieldOfView)(this); 33 | } 34 | 35 | void SetFieldOfView(float m_fValue) 36 | { 37 | reinterpret_cast(m_CameraFunctions.m_SetFieldOfView)(this, m_fValue); 38 | } 39 | 40 | void WorldToScreen(Vector3& m_vWorld, Vector3& m_vScreen, int m_iEye = 2) 41 | { 42 | reinterpret_cast(m_CameraFunctions.m_WorldToScreen)(this, m_vWorld, m_iEye, m_vScreen); 43 | } 44 | }; 45 | 46 | namespace Camera 47 | { 48 | void Initialize() 49 | { 50 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_CAMERA_CLASS); 51 | 52 | m_CameraFunctions.m_GetCurrent = IL2CPP::ResolveCall(UNITY_CAMERA_GETCURRENT); 53 | m_CameraFunctions.m_GetMain = IL2CPP::ResolveCall(UNITY_CAMERA_GETMAIN); 54 | m_CameraFunctions.m_GetDepth = IL2CPP::ResolveCall(UNITY_CAMERA_GETDEPTH); 55 | m_CameraFunctions.m_SetDepth = IL2CPP::ResolveCall(UNITY_CAMERA_SETDEPTH); 56 | m_CameraFunctions.m_GetFieldOfView = IL2CPP::ResolveCall(UNITY_CAMERA_GETFIELDOFVIEW); 57 | m_CameraFunctions.m_SetFieldOfView = IL2CPP::ResolveCall(UNITY_CAMERA_SETFIELDOFVIEW); 58 | m_CameraFunctions.m_WorldToScreen = IL2CPP::ResolveCall(UNITY_CAMERA_WORLDTOSCREEN); 59 | } 60 | 61 | CCamera* GetCurrent() 62 | { 63 | return reinterpret_cast(m_CameraFunctions.m_GetCurrent)(); 64 | } 65 | 66 | CCamera* GetMain() 67 | { 68 | return reinterpret_cast(m_CameraFunctions.m_GetMain)(); 69 | } 70 | } 71 | 72 | enum m_eCameraType : int 73 | { 74 | m_eCameraType_Game = 1, 75 | m_eCameraType_SceneView = 2, 76 | m_eCameraType_Preview = 4, 77 | m_eCameraType_VR = 8, 78 | m_eCameraType_Reflection = 16, 79 | }; 80 | 81 | enum m_eCameraEye : int 82 | { 83 | m_eCameraEye_Left = 0, 84 | m_eCameraEye_Right = 1, 85 | m_eCameraEye_Center = 2, 86 | }; 87 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/Component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct ComponentFunctions_t 6 | { 7 | void* m_GetGameObject = nullptr; 8 | void* m_GetTransform = nullptr; 9 | }; 10 | ComponentFunctions_t m_ComponentFunctions; 11 | 12 | class CComponent : public CObject 13 | { 14 | public: 15 | CGameObject* GetGameObject() 16 | { 17 | return reinterpret_cast(m_ComponentFunctions.m_GetGameObject)(this); 18 | } 19 | 20 | CTransform* GetTransform() 21 | { 22 | return reinterpret_cast(m_ComponentFunctions.m_GetTransform)(this); 23 | } 24 | }; 25 | 26 | namespace Component 27 | { 28 | void Initialize() 29 | { 30 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_COMPONENT_CLASS); 31 | 32 | m_ComponentFunctions.m_GetGameObject = IL2CPP::ResolveCall(UNITY_COMPONENT_GETGAMEOBJECT); 33 | m_ComponentFunctions.m_GetTransform = IL2CPP::ResolveCall(UNITY_COMPONENT_GETTRANSFORM); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/GameObject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct GameObjectFunctions_t 6 | { 7 | void* m_AddComponent = nullptr; 8 | void* m_CreatePrimitive = nullptr; 9 | void* m_Find = nullptr; 10 | void* m_FindGameObjectsWithTag = nullptr; 11 | void* m_GetComponent = nullptr; 12 | void* m_GetComponents = nullptr; 13 | void* m_GetComponentInChildren = nullptr; 14 | void* m_GetActive = nullptr; 15 | void* m_GetLayer = nullptr; 16 | void* m_GetTransform = nullptr; 17 | void* m_SetActive = nullptr; 18 | void* m_SetLayer = nullptr; 19 | }; 20 | GameObjectFunctions_t m_GameObjectFunctions; 21 | 22 | class CGameObject : public CObject 23 | { 24 | public: 25 | void AddComponent(il2cppObject* m_pSystemType) 26 | { 27 | reinterpret_cast(m_GameObjectFunctions.m_AddComponent)(this, m_pSystemType); 28 | } 29 | 30 | CComponent* GetComponent(const char* m_pName) 31 | { 32 | return reinterpret_cast(m_GameObjectFunctions.m_GetComponent)(this, IL2CPP::String::New(m_pName)); 33 | } 34 | 35 | CComponent* GetComponentInChildren(il2cppObject* m_pSystemType, bool includeInactive) 36 | { 37 | return reinterpret_cast(m_GameObjectFunctions.m_GetComponentInChildren)(this, m_pSystemType, includeInactive); 38 | } 39 | 40 | // e.g CGameObject->GetComponentInChildren("Namespace.Component"); 41 | CComponent* GetComponentInChildren(const char* type) 42 | { 43 | il2cppClass* m_pClass = IL2CPP::Class::Find(type); 44 | if (!m_pClass) return nullptr; 45 | 46 | return GetComponentInChildren(IL2CPP::Class::GetSystemType(m_pClass), true); 47 | } 48 | 49 | il2cppArray* GetComponents(il2cppObject* m_pSystemType) 50 | { 51 | /* 52 | 0 - Object 53 | 1 - Type 54 | 2 - Use search type as array return type 55 | 3 - Recursive 56 | 4 - Include inactive 57 | 5 - Reverse 58 | 6 - Result list 59 | */ 60 | return reinterpret_cast*(UNITY_CALLING_CONVENTION)(void*, void*, bool, bool, bool, bool, void*)>(m_GameObjectFunctions.m_GetComponents)(this, m_pSystemType, false, false, true, false, nullptr); 61 | } 62 | 63 | il2cppArray* GetComponents(const char* m_pSystemTypeName) 64 | { 65 | il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName); 66 | if (!m_pClass) return nullptr; 67 | 68 | return GetComponents(IL2CPP::Class::GetSystemType(m_pClass)); 69 | } 70 | 71 | CComponent* GetComponentByIndex(il2cppObject* m_pSystemType, unsigned int m_uIndex = 0U) 72 | { 73 | il2cppArray* m_pComponents = GetComponents(m_pSystemType); 74 | if (!m_pComponents || m_uIndex >= m_pComponents->m_uMaxLength) return nullptr; 75 | 76 | return m_pComponents->operator[](m_uIndex); 77 | } 78 | 79 | CComponent* GetComponentByIndex(const char* m_pSystemTypeName, unsigned int m_uIndex = 0U) 80 | { 81 | il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName); 82 | if (!m_pClass) return nullptr; 83 | 84 | return GetComponentByIndex(IL2CPP::Class::GetSystemType(m_pClass), m_uIndex); 85 | } 86 | 87 | CTransform* GetTransform() 88 | { 89 | return reinterpret_cast(m_GameObjectFunctions.m_GetTransform)(this); 90 | } 91 | 92 | bool GetActive() 93 | { 94 | return reinterpret_cast(m_GameObjectFunctions.m_GetActive)(this); 95 | } 96 | 97 | unsigned int GetLayer() 98 | { 99 | return reinterpret_cast(m_GameObjectFunctions.m_GetLayer)(this); 100 | } 101 | 102 | /* 103 | * (WARNING) when you use GameObject::Find and you set the object to unactive, you won't find it anymore with that slow function. 104 | */ 105 | void SetActive(bool m_bActive) 106 | { 107 | reinterpret_cast(m_GameObjectFunctions.m_SetActive)(this, m_bActive); 108 | } 109 | 110 | void SetLayer(unsigned int m_uLayer) 111 | { 112 | reinterpret_cast(m_GameObjectFunctions.m_SetLayer)(this, m_uLayer); 113 | } 114 | }; 115 | 116 | namespace GameObject 117 | { 118 | enum class m_ePrimitiveType : int 119 | { 120 | Default = 0, 121 | Sphere = 0, 122 | Capsule, 123 | Cylinder, 124 | Cube, 125 | Plane, 126 | Quad, 127 | }; 128 | 129 | void Initialize() 130 | { 131 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_GAMEOBJECT_CLASS); 132 | 133 | m_GameObjectFunctions.m_AddComponent = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_ADDCOMPONENT); 134 | m_GameObjectFunctions.m_CreatePrimitive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_CREATEPRIMITIVE); 135 | m_GameObjectFunctions.m_Find = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_FIND); 136 | m_GameObjectFunctions.m_FindGameObjectsWithTag = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_FINDGAMEOBJECTWITHTAG); 137 | m_GameObjectFunctions.m_GetComponent = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETCOMPONENT); 138 | m_GameObjectFunctions.m_GetComponents = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETCOMPONENTS); 139 | m_GameObjectFunctions.m_GetComponentInChildren = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETCOMPONENTINCHILDREN); 140 | m_GameObjectFunctions.m_GetActive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETACTIVE); 141 | m_GameObjectFunctions.m_GetLayer = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETLAYER); 142 | m_GameObjectFunctions.m_GetTransform = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETTRANSFORM); 143 | m_GameObjectFunctions.m_SetActive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_SETACTIVE); 144 | m_GameObjectFunctions.m_SetLayer = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_SETLAYER); 145 | } 146 | 147 | CGameObject* CreatePrimitive(m_ePrimitiveType m_Type) 148 | { 149 | return reinterpret_cast(m_GameObjectFunctions.m_CreatePrimitive)(m_Type); 150 | } 151 | 152 | CGameObject* Find(const char* m_Name) 153 | { 154 | return reinterpret_cast(m_GameObjectFunctions.m_Find)(IL2CPP::String::New(m_Name)); 155 | } 156 | 157 | il2cppArray* FindWithTag(const char* m_Tag) 158 | { 159 | return reinterpret_cast*(UNITY_CALLING_CONVENTION)(void*)>(m_GameObjectFunctions.m_FindGameObjectsWithTag)(IL2CPP::String::New(m_Tag)); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/LayerMask.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct LayerMaskFunctions_t 6 | { 7 | void* m_LayerToName = nullptr; 8 | void* m_NameToLayer = nullptr; 9 | }; 10 | LayerMaskFunctions_t m_LayerMaskFunctions; 11 | 12 | namespace LayerMask 13 | { 14 | void Initialize() 15 | { 16 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_LAYERMASK_CLASS); 17 | 18 | m_LayerMaskFunctions.m_LayerToName = IL2CPP::ResolveCall(UNITY_LAYERMASK_LAYERTONAME); 19 | m_LayerMaskFunctions.m_NameToLayer = IL2CPP::ResolveCall(UNITY_LAYERMASK_NAMETOLAYER); 20 | } 21 | 22 | System_String* LayerToName(unsigned int m_uLayer) 23 | { 24 | return reinterpret_cast(m_LayerMaskFunctions.m_LayerToName)(m_uLayer); 25 | } 26 | 27 | uint32_t NameToLayer(const char* m_pName) 28 | { 29 | return reinterpret_cast(m_LayerMaskFunctions.m_NameToLayer)(IL2CPP::String::New(m_pName)); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/Object.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma clang diagnostic ignored "-Wunused-function" 4 | 5 | namespace Unity 6 | { 7 | struct ObjectFunctions_t 8 | { 9 | void* m_Destroy = nullptr; 10 | void* m_FindObjectsOfType = nullptr; 11 | void* m_GetName = nullptr; 12 | }; 13 | ObjectFunctions_t m_ObjectFunctions; 14 | 15 | class CObject : public IL2CPP::CClass 16 | { 17 | public: 18 | void Destroy(float fTimeDelay = 0.f) 19 | { 20 | reinterpret_cast(m_ObjectFunctions.m_Destroy)(this, fTimeDelay); 21 | } 22 | 23 | System_String* GetName() 24 | { 25 | return reinterpret_cast(m_ObjectFunctions.m_GetName)(this); 26 | } 27 | }; 28 | 29 | namespace Object 30 | { 31 | void Initialize() 32 | { 33 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_OBJECT_CLASS); 34 | 35 | m_ObjectFunctions.m_Destroy = IL2CPP::ResolveCall(UNITY_OBJECT_DESTROY); 36 | m_ObjectFunctions.m_FindObjectsOfType = IL2CPP::ResolveCall(UNITY_OBJECT_FINDOBJECTSOFTYPE); 37 | m_ObjectFunctions.m_GetName = IL2CPP::ResolveCall(UNITY_OBJECT_GETNAME); 38 | } 39 | 40 | static il2cppObject* New(il2cppClass* m_pClass) 41 | { 42 | return reinterpret_cast(IL2CPP::Functions.m_pObjectNew)(m_pClass); 43 | } 44 | 45 | template 46 | static il2cppArray* FindObjectsOfType(il2cppObject* m_pSystemType, bool m_bIncludeInactive = false) 47 | { 48 | return reinterpret_cast*(UNITY_CALLING_CONVENTION)(void*, bool)>(m_ObjectFunctions.m_FindObjectsOfType)(m_pSystemType, m_bIncludeInactive); 49 | } 50 | 51 | template 52 | static il2cppArray* FindObjectsOfType(const char* m_pSystemTypeName, bool m_bIncludeInactive = false) 53 | { 54 | il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName); 55 | if (!m_pClass) return nullptr; 56 | 57 | return FindObjectsOfType(IL2CPP::Class::GetSystemType(m_pClass), m_bIncludeInactive); 58 | } 59 | 60 | template 61 | static T* FindObjectOfType(il2cppObject* m_pSystemType, bool m_bIncludeInactive = false) 62 | { 63 | il2cppArray* m_pArray = FindObjectsOfType(m_pSystemType, m_bIncludeInactive); 64 | if (!m_pArray || m_pArray->m_uMaxLength == 0U) return nullptr; 65 | 66 | return m_pArray->m_pValues[0]; 67 | } 68 | 69 | template 70 | static T* FindObjectOfType(const char* m_pSystemTypeName, bool m_bIncludeInactive = false) 71 | { 72 | il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName); 73 | if (!m_pClass) return nullptr; 74 | 75 | return FindObjectOfType(IL2CPP::Class::GetSystemType(m_pClass), m_bIncludeInactive); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/Rigidbody.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct RigidbodyFunctions_t 6 | { 7 | void* m_GetDetectCollisions = nullptr; 8 | void* m_GetVelocity = nullptr; 9 | void* m_SetDetectCollisions = nullptr; 10 | void* m_SetVelocity = nullptr; 11 | }; 12 | RigidbodyFunctions_t m_RigidbodyFunctions; 13 | 14 | class CRigidbody : public IL2CPP::CClass 15 | { 16 | public: 17 | bool GetDetectCollisions() 18 | { 19 | return reinterpret_cast(m_RigidbodyFunctions.m_GetDetectCollisions)(this); 20 | } 21 | 22 | void SetDetectCollisions(bool m_bDetect) 23 | { 24 | reinterpret_cast(m_RigidbodyFunctions.m_SetDetectCollisions)(this, m_bDetect); 25 | } 26 | 27 | Vector3 GetVelocity() 28 | { 29 | Vector3 vRet; 30 | reinterpret_cast(m_RigidbodyFunctions.m_GetVelocity)(this, vRet); 31 | return vRet; 32 | } 33 | 34 | void SetVelocity(Vector3 m_vVector) 35 | { 36 | reinterpret_cast(m_RigidbodyFunctions.m_SetVelocity)(this, m_vVector); 37 | } 38 | }; 39 | 40 | namespace RigidBody 41 | { 42 | void Initialize() 43 | { 44 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_RIGIDBODY_CLASS); 45 | 46 | m_RigidbodyFunctions.m_GetDetectCollisions = IL2CPP::ResolveCall(UNITY_RIGIDBODY_GETDETECTCOLLISIONS); 47 | m_RigidbodyFunctions.m_GetVelocity = IL2CPP::ResolveCall(UNITY_RIGIDBODY_GETVELOCITY); 48 | m_RigidbodyFunctions.m_SetDetectCollisions = IL2CPP::ResolveCall(UNITY_RIGIDBODY_SETDETECTCOLLISIONS); 49 | m_RigidbodyFunctions.m_SetVelocity = IL2CPP::ResolveCall(UNITY_RIGIDBODY_SETVELOCITY); 50 | 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/API/Transform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct TransformFunctions_t 6 | { 7 | void* m_GetParent = nullptr; 8 | void* m_GetRoot = nullptr; 9 | void* m_GetChild = nullptr; 10 | void* m_GetChildCount = nullptr; 11 | void* m_FindChild = nullptr; 12 | void* m_GetPosition = nullptr; 13 | void* m_GetForward = nullptr; 14 | void* m_GetRotation = nullptr; 15 | void* m_GetLocalPosition = nullptr; 16 | void* m_GetLocalScale = nullptr; 17 | void* m_SetPosition = nullptr; 18 | void* m_SetForward = nullptr; 19 | void* m_SetRotation = nullptr; 20 | void* m_SetLocalPosition = nullptr; 21 | void* m_SetLocalScale = nullptr; 22 | }; 23 | TransformFunctions_t m_TransformFunctions; 24 | 25 | class CTransform : public IL2CPP::CClass 26 | { 27 | public: 28 | CTransform* GetParent() 29 | { 30 | return reinterpret_cast(m_TransformFunctions.m_GetParent)(this); 31 | } 32 | 33 | CTransform* GetRoot() 34 | { 35 | return reinterpret_cast(m_TransformFunctions.m_GetRoot)(this); 36 | } 37 | 38 | CTransform* GetChild(int m_iIndex) 39 | { 40 | return reinterpret_cast(m_TransformFunctions.m_GetChild)(this, m_iIndex); 41 | } 42 | 43 | int GetChildCount() 44 | { 45 | return reinterpret_cast(m_TransformFunctions.m_GetChildCount)(this); 46 | } 47 | 48 | CTransform* FindChild(const char* path, bool isActiveOnly) 49 | { 50 | return reinterpret_cast(m_TransformFunctions.m_FindChild)(this, IL2CPP::String::New(path), isActiveOnly); 51 | } 52 | 53 | // e.g CGameObject->GetTransform()->FindChild("child1/child2/child3"); 54 | CTransform* FindChild(const char* path) 55 | { 56 | if (path == NULL) { 57 | return nullptr; 58 | } 59 | return FindChild(path, false); 60 | } 61 | 62 | Vector3 GetPosition() 63 | { 64 | Vector3 vRet; 65 | reinterpret_cast(m_TransformFunctions.m_GetPosition)(this, vRet); 66 | return vRet; 67 | } 68 | 69 | Vector3 GetForward() 70 | { 71 | Vector3 vRet; 72 | vRet = reinterpret_cast(m_TransformFunctions.m_GetForward)(this); 73 | return vRet; 74 | } 75 | 76 | Quaternion GetRotation() 77 | { 78 | Quaternion m_qRet; 79 | reinterpret_cast(m_TransformFunctions.m_GetRotation)(this, m_qRet); 80 | return m_qRet; 81 | } 82 | 83 | Vector3 GetLocalPosition() 84 | { 85 | Vector3 vRet; 86 | reinterpret_cast(m_TransformFunctions.m_GetLocalPosition)(this, vRet); 87 | return vRet; 88 | } 89 | 90 | Vector3 GetLocalScale() 91 | { 92 | Vector3 vRet; 93 | reinterpret_cast(m_TransformFunctions.m_GetLocalScale)(this, vRet); 94 | return vRet; 95 | } 96 | 97 | void SetPosition(Vector3 m_vVector) 98 | { 99 | reinterpret_cast(m_TransformFunctions.m_SetPosition)(this, m_vVector); 100 | } 101 | 102 | void SetForward(Vector3 m_vVector) 103 | { 104 | reinterpret_cast(m_TransformFunctions.m_SetForward)(this, m_vVector); 105 | } 106 | 107 | void SetRotation(Quaternion m_qQuat) 108 | { 109 | reinterpret_cast(m_TransformFunctions.m_SetRotation)(this, m_qQuat); 110 | } 111 | 112 | void SetLocalPosition(Vector3 m_vVector) 113 | { 114 | reinterpret_cast(m_TransformFunctions.m_SetLocalPosition)(this, m_vVector); 115 | } 116 | 117 | void SetLocalScale(Vector3 m_vVector) 118 | { 119 | reinterpret_cast(m_TransformFunctions.m_SetLocalScale)(this, m_vVector); 120 | } 121 | }; 122 | 123 | namespace Transform 124 | { 125 | void Initialize() 126 | { 127 | IL2CPP::SystemTypeCache::Initializer::Add(UNITY_TRANSFORM_CLASS); 128 | 129 | m_TransformFunctions.m_GetParent = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETPARENT); 130 | m_TransformFunctions.m_GetRoot = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETROOT); 131 | m_TransformFunctions.m_GetChild = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETCHILD); 132 | m_TransformFunctions.m_GetChildCount = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETCHILDCOUNT); 133 | m_TransformFunctions.m_FindChild = IL2CPP::ResolveCall(UNITY_TRANSFORM_FINDCHILD); 134 | m_TransformFunctions.m_GetPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETPOSITION); 135 | m_TransformFunctions.m_GetForward = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETFORWARD); 136 | m_TransformFunctions.m_GetRotation = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETROTATION); 137 | m_TransformFunctions.m_GetLocalPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETLOCALPOSITION); 138 | m_TransformFunctions.m_GetLocalScale = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETLOCALSCALE); 139 | m_TransformFunctions.m_SetPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETPOSITION); 140 | m_TransformFunctions.m_SetForward = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETFORWARD); 141 | m_TransformFunctions.m_SetRotation = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETROTATION); 142 | m_TransformFunctions.m_SetLocalPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETLOCALPOSITION); 143 | m_TransformFunctions.m_SetLocalScale = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETLOCALSCALE); 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Defines.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Calling Convention 4 | #define UNITY_CALLING_CONVENTION * 5 | 6 | 7 | // Camera 8 | #define UNITY_CAMERA_CLASS "UnityEngine.Camera" 9 | #define UNITY_CAMERA_GETCURRENT IL2CPP_RStr(UNITY_CAMERA_CLASS"::get_current") 10 | #define UNITY_CAMERA_GETMAIN IL2CPP_RStr(UNITY_CAMERA_CLASS"::get_main") 11 | #define UNITY_CAMERA_GETDEPTH IL2CPP_RStr(UNITY_CAMERA_CLASS"::get_depth") 12 | #define UNITY_CAMERA_SETDEPTH IL2CPP_RStr(UNITY_CAMERA_CLASS"::set_depth") 13 | #define UNITY_CAMERA_GETFIELDOFVIEW IL2CPP_RStr(UNITY_CAMERA_CLASS"::get_fieldOfView") 14 | #define UNITY_CAMERA_SETFIELDOFVIEW IL2CPP_RStr(UNITY_CAMERA_CLASS"::set_fieldOfView") 15 | #define UNITY_CAMERA_WORLDTOSCREEN IL2CPP_RStr(UNITY_CAMERA_CLASS"::WorldToScreenPoint_Injected") 16 | 17 | // Component 18 | #define UNITY_COMPONENT_CLASS "UnityEngine.Component" 19 | #define UNITY_COMPONENT_GETGAMEOBJECT IL2CPP_RStr(UNITY_COMPONENT_CLASS"::get_gameObject") 20 | #define UNITY_COMPONENT_GETTRANSFORM IL2CPP_RStr(UNITY_COMPONENT_CLASS"::get_transform") 21 | 22 | // GameObject 23 | #define UNITY_GAMEOBJECT_CLASS "UnityEngine.GameObject" 24 | #define UNITY_GAMEOBJECT_ADDCOMPONENT IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::Internal_AddComponentWithType") 25 | #define UNITY_GAMEOBJECT_CREATEPRIMITIVE IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::CreatePrimitive") 26 | #define UNITY_GAMEOBJECT_FIND IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::Find") 27 | #define UNITY_GAMEOBJECT_GETCOMPONENT IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::GetComponentByName") 28 | #define UNITY_GAMEOBJECT_GETCOMPONENTS IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::GetComponentsInternal") 29 | #define UNITY_GAMEOBJECT_GETCOMPONENTINCHILDREN IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::GetComponentInChildren") 30 | #define UNITY_GAMEOBJECT_GETACTIVE IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::get_active") 31 | #define UNITY_GAMEOBJECT_GETLAYER IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::get_layer") 32 | #define UNITY_GAMEOBJECT_GETTRANSFORM IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::get_transform") 33 | #define UNITY_GAMEOBJECT_SETACTIVE IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::set_active") 34 | #define UNITY_GAMEOBJECT_SETLAYER IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::set_layer") 35 | #define UNITY_GAMEOBJECT_FINDGAMEOBJECTWITHTAG IL2CPP_RStr(UNITY_GAMEOBJECT_CLASS"::FindGameObjectsWithTag") 36 | 37 | // LayerMask 38 | #define UNITY_LAYERMASK_CLASS "UnityEngine.LayerMask" 39 | #define UNITY_LAYERMASK_LAYERTONAME IL2CPP_RStr(UNITY_LAYERMASK_CLASS"::LayerToName") 40 | #define UNITY_LAYERMASK_NAMETOLAYER IL2CPP_RStr(UNITY_LAYERMASK_CLASS"::NameToLayer") 41 | 42 | // MonoBehaviour 43 | #define UNITY_MONOBEHAVIOUR_CLASS "UnityEngine.MonoBehaviour" 44 | 45 | // Object 46 | #define UNITY_OBJECT_CLASS "UnityEngine.Object" 47 | #define UNITY_OBJECT_DESTROY IL2CPP_RStr(UNITY_OBJECT_CLASS"::Destroy") 48 | #define UNITY_OBJECT_FINDOBJECTSOFTYPE IL2CPP_RStr(UNITY_OBJECT_CLASS"::FindObjectsOfType(System.Type,System.Boolean)") 49 | #define UNITY_OBJECT_GETNAME IL2CPP_RStr(UNITY_OBJECT_CLASS"::GetName") 50 | 51 | // Rigidbody 52 | #define UNITY_RIGIDBODY_CLASS "UnityEngine.Rigidbody" 53 | #define UNITY_RIGIDBODY_GETDETECTCOLLISIONS IL2CPP_RStr(UNITY_RIGIDBODY_CLASS"::get_detectCollisions") 54 | #define UNITY_RIGIDBODY_GETVELOCITY IL2CPP_RStr(UNITY_RIGIDBODY_CLASS"::get_velocity_Injected") 55 | #define UNITY_RIGIDBODY_SETDETECTCOLLISIONS IL2CPP_RStr(UNITY_RIGIDBODY_CLASS"::set_detectCollisions") 56 | #define UNITY_RIGIDBODY_SETVELOCITY IL2CPP_RStr(UNITY_RIGIDBODY_CLASS"::set_velocity_Injected") 57 | 58 | // Transform 59 | #define UNITY_TRANSFORM_CLASS "UnityEngine.Transform" 60 | #define UNITY_TRANSFORM_GETPARENT IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::GetParent") 61 | #define UNITY_TRANSFORM_GETROOT IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::GetRoot") 62 | #define UNITY_TRANSFORM_GETCHILD IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::GetChild") 63 | #define UNITY_TRANSFORM_GETCHILDCOUNT IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_childCount") 64 | #define UNITY_TRANSFORM_FINDCHILD IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::FindRelativeTransformWithPath") 65 | #define UNITY_TRANSFORM_GETPOSITION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_position_Injected") 66 | #define UNITY_TRANSFORM_GETROTATION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_rotation_Injected") 67 | #define UNITY_TRANSFORM_GETLOCALPOSITION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_localPosition_Injected") 68 | #define UNITY_TRANSFORM_GETLOCALSCALE IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_localScale_Injected") 69 | #define UNITY_TRANSFORM_SETPOSITION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::set_position_Injected") 70 | #define UNITY_TRANSFORM_SETROTATION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::set_rotation_Injected") 71 | #define UNITY_TRANSFORM_GETFORWARD IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::get_forward") 72 | #define UNITY_TRANSFORM_SETFORWARD IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::set_forward") 73 | #define UNITY_TRANSFORM_SETLOCALPOSITION IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::set_localPosition_Injected") 74 | #define UNITY_TRANSFORM_SETLOCALSCALE IL2CPP_RStr(UNITY_TRANSFORM_CLASS"::set_localScale_Injected") 75 | 76 | namespace Unity 77 | { 78 | enum m_eTypeEnum 79 | { 80 | Type_Void = 1, 81 | Type_Boolean = 2, 82 | Type_Character = 3, 83 | Type_Integer = 8, 84 | Type_Float = 12, 85 | Type_String = 14, 86 | Type_Pointer = 15, 87 | Type_ValueType = 17, 88 | Type_Class = 18, 89 | Type_Variable = 19, 90 | Type_Array = 20, 91 | Type_Enum = 85, 92 | }; 93 | 94 | enum m_eFieldAttribute 95 | { 96 | FieldAttribute_Compiler, 97 | FieldAttribute_Private, 98 | FieldAttribute_FamilyAndAssembly, 99 | FieldAttribute_Assembly, 100 | FieldAttribute_Family, 101 | FieldAttribute_FamilyOrAssembly, 102 | FieldAttribute_Public, 103 | FieldAttribute_AccessMask, 104 | FieldAttribute_Static = 16, 105 | FieldAttribute_InitOnly = 32, 106 | FieldAttribute_Literal = 64, 107 | FieldAttribute_NotSerialized = 128, 108 | FieldAttribute_HasRVA = 256, 109 | FieldAttribute_SpecialName = 512, 110 | FieldAttribute_RTSpecialName = 1024, 111 | FieldAttribute_HasMarshal = 4096, 112 | FieldAttribute_InvokeImpl = 8192, 113 | FieldAttribute_Default = 32768, 114 | FieldAttribute_Reserved = 38144, 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Obfuscators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | namespace Obfuscators 6 | { 7 | // Should do the basic work 8 | std::string ROT_String(const char* pString, int iValue) 9 | { 10 | std::string sRet; 11 | size_t sSize = strlen(pString); 12 | for (size_t i = 0; sSize > i; ++i) 13 | { 14 | bool bIsUppercase = pString[i] >= 'A' && 'Z' >= pString[i]; 15 | bool bIsLowercase = !bIsUppercase && pString[i] >= 'a' && 'z' >= pString[i]; 16 | if (!bIsUppercase && !bIsLowercase) 17 | { 18 | sRet += pString[i]; 19 | continue; 20 | } 21 | 22 | int iNewValue = static_cast(pString[i]) + iValue; 23 | if (bIsUppercase) 24 | { 25 | int iMaxValue = static_cast('Z'); 26 | while (iNewValue > iMaxValue) iNewValue = static_cast('A') + (iNewValue - iMaxValue); 27 | } 28 | else 29 | { 30 | int iMaxValue = static_cast('z'); 31 | while (iNewValue > iMaxValue) iNewValue = static_cast('a') + (iNewValue - iMaxValue); 32 | } 33 | 34 | sRet += static_cast(iNewValue); 35 | } 36 | 37 | sRet += '\0'; 38 | return sRet; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Structures/Engine.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma clang diagnostic ignored "-Wmissing-braces" 3 | 4 | namespace Unity 5 | { 6 | struct Vector4 7 | { 8 | float x, y, z, w; 9 | 10 | Vector4() { x = y = z = w = 0.f; } 11 | Vector4(float f1, float f2, float f3, float f4) { x = f1; y = f2; z = f3; w = f4; } 12 | }; 13 | 14 | struct Bounds 15 | { 16 | Vector3 m_vCenter; 17 | Vector3 m_vExtents; 18 | }; 19 | 20 | struct Plane 21 | { 22 | Vector3 m_vNormal; 23 | float fDistance; 24 | }; 25 | 26 | struct Ray 27 | { 28 | Vector3 m_vOrigin; 29 | Vector3 m_vDirection; 30 | }; 31 | 32 | struct Rect 33 | { 34 | float fX, fY; 35 | float fWidth, fHeight; 36 | 37 | Rect() { fX = fY = fWidth = fHeight = 0.f; } 38 | Rect(float f1, float f2, float f3, float f4) { fX = f1; fY = f2; fWidth = f3; fHeight = f4; } 39 | }; 40 | 41 | struct Color 42 | { 43 | float r, g, b, a; 44 | 45 | Color() { r = g = b = a = 0.f; } 46 | Color(float fRed = 0.f, float fGreen = 0.f, float fBlue = 0.f, float fAlpha = 1.f) { r = fRed; g = fGreen; b = fBlue; a = fAlpha; } 47 | }; 48 | 49 | struct Matrix4x4 50 | { 51 | float m[4][4] = { 0 }; 52 | 53 | Matrix4x4() { } 54 | 55 | float* operator[](int i) { return m[i]; } 56 | }; 57 | 58 | struct CSMatrix4x4 59 | { 60 | float 61 | m11 = 0, m12 = 0, m13 = 0, m14 = 0, 62 | m21 = 0, m22 = 0, m23 = 0, m24 = 0, 63 | m31 = 0, m32 = 0, m33 = 0, m34 = 0, 64 | m41 = 0, m42 = 0, m43 = 0, m44 = 0; 65 | 66 | CSMatrix4x4() { } 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Structures/System_String.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__clang__) 4 | #pragma clang diagnostic push 5 | #pragma clang diagnostic ignored "-Wtautological-undefined-compare" 6 | #pragma clang diagnostic ignored "-Wtautological-pointer-compare" 7 | #endif 8 | 9 | namespace Unity 10 | { 11 | struct System_String : il2cppObject 12 | { 13 | int32_t m_iLength; // 0x8 14 | wchar_t m_wString[1024]; // 0xC 15 | 16 | void Clear() 17 | { 18 | if (this == nullptr) return; 19 | 20 | memset(m_wString, 0, static_cast(m_iLength) * 2); 21 | m_iLength = 0; 22 | } 23 | 24 | wchar_t* ToWideString() 25 | { 26 | return m_wString; 27 | } 28 | 29 | int32_t ToLength() 30 | { 31 | return m_iLength; 32 | } 33 | 34 | std::string ToString() 35 | { 36 | if ((this == nullptr) || (m_wString == nullptr) || (m_iLength == 0)) 37 | return ""; 38 | 39 | std::string retStr; 40 | mbstate_t state = mbstate_t(); 41 | char buf[MB_CUR_MAX]; 42 | 43 | for (int32_t i = 0; i < m_iLength; ++i) 44 | { 45 | size_t ret = wcrtomb(buf, m_wString[i], &state); 46 | if (ret == (size_t)-1) 47 | { 48 | return ""; 49 | } 50 | retStr.append(buf, ret); 51 | } 52 | return retStr; 53 | } 54 | }; 55 | } 56 | 57 | #if defined(__clang__) 58 | #pragma clang diagnostic pop 59 | #endif 60 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Structures/il2cpp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | struct il2cppImage 6 | { 7 | const char* m_pName; 8 | const char* m_pNameNoExt; 9 | }; 10 | 11 | struct il2cppAssemblyName 12 | { 13 | const char* m_pName; 14 | const char* m_pCulture; 15 | const char* m_pHash; 16 | const char* m_pPublicKey; 17 | unsigned int m_uHash; 18 | int m_iHashLength; 19 | unsigned int m_uFlags; 20 | int m_iMajor; 21 | int m_iMinor; 22 | int m_iBuild; 23 | int m_bRevision; 24 | unsigned char m_uPublicKeyToken[8]; 25 | }; 26 | 27 | struct il2cppAssembly 28 | { 29 | il2cppImage* m_pImage; 30 | unsigned int m_uToken; 31 | int m_ReferencedAssemblyStart; 32 | int m_ReferencedAssemblyCount; 33 | il2cppAssemblyName m_aName; 34 | }; 35 | 36 | struct il2cppClass 37 | { 38 | void* m_pImage; 39 | void* m_pGC; 40 | const char* m_pName; 41 | const char* m_pNamespace; 42 | void* m_pValue; 43 | void* m_pArgs; 44 | il2cppClass* m_pElementClass; 45 | il2cppClass* m_pCastClass; 46 | il2cppClass* m_pDeclareClass; 47 | il2cppClass* m_pParentClass; 48 | void* m_pGenericClass; 49 | void* m_pTypeDefinition; 50 | void* m_pInteropData; 51 | void* m_pFields; 52 | void* m_pEvents; 53 | void* m_pProperties; 54 | void** m_pMethods; 55 | il2cppClass** m_pNestedTypes; 56 | il2cppClass** m_ImplementedInterfaces; 57 | void* m_pInterfaceOffsets; 58 | void* m_pStaticFields; 59 | void* m_pRGCTX; 60 | }; 61 | 62 | struct il2cppObject 63 | { 64 | il2cppClass* m_pClass = nullptr; 65 | void* m_pMonitor = nullptr; 66 | }; 67 | 68 | #ifdef UNITY_VERSION_2022_3_8F1 69 | struct il2cppType 70 | { 71 | void* data; 72 | unsigned int bits; 73 | }; 74 | #else 75 | struct il2cppType 76 | { 77 | union 78 | { 79 | void* m_pDummy; 80 | unsigned int m_uClassIndex; 81 | il2cppType* m_pType; 82 | void* m_pArray; 83 | unsigned int m_uGenericParameterIndex; 84 | void* m_pGenericClass; 85 | }; 86 | unsigned int m_uAttributes : 16; 87 | unsigned int m_uType : 8; 88 | unsigned int m_uMods : 6; 89 | unsigned int m_uByref : 1; 90 | unsigned int m_uPinned : 1; 91 | }; 92 | #endif 93 | 94 | struct il2cppFieldInfo 95 | { 96 | const char* m_pName; 97 | il2cppType* m_pType; 98 | il2cppClass* m_pParentClass; 99 | int m_iOffset; 100 | int m_iAttributeIndex; 101 | unsigned int m_uToken; 102 | }; 103 | 104 | struct il2cppParameterInfo 105 | { 106 | const char* m_pName; 107 | int m_iPosition; 108 | unsigned int m_uToken; 109 | il2cppType* m_pParameterType; 110 | }; 111 | 112 | struct il2cppMethodInfo 113 | { 114 | void* m_pMethodPointer; 115 | void* m_pMethodPointerRva; 116 | #ifdef UNITY_VERSION_2022_3_8F1 117 | void* m_pVirtualMethodPointer; 118 | #endif 119 | void* m_pInvokerMethod; 120 | const char* m_pName; 121 | il2cppClass* m_pClass; 122 | il2cppType* m_pReturnType; 123 | #ifdef UNITY_VERSION_2022_3_8F1 124 | il2cppType** m_pParameters; 125 | #else 126 | il2cppParameterInfo* m_pParameters; 127 | #endif 128 | 129 | union 130 | { 131 | void* m_pRGCTX; 132 | void* m_pMethodDefinition; 133 | }; 134 | 135 | union 136 | { 137 | void* m_pGenericMethod; 138 | void* m_pGenericContainer; 139 | }; 140 | 141 | unsigned int m_uToken; 142 | unsigned short m_uFlags; 143 | unsigned short m_uFlags2; 144 | unsigned short m_uSlot; 145 | unsigned char m_uArgsCount; 146 | unsigned char m_uGeneric : 1; 147 | unsigned char m_uInflated : 1; 148 | unsigned char m_uWrapperType : 1; 149 | unsigned char m_uMarshaledFromNative : 1; 150 | }; 151 | 152 | struct il2cppPropertyInfo 153 | { 154 | il2cppClass* m_pParentClass; 155 | const char* m_pName; 156 | il2cppMethodInfo* m_pGet; 157 | il2cppMethodInfo* m_pSet; 158 | unsigned int m_uAttributes; 159 | unsigned int m_uToken; 160 | }; 161 | 162 | struct il2cppArrayBounds 163 | { 164 | uintptr_t m_uLength; 165 | int m_iLowerBound; 166 | }; 167 | } 168 | -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Structures/il2cppArray.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | template 6 | struct il2cppArray : il2cppObject 7 | { 8 | il2cppArrayBounds* m_pBounds = nullptr; 9 | uintptr_t m_uMaxLength = 0; 10 | T* m_pValues = nullptr; 11 | 12 | uintptr_t GetData() 13 | { 14 | return reinterpret_cast(&m_pValues); 15 | } 16 | 17 | T& operator[](unsigned int m_uIndex) 18 | { 19 | return *reinterpret_cast(GetData() + sizeof(T) * m_uIndex); 20 | } 21 | 22 | T& At(unsigned int m_uIndex) 23 | { 24 | return operator[](m_uIndex); 25 | } 26 | 27 | void Insert(T* m_pArray, uintptr_t m_uSize, uintptr_t m_uIndex = 0) 28 | { 29 | if ((m_uSize + m_uIndex) >= m_uMaxLength) 30 | { 31 | if (m_uIndex >= m_uMaxLength) 32 | return; 33 | 34 | m_uSize = m_uMaxLength - m_uIndex; 35 | } 36 | 37 | for (uintptr_t u = 0; m_uSize > u; ++u) 38 | operator[](u + m_uIndex) = m_pArray[u]; 39 | } 40 | 41 | void Fill(T m_tValue) 42 | { 43 | for (uintptr_t u = 0; m_uMaxLength > u; ++u) 44 | operator[](u) = m_tValue; 45 | } 46 | 47 | void RemoveAt(unsigned int m_uIndex) 48 | { 49 | if (m_uIndex >= m_uMaxLength) 50 | return; 51 | 52 | if (m_uMaxLength > (m_uIndex + 1)) 53 | { 54 | for (unsigned int u = m_uIndex; (static_cast(m_uMaxLength) - m_uIndex) > u; ++u) 55 | operator[](u) = operator[](u + 1); 56 | } 57 | 58 | --m_uMaxLength; 59 | } 60 | 61 | void RemoveRange(unsigned int m_uIndex, unsigned int m_uCount) 62 | { 63 | if (m_uCount == 0) 64 | m_uCount = 1; 65 | 66 | unsigned int m_uTotal = m_uIndex + m_uCount; 67 | if (m_uTotal >= m_uMaxLength) 68 | return; 69 | 70 | if (m_uMaxLength > (m_uTotal + 1)) 71 | { 72 | for (unsigned int u = m_uIndex; (static_cast(m_uMaxLength) - m_uTotal) >= u; ++u) 73 | operator[](u) = operator[](u + m_uCount); 74 | } 75 | 76 | m_uMaxLength -= m_uCount; 77 | } 78 | 79 | void RemoveAll() 80 | { 81 | if (m_uMaxLength > 0) 82 | { 83 | memset(GetData(), 0, sizeof(T) * m_uMaxLength); 84 | m_uMaxLength = 0; 85 | } 86 | } 87 | }; 88 | 89 | // Defined here because its basically same shit 90 | template 91 | struct il2cppList : il2cppObject 92 | { 93 | il2cppArray* m_pListArray; 94 | 95 | il2cppArray* ToArray() { return m_pListArray; } 96 | }; 97 | } -------------------------------------------------------------------------------- /Lib/Resolver/Unity/Structures/il2cppDictionary.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Unity 4 | { 5 | template 6 | struct il2cppDictionary : il2cppObject 7 | { 8 | struct Entry 9 | { 10 | int m_iHashCode; 11 | int m_iNext; 12 | TKey m_tKey; 13 | TValue m_tValue; 14 | }; 15 | il2cppArray* m_pBuckets; 16 | il2cppArray* m_pEntries; 17 | int m_iCount; 18 | int m_iVersion; 19 | int m_iFreeList; 20 | int m_iFreeCount; 21 | void* m_pComparer; 22 | void* m_pKeys; 23 | void* m_pValues; 24 | 25 | Entry* GetEntry() 26 | { 27 | return (Entry*)m_pEntries->GetData(); 28 | } 29 | 30 | TKey GetKeyByIndex(int iIndex) 31 | { 32 | TKey tKey = { 0 }; 33 | 34 | Entry* pEntry = GetEntry(); 35 | if (pEntry) 36 | tKey = pEntry[iIndex].m_tKey; 37 | 38 | return tKey; 39 | } 40 | 41 | TValue GetValueByIndex(int iIndex) 42 | { 43 | TValue tValue = { 0 }; 44 | 45 | Entry* pEntry = GetEntry(); 46 | if (pEntry) 47 | tValue = pEntry[iIndex].m_tValue; 48 | 49 | return tValue; 50 | } 51 | 52 | TValue GetValueByKey(TKey tKey) 53 | { 54 | TValue tValue = { 0 }; 55 | for (int i = 0; i < m_iCount; i++) { 56 | if (GetEntry()[i].m_tKey == tKey) 57 | tValue = GetEntry()[i].m_tValue; 58 | } 59 | return tValue; 60 | } 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /Lib/Resolver/Utils/Hash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace IL2CPP 4 | { 5 | namespace Utils 6 | { 7 | namespace Hash 8 | { 9 | uint32_t Get(const char* m_String) 10 | { 11 | uint32_t m_Hash = 0; 12 | 13 | for (; *m_String; ++m_String) 14 | { 15 | m_Hash += *m_String; 16 | m_Hash += m_Hash << 10; 17 | m_Hash ^= m_Hash >> 6; 18 | } 19 | 20 | m_Hash += m_Hash << 3; 21 | m_Hash ^= m_Hash >> 11; 22 | m_Hash += m_Hash << 15; 23 | 24 | return m_Hash; 25 | } 26 | 27 | constexpr uint32_t GetCompileTime(const char* m_String) 28 | { 29 | uint32_t m_Hash = 0; 30 | 31 | for (; *m_String; ++m_String) 32 | { 33 | m_Hash += *m_String; 34 | m_Hash += m_Hash << 10; 35 | m_Hash ^= m_Hash >> 6; 36 | } 37 | 38 | m_Hash += m_Hash << 3; 39 | m_Hash ^= m_Hash >> 11; 40 | m_Hash += m_Hash << 15; 41 | 42 | return m_Hash; 43 | } 44 | } 45 | } 46 | } 47 | 48 | #define IL2CPP_HASH(m_String) \ 49 | [](){ \ 50 | static constexpr uint32_t m_Hash = IL2CPP::Utils::Hash::GetCompileTime(m_String); \ 51 | return m_Hash; \ 52 | }() 53 | -------------------------------------------------------------------------------- /Lib/Resolver/Utils/MemoryInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class MemoryInfo 4 | { 5 | public: 6 | uint32_t index; 7 | const mach_header *header; 8 | const char *name; 9 | intptr_t address; 10 | }; 11 | 12 | // Credit KittyMemory 13 | MemoryInfo getBaseAddress(const std::string &fileName) 14 | { 15 | MemoryInfo _info; 16 | 17 | const uint32_t imageCount = _dyld_image_count(); 18 | 19 | for (uint32_t i = 0; i < imageCount; i++) 20 | { 21 | const char *name = _dyld_get_image_name(i); 22 | if (!name) 23 | continue; 24 | 25 | std::string fullpath(name); 26 | 27 | if (fullpath.length() < fileName.length() || fullpath.compare(fullpath.length() - fileName.length(), fileName.length(), fileName) != 0) 28 | continue; 29 | 30 | _info.index = i; 31 | _info.header = _dyld_get_image_header(i); 32 | _info.name = _dyld_get_image_name(i); 33 | _info.address = _dyld_get_image_vmaddr_slide(i); 34 | 35 | break; 36 | } 37 | return _info; 38 | } 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 #arm64e 2 | DEBUG = 1 #0 3 | FOR_RELEASE = 0 #1 4 | FINALPACKAGE = 0 #1 5 | 6 | # Only set this to 1 if you are building the tweak in a mobile device 7 | MOBILE_THEOS=0 8 | ifeq ($(MOBILE_THEOS),1) 9 | # path to your sdk 10 | SDK_PATH = $(THEOS)/sdks/iPhoneOS15.5.sdk/ 11 | $(info ===> Setting SYSROOT to $(SDK_PATH)...) 12 | SYSROOT = $(SDK_PATH) 13 | else 14 | TARGET = iphone:clang:latest:15.5 15 | endif 16 | 17 | THEOS_PACKAGE_SCHEME = rootless #rootfull 18 | 19 | include $(THEOS)/makefiles/common.mk 20 | 21 | TWEAK_NAME = @@PROJECTNAME@@ 22 | 23 | ${TWEAK_NAME}_CFLAGS = -fobjc-arc -std=c++17 -I$(THEOS_PROJECT_DIR)/Lib/Keystone/includes 24 | ${TWEAK_NAME}_CCFLAGS = -std=c++17 25 | ${TWEAK_NAME}_CXXFLAGS = -std=c++17 26 | ${TWEAK_NAME}_FRAMEWORKS = UIKit Foundation QuartzCore 27 | ${TWEAK_NAME}_LDFLAGS += $(THEOS_PROJECT_DIR)/Lib/Keystone/arm64/libkeystone.a 28 | ${TWEAK_NAME}_CFLAGS += -I$(THEOS_PROJECT_DIR)/Lib/Keystone/includes 29 | 30 | ${TWEAK_NAME}_FILES = Tweak.mm \ 31 | ${wildcard Source/Memory/Kitty/*.cpp} \ 32 | ${wildcard Source/Memory/Kitty/*.mm} \ 33 | ${wildcard Source/UI/*.mm} \ 34 | ${wildcard Source/Memory/Hook/*.mm} \ 35 | ${wildcard Source/Memory/Patch/*.mm} \ 36 | ${wildcard Source/Memory/Helper.mm} \ 37 | ${wildcard Source/Framework/*.mm} \ 38 | ${wildcard Source/Memory/Thread/*.mm} 39 | 40 | ${TWEAK_NAME}_LIBRARIES += substrate 41 | 42 | include $(THEOS_MAKE_PATH)/tweak.mk 43 | -------------------------------------------------------------------------------- /NIC/control: -------------------------------------------------------------------------------- 1 | name "Batchh/SilentPwn 2.0.5" 2 | prompt FILTER "Bundle filter" "com.company.appname" 3 | constrain file "control" to package 4 | constrain "theos" to link_theos 5 | -------------------------------------------------------------------------------- /NIC/control.pl: -------------------------------------------------------------------------------- 1 | NIC->prompt("APPNAME", "Enter name of the app", {default => ""}); 2 | 3 | NIC->prompt("APPVERSION", "Enter current version of the app", {default => ""}); 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SilentPwn 🕵️‍♂️🔓 2 | 3 | ## Overview 4 | SilentPwn is an advanced iOS Mod Menu framework designed for runtime manipulation and system-level interactions. Perfect for iOS application research, game modifications, and security testing. 5 | 6 | [Video Menu Preview](https://i.imgur.com/lorajGZ.mp4) 7 | 8 | ## 🚀 Features 9 | 10 | ### Memory Hooking 11 | - Runtime method interception 12 | - Hook by memory address or symbol name 13 | - Preserve original method functionality 14 | 15 | ### Configuration Management 16 | - Centralized global configuration 17 | - Debug mode support 18 | - Customizable runtime settings 19 | 20 | ### Dynamic Menu System 21 | - Interactive UI elements 22 | - Slider and toggle controls 23 | - Categorized modifications 24 | 25 | ### Advanced Capabilities 26 | - IL2CPP class utilities 27 | - Memory patching 28 | - Runtime obfuscation 29 | 30 | ## 🛠 Prerequisites 31 | 32 | - [iPhone15.5 SDK](https://github.com/Batchhh/SilentPwn/releases/latest) 33 | - IOS Development Tools 34 | - [Theos](https://theos.dev/) 35 | - Objective-C++ knowledge 36 | 37 | ## 🔧 Download Package 38 | 39 | Install the [package](https://github.com/Batchhh/SilentPwn/releases/latest) 40 | 41 | ## 🔧 Download iPhone15.5 SDK 42 | - [Download iPhone15.5 SDK in 2.0.0 Release](https://github.com/Batchhh/SilentPwn/releases/tag/2.0.0) 43 | ```bash 44 | mv iPhoneOS15.5.sdk $THEOS/sdks/ 45 | ``` 46 | 47 | ## 🔧 Build 48 | 49 | 1. Clone the repository 50 | ```bash 51 | git clone https://github.com/Batchhh/SilentPwn.git 52 | cd SilentPwn 53 | ``` 54 | 55 | 2. Build for theos 56 | ```bash 57 | $THEOS/bin/nicify.pl . && mv Batchh_SilentPwn*.nic.tar $THEOS/templates/ios 58 | ``` 59 | 60 | ## 🎉 Upload.sh 61 | 62 | Run the script to upload the package to your device 63 | ```bash 64 | ./Upload.sh 65 | ``` 66 | This script will automatically remove the old com.* files on the device and upload the new package, also install the package and respring the device if you want. 67 | 68 | ## 📖 Documentation 69 | 70 | Detailed documentation available in [wiki.md](https://github.com/Batchhh/SilentPwn/wiki/SilentPwn-iOS-Modification-Wiki) 71 | 72 | ## 🚧 Usage Warning 73 | 74 | **Disclaimer**: This framework is for research and educational purposes. Ensure compliance with legal and ethical guidelines. 75 | 76 | ## 📜 License 77 | 78 | Distributed under the GNU General Public License v3.0. 79 | See `LICENSE` for more information. 80 | 81 | ## 🏆 Credits 82 | 83 | - [Batchh on GitHub](https://github.com/Batchhh) 84 | - [Batchh on iOSGods](https://iosgods.com/profile/10738750-batchh/) 85 | - [MJx0 - KittyMemory](https://github.com/MJx0/KittyMemory) 86 | - LeFF Obfuscate.h 87 | 88 | **⚠️ Ethical Use Only ⚠️** 89 | -------------------------------------------------------------------------------- /Source/Config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Config.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Configuration file for SilentPwn 10 | */ 11 | 12 | #pragma once 13 | 14 | extern const char* getCurrentFrameworkName(); 15 | extern const char* getCurrentFrameworkPath(); 16 | extern const char* getAppName(); 17 | extern const char* getAppVersion(); 18 | 19 | #define frameWork getCurrentFrameworkName() 20 | #define frameWorkPath getCurrentFrameworkPath() 21 | #define appName getAppName() 22 | #define appVersion getAppVersion() 23 | 24 | #define Author "@@@USER@@" 25 | #define Version "@@APPVERSION@@" 26 | #define iOSGodsAuthorProfile "https://iosgods.com/" // add your profile link 27 | 28 | #define About "Author: " Author "\nVersion: " Version 29 | #define changelog "Added stuff" 30 | 31 | #define WAIT 3.0 // seconds 32 | 33 | #define DebugMode true // This will enable debug tools 34 | -------------------------------------------------------------------------------- /Source/Framework/Framework.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Framework.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main framework header for SilentPwn iOS modification 10 | */ 11 | 12 | #pragma once 13 | #import 14 | #import 15 | 16 | const char* getFrameworkName(); 17 | const char* getFrameworkPath(); 18 | const char* getCurrentFrameworkName(); 19 | const char* getCurrentFrameworkPath(); 20 | 21 | const char* getAppName(); 22 | const char* getAppVersion(); 23 | 24 | BOOL editJSONFile(NSString *fileName, void (^editBlock)(NSMutableDictionary *jsonDict)); 25 | -------------------------------------------------------------------------------- /Source/Framework/Framework.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Framework.mm 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main framework header for SilentPwn iOS modification 10 | */ 11 | 12 | #import 13 | #import 14 | #import "Framework.h" 15 | 16 | static const char *g_frameworkName = NULL; 17 | static const char *g_frameworkPath = NULL; 18 | 19 | const char *getFrameworkPath() { 20 | @autoreleasepool { 21 | NSString *appPath = [[NSBundle mainBundle] bundlePath]; 22 | NSString *mainBundleName = [[NSBundle mainBundle] 23 | objectForInfoDictionaryKey:@"CFBundleExecutable"]; 24 | 25 | // First, try UnityFramework 26 | NSString *unityFrameworkPath = 27 | [appPath stringByAppendingPathComponent: 28 | @"Frameworks/UnityFramework.framework/UnityFramework"]; 29 | void *handle = 30 | dlopen([unityFrameworkPath fileSystemRepresentation], RTLD_LAZY); 31 | 32 | if (handle) { 33 | dlclose(handle); 34 | return strdup([unityFrameworkPath UTF8String]); 35 | } 36 | 37 | // If UnityFramework fails, use the main bundle executable 38 | NSString *finalPath = [appPath stringByAppendingPathComponent:mainBundleName]; 39 | return strdup([finalPath UTF8String]); 40 | } 41 | } 42 | 43 | const char *getCurrentFrameworkPath() { 44 | if (g_frameworkPath == NULL) { 45 | g_frameworkPath = getFrameworkPath(); 46 | } 47 | return g_frameworkPath; 48 | } 49 | 50 | const char *getFrameworkName() { 51 | @autoreleasepool { 52 | NSString *mainBundleName = [[NSBundle mainBundle] 53 | objectForInfoDictionaryKey:@"CFBundleExecutable"]; 54 | NSString *appPath = [[NSBundle mainBundle] bundlePath]; 55 | 56 | // First, try UnityFramework 57 | NSString *unityFrameworkPath = 58 | [appPath stringByAppendingPathComponent: 59 | @"Frameworks/UnityFramework.framework/UnityFramework"]; 60 | void *handle = 61 | dlopen([unityFrameworkPath fileSystemRepresentation], RTLD_LAZY); 62 | 63 | if (handle) { 64 | dlclose(handle); 65 | return "UnityFramework"; 66 | } 67 | // If UnityFramework fails, use the main bundle executable name 68 | return strdup([mainBundleName UTF8String]); 69 | } 70 | } 71 | 72 | const char *getCurrentFrameworkName() { 73 | if (g_frameworkName == NULL) { 74 | g_frameworkName = getFrameworkName(); 75 | } 76 | return g_frameworkName; 77 | } 78 | 79 | BOOL editJSONFile(NSString *fileName, void (^editBlock)(NSMutableDictionary *jsonDict)) { 80 | @autoreleasepool { 81 | NSString *documentsPath = 82 | [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) 83 | firstObject]; 84 | NSString *fullPath = [documentsPath stringByAppendingPathComponent:fileName]; 85 | 86 | NSError *error = nil; 87 | NSData *jsonData = [NSData dataWithContentsOfFile:fullPath 88 | options:0 89 | error:&error]; 90 | if (error) return NO; 91 | 92 | NSMutableDictionary *jsonDict = 93 | [NSJSONSerialization JSONObjectWithData:jsonData 94 | options:NSJSONReadingMutableContainers 95 | error:&error]; 96 | if (error) return NO; 97 | 98 | if (![jsonDict isKindOfClass:[NSMutableDictionary class]]) return NO; 99 | 100 | editBlock(jsonDict); 101 | 102 | NSData *updatedJsonData = [NSJSONSerialization dataWithJSONObject:jsonDict 103 | options:NSJSONWritingPrettyPrinted 104 | error:&error]; 105 | if (error) return NO; 106 | 107 | return [updatedJsonData writeToFile:fullPath atomically:YES]; 108 | } 109 | } 110 | 111 | const char *getAppName() { 112 | @autoreleasepool { 113 | NSString *bundleName = [[NSBundle mainBundle] 114 | objectForInfoDictionaryKey:@"CFBundleDisplayName"]; 115 | if (!bundleName) { 116 | bundleName = 117 | [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; 118 | } 119 | return strdup([bundleName UTF8String]) ?: "Unknown"; 120 | } 121 | } 122 | 123 | const char *getAppVersion() { 124 | @autoreleasepool { 125 | NSString *version = [[NSBundle mainBundle] 126 | objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 127 | return strdup([version UTF8String]) ?: "Unknown"; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Source/Memory/Helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Helper.h 3 | * Project: SilentPwn 4 | * Description: Low-level Assembly Language Helpers for ARM64 Architecture 5 | * 6 | * This header provides a comprehensive set of ARM64 assembly language patterns 7 | * and instructions for low-level memory manipulation, type handling, and 8 | * system-level operations. 9 | * 10 | * Key Features: 11 | * - Direct ARM64 assembly language snippets 12 | * - Numeric type handling (int, long, float, double) 13 | * - Stack and frame management 14 | * - Bitwise and arithmetic operations 15 | * - Type conversions 16 | * 17 | * Usage: 18 | * These assembly patterns can be used for: 19 | * - Performance-critical code 20 | * - Memory manipulation 21 | * - Custom numeric algorithms 22 | * - Low-level system interactions 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | // Memory read and write operations 33 | template 34 | void SetValue(void* ptr, uint64_t offset, T value) { 35 | *(T*)((uint64_t)(ptr) + offset) = value; 36 | } 37 | 38 | template 39 | T GetValue(void* ptr, uint64_t offset) { 40 | return *(T*)((uint64_t)(ptr) + offset); 41 | } 42 | 43 | inline void* AccessClass(void* ptr, uint64_t offset) { 44 | return *(void**)((uint64_t)(ptr) + offset); 45 | } 46 | 47 | namespace ASM { 48 | // Basic Control Flow 49 | extern const std::string RET; // Return from function 50 | extern const std::string NOP; // No operation 51 | extern const std::string BREAKPOINT; // Trigger breakpoint 52 | extern const std::string INFINITE_LOOP; // Infinite loop 53 | extern const std::string JUMP_ALWAYS; // Unconditional jump 54 | 55 | // Register Manipulation 56 | extern const std::string BOOL_TRUE; // Set return value to true 57 | extern const std::string BOOL_FALSE; // Set return value to false 58 | 59 | // Stack and Frame Management 60 | extern const std::string PUSH_ALL_REGS; // Save frame and link registers 61 | extern const std::string POP_ALL_REGS; // Restore frame and link registers 62 | extern const std::string STACK_FRAME_SETUP; // Allocate stack frame 63 | extern const std::string STACK_FRAME_TEAR; // Deallocate stack frame 64 | extern const std::string PUSH_CALLEE_SAVED_REGS; // Push callee-saved registers 65 | extern const std::string POP_CALLEE_SAVED_REGS; // Pop callee-saved registers 66 | extern const std::string ALLOCATE_STACK_LARGE; // Allocate large stack frame 67 | extern const std::string DEALLOCATE_STACK_LARGE; // Deallocate large stack frame 68 | extern const std::string STACK_PROBE; // Ensure stack guard page is mapped 69 | extern const std::string SAVE_LINK_REGISTER; // Save link register to stack 70 | extern const std::string RESTORE_LINK_REGISTER; // Restore link register from stack 71 | extern const std::string ALIGN_STACK_16BYTE; // Ensure 16-byte stack alignment 72 | extern const std::string CREATE_STACK_FRAME_WITH_LOCALS; // Create stack frame with local variables 73 | 74 | // System and Memory Interactions 75 | extern const std::string SYSCALL_INTERRUPT; // System call 76 | extern const std::string MEMORY_BARRIER; // Data memory barrier 77 | extern const std::string MEMORY_SYNC; // Data synchronization barrier 78 | 79 | // Branching and Jumping 80 | extern const std::string BRANCH_LINK; // Branch with link (function call) 81 | extern const std::string CONDITIONAL_JUMP; // Conditional branch if not equal 82 | 83 | // Integer Operations 84 | extern const std::string ASM_INT_ZERO; // Set 32-bit integer to zero 85 | extern const std::string ASM_LONG_ZERO; // Set 64-bit integer to zero 86 | extern const std::string ASM_INT_MAX_VAL; // Set 32-bit integer to maximum value 87 | extern const std::string ASM_LONG_MAX_VAL; // Set 64-bit integer to maximum value 88 | extern const std::string ASM_INT_MIN_VAL; // Set 32-bit integer to minimum value 89 | extern const std::string ASM_LONG_MIN_VAL; // Set 64-bit integer to minimum value 90 | 91 | // Integer Arithmetic 92 | extern const std::string INT_ADD; // Add two 32-bit integers 93 | extern const std::string LONG_ADD; // Add two 64-bit integers 94 | extern const std::string INT_SUB; // Subtract two 32-bit integers 95 | extern const std::string LONG_SUB; // Subtract two 64-bit integers 96 | extern const std::string INT_MUL; // Multiply two 32-bit integers 97 | extern const std::string LONG_MUL; // Multiply two 64-bit integers 98 | 99 | // Floating Point Operations 100 | extern const std::string FLOAT_ZERO; // Set single-precision float to zero 101 | extern const std::string DOUBLE_ZERO; // Set double-precision float to zero 102 | extern const std::string FLOAT_MAX; // Set single-precision float to maximum value 103 | extern const std::string DOUBLE_MAX; // Set double-precision float to maximum value 104 | extern const std::string FLOAT_MIN; // Set single-precision float to minimum value 105 | extern const std::string DOUBLE_MIN; // Set double-precision float to minimum value 106 | 107 | // Floating Point Arithmetic 108 | extern const std::string FLOAT_ADD; // Add two single-precision floats 109 | extern const std::string DOUBLE_ADD; // Add two double-precision floats 110 | extern const std::string FLOAT_SUB; // Subtract two single-precision floats 111 | extern const std::string DOUBLE_SUB; // Subtract two double-precision floats 112 | extern const std::string FLOAT_MUL; // Multiply two single-precision floats 113 | extern const std::string DOUBLE_MUL; // Multiply two double-precision floats 114 | 115 | // Boolean and Comparison Operations 116 | extern const std::string BOOL_SET_TRUE; // Set boolean to true 117 | extern const std::string BOOL_SET_FALSE; // Set boolean to false 118 | extern const std::string INT_COMPARE_EQUAL; // Compare two 32-bit integers for equality 119 | extern const std::string LONG_COMPARE_EQUAL; // Compare two 64-bit integers for equality 120 | extern const std::string FLOAT_COMPARE_EQUAL; // Compare two single-precision floats for equality 121 | extern const std::string DOUBLE_COMPARE_EQUAL; // Compare two double-precision floats for equality 122 | 123 | // Type Conversion 124 | extern const std::string INT_TO_FLOAT; // Convert 32-bit integer to single-precision float 125 | extern const std::string INT_TO_DOUBLE; // Convert 32-bit integer to double-precision float 126 | extern const std::string LONG_TO_FLOAT; // Convert 64-bit integer to single-precision float 127 | extern const std::string LONG_TO_DOUBLE; // Convert 64-bit integer to double-precision float 128 | extern const std::string FLOAT_TO_INT; // Convert single-precision float to 32-bit integer 129 | extern const std::string DOUBLE_TO_INT; // Convert double-precision float to 32-bit integer 130 | 131 | // Bitwise Operations 132 | extern const std::string INT_BITWISE_AND; // Bitwise AND for 32-bit integers 133 | extern const std::string LONG_BITWISE_AND; // Bitwise AND for 64-bit integers 134 | extern const std::string INT_BITWISE_OR; // Bitwise OR for 32-bit integers 135 | extern const std::string LONG_BITWISE_OR; // Bitwise OR for 64-bit integers 136 | extern const std::string INT_BITWISE_XOR; // Bitwise XOR for 32-bit integers 137 | extern const std::string LONG_BITWISE_XOR; // Bitwise XOR for 64-bit integers 138 | 139 | // Floating Point and SIMD 140 | extern const std::string VECTOR_ZERO; // Zero a vector register 141 | extern const std::string FLOATING_POINT_MOVE; // Move floating point register 142 | 143 | // Instance Variable and Function Pointer Operations 144 | // Memory Load and Store 145 | extern const std::string LOAD_INSTANCE_VAR_8BIT; // Load 8-bit instance variable 146 | extern const std::string LOAD_INSTANCE_VAR_16BIT; // Load 16-bit instance variable 147 | extern const std::string LOAD_INSTANCE_VAR_32BIT; // Load 32-bit instance variable 148 | extern const std::string LOAD_INSTANCE_VAR_64BIT; // Load 64-bit instance variable 149 | extern const std::string STORE_INSTANCE_VAR_8BIT; // Store 8-bit instance variable 150 | extern const std::string STORE_INSTANCE_VAR_16BIT; // Store 16-bit instance variable 151 | extern const std::string STORE_INSTANCE_VAR_32BIT; // Store 32-bit instance variable 152 | extern const std::string STORE_INSTANCE_VAR_64BIT; // Store 64-bit instance variable 153 | 154 | // Function Pointer Manipulation 155 | extern const std::string LOAD_FUNCTION_PTR; // Load function pointer 156 | extern const std::string STORE_FUNCTION_PTR; // Store function pointer 157 | extern const std::string CALL_FUNCTION_PTR; // Call function through pointer 158 | extern const std::string COMPARE_FUNCTION_PTR; // Compare function pointers 159 | 160 | // Pointer Arithmetic and Manipulation 161 | extern const std::string OFFSET_INSTANCE_VAR; // Calculate offset to instance variable 162 | extern const std::string NULL_CHECK_PTR; // Check if pointer is null 163 | extern const std::string VALIDATE_PTR_RANGE; // Validate pointer is within a memory range 164 | 165 | // Advanced Pointer Operations 166 | extern const std::string ATOMIC_PTR_SWAP; // Atomic pointer swap 167 | extern const std::string VOLATILE_PTR_LOAD; // Volatile pointer load 168 | extern const std::string VOLATILE_PTR_STORE; // Volatile pointer store 169 | 170 | // Object Method Invocation 171 | extern const std::string LOAD_SELF_PTR; // Load self/this pointer 172 | extern const std::string VIRTUAL_METHOD_CALL; // Call virtual method through vtable 173 | extern const std::string INTERFACE_METHOD_DISPATCH; // Interface method dispatch 174 | } 175 | -------------------------------------------------------------------------------- /Source/Memory/Helper.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Helper.mm 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Helper functions for KittyMemory framework 10 | */ 11 | 12 | 13 | #include "Helper.h" 14 | #include 15 | 16 | // Comprehensive list of ARM64 assembly language patterns 17 | namespace ASM { 18 | // Basic Control Flow 19 | const std::string RET = "ret"; // Return from function 20 | const std::string NOP = "nop"; // No operation 21 | const std::string BREAKPOINT = "brk #0"; // Trigger breakpoint 22 | const std::string INFINITE_LOOP = "b #0; nop"; // Infinite loop 23 | 24 | // Register Manipulation 25 | const std::string BOOL_TRUE = "mov w0, #1; ret"; // Set return value to true 26 | const std::string BOOL_FALSE = "mov w0, #0; ret"; // Set return value to false 27 | 28 | // Stack and Frame Management (Extended) 29 | const std::string PUSH_ALL_REGS = "stp x29, x30, [sp, #-16]!; add x29, sp, #0"; // Save frame and link registers 30 | const std::string POP_ALL_REGS = "ldp x29, x30, [sp], #16; ret"; // Restore frame and link registers 31 | const std::string STACK_FRAME_SETUP = "add sp, sp, #-16; mov fp, sp"; // Allocate stack frame 32 | const std::string STACK_FRAME_TEAR = "add sp, sp, #16; ret"; // Deallocate stack frame 33 | 34 | // Additional Stack Management Instructions 35 | const std::string PUSH_CALLEE_SAVED_REGS = "stp x19, x20, [sp, #-16]!; stp x21, x22, [sp, #-16]!"; // Push callee-saved registers 36 | const std::string POP_CALLEE_SAVED_REGS = "ldp x21, x22, [sp], #16; ldp x19, x20, [sp], #16"; // Restore callee-saved registers 37 | const std::string ALLOCATE_STACK_LARGE = "sub sp, sp, #256"; // Allocate a large stack frame (256 bytes) 38 | const std::string DEALLOCATE_STACK_LARGE = "add sp, sp, #256"; // Deallocate a large stack frame 39 | const std::string STACK_PROBE = "mov x16, sp; str xzr, [x16, #-16]!"; // Stack probe to ensure stack guard page is mapped 40 | const std::string SAVE_LINK_REGISTER = "str x30, [sp, #-16]!"; // Save link register to stack 41 | const std::string RESTORE_LINK_REGISTER = "ldr x30, [sp], #16"; // Restore link register from stack 42 | const std::string ALIGN_STACK_16BYTE = "and sp, sp, #-16"; // Ensure 16-byte stack alignment 43 | const std::string CREATE_STACK_FRAME_WITH_LOCALS = "stp x29, x30, [sp, #-32]!; mov x29, sp; sub sp, sp, #16"; // Create stack frame with space for local variables 44 | 45 | // System and Memory Interactions 46 | const std::string SYSCALL_INTERRUPT = "svc #0"; // System call 47 | const std::string MEMORY_BARRIER = "dmb sy"; // Data memory barrier 48 | const std::string MEMORY_SYNC = "dsb sy"; // Data synchronization barrier 49 | 50 | // Branching and Jumping 51 | const std::string BRANCH_LINK = "bl #4"; // Branch with link (function call) 52 | const std::string CONDITIONAL_JUMP = "b.ne #8"; // Conditional branch if not equal 53 | const std::string JUMP_ALWAYS = "b #0"; // Unconditional jump 54 | 55 | // High Value Constants and Floating Point 56 | const std::string HIGH_FLOAT = "fmov s0, #3.402823e+38; ret"; // Max single-precision float 57 | const std::string HIGH_DOUBLE = "fmov d0, #1.797693e+308; ret"; // Max double-precision float 58 | const std::string MAX_INT = "mov x0, #0x7FFFFFFFFFFFFFFF; ret"; // Maximum 64-bit signed integer 59 | 60 | // Bit Manipulation 61 | const std::string CLEAR_REGISTER = "mov x0, #0"; // Clear a register 62 | const std::string SET_ALL_BITS = "mov x0, #-1"; // Set all bits in register 63 | 64 | // Comparison and Conditional Execution 65 | const std::string COMPARE_ZERO = "cmp x0, #0"; // Compare register to zero 66 | const std::string EQUAL_ZERO = "beq #8"; // Branch if equal to zero 67 | const std::string NOT_EQUAL_ZERO = "bne #8"; // Branch if not equal to zero 68 | 69 | // Advanced Memory Operations 70 | const std::string PREFETCH_MEMORY = "prfm pldl1keep, [x0]"; // Prefetch memory 71 | const std::string CACHE_INVALIDATE = "dc civac, x0"; // Clean and invalidate data cache 72 | 73 | // Atomic Operations 74 | const std::string ATOMIC_INCREMENT = "ldadd w1, w2, [x0]"; // Atomic add 75 | const std::string ATOMIC_COMPARE_SWAP = "casal w1, w2, [x0]"; // Atomic compare and swap 76 | 77 | // Exception Handling 78 | const std::string EXCEPTION_RETURN = "eret"; // Exception return 79 | const std::string SUPERVISOR_CALL = "svc #0"; // Supervisor call 80 | 81 | // Floating Point and SIMD 82 | const std::string VECTOR_ZERO = "movi v0.16b, #0"; // Zero a vector register 83 | const std::string FLOATING_POINT_MOVE = "fmov d0, d1"; // Move floating point register 84 | 85 | // Numeric Type Handling and Manipulation 86 | // Integer Operations 87 | const std::string ASM_INT_ZERO = "mov w0, #0"; // Set 32-bit integer to zero 88 | const std::string ASM_LONG_ZERO = "mov x0, #0"; // Set 64-bit integer to zero 89 | const std::string ASM_INT_MAX_VAL = "mov w0, #0x7FFFFFFF"; // Set 32-bit integer to maximum value 90 | const std::string ASM_LONG_MAX_VAL = "mov x0, #0x7FFFFFFFFFFFFFFF"; // Set 64-bit integer to maximum value 91 | const std::string ASM_INT_MIN_VAL = "mov w0, #0x80000000"; // Set 32-bit integer to minimum value 92 | const std::string ASM_LONG_MIN_VAL = "mov x0, #0x8000000000000000"; // Set 64-bit integer to minimum value 93 | 94 | // Integer Arithmetic 95 | const std::string INT_ADD = "add w0, w1, w2"; // Add two 32-bit integers 96 | const std::string LONG_ADD = "add x0, x1, x2"; // Add two 64-bit integers 97 | const std::string INT_SUB = "sub w0, w1, w2"; // Subtract two 32-bit integers 98 | const std::string LONG_SUB = "sub x0, x1, x2"; // Subtract two 64-bit integers 99 | const std::string INT_MUL = "mul w0, w1, w2"; // Multiply two 32-bit integers 100 | const std::string LONG_MUL = "mul x0, x1, x2"; // Multiply two 64-bit integers 101 | 102 | // Floating Point Operations 103 | const std::string FLOAT_ZERO = "fmov s0, #0.0"; // Set single-precision float to zero 104 | const std::string DOUBLE_ZERO = "fmov d0, #0.0"; // Set double-precision float to zero 105 | const std::string FLOAT_MAX = "fmov s0, #3.402823e+38"; // Set single-precision float to maximum value 106 | const std::string DOUBLE_MAX = "fmov d0, #1.797693e+308"; // Set double-precision float to maximum value 107 | const std::string FLOAT_MIN = "fmov s0, #-3.402823e+38"; // Set single-precision float to minimum value 108 | const std::string DOUBLE_MIN = "fmov d0, #-1.797693e+308"; // Set double-precision float to minimum value 109 | 110 | // Floating Point Arithmetic 111 | const std::string FLOAT_ADD = "fadd s0, s1, s2"; // Add two single-precision floats 112 | const std::string DOUBLE_ADD = "fadd d0, d1, d2"; // Add two double-precision floats 113 | const std::string FLOAT_SUB = "fsub s0, s1, s2"; // Subtract two single-precision floats 114 | const std::string DOUBLE_SUB = "fsub d0, d1, d2"; // Subtract two double-precision floats 115 | const std::string FLOAT_MUL = "fmul s0, s1, s2"; // Multiply two single-precision floats 116 | const std::string DOUBLE_MUL = "fmul d0, d1, d2"; // Multiply two double-precision floats 117 | 118 | // Boolean and Comparison Operations 119 | const std::string BOOL_SET_TRUE = "mov w0, #1"; // Set boolean to true 120 | const std::string BOOL_SET_FALSE = "mov w0, #0"; // Set boolean to false 121 | const std::string INT_COMPARE_EQUAL = "cmp w0, w1; beq #8"; // Compare two 32-bit integers for equality 122 | const std::string LONG_COMPARE_EQUAL = "cmp x0, x1; beq #8"; // Compare two 64-bit integers for equality 123 | const std::string FLOAT_COMPARE_EQUAL = "fcmp s0, s1; beq #8"; // Compare two single-precision floats for equality 124 | const std::string DOUBLE_COMPARE_EQUAL = "fcmp d0, d1; beq #8"; // Compare two double-precision floats for equality 125 | 126 | // Type Conversion 127 | const std::string INT_TO_FLOAT = "scvtf s0, w0"; // Convert 32-bit integer to single-precision float 128 | const std::string INT_TO_DOUBLE = "scvtf d0, w0"; // Convert 32-bit integer to double-precision float 129 | const std::string LONG_TO_FLOAT = "scvtf s0, x0"; // Convert 64-bit integer to single-precision float 130 | const std::string LONG_TO_DOUBLE = "scvtf d0, x0"; // Convert 64-bit integer to double-precision float 131 | const std::string FLOAT_TO_INT = "fcvtzs w0, s0"; // Convert single-precision float to 32-bit integer 132 | const std::string DOUBLE_TO_INT = "fcvtzs w0, d0"; // Convert double-precision float to 32-bit integer 133 | 134 | // Bitwise Operations 135 | const std::string INT_BITWISE_AND = "and w0, w1, w2"; // Bitwise AND for 32-bit integers 136 | const std::string LONG_BITWISE_AND = "and x0, x1, x2"; // Bitwise AND for 64-bit integers 137 | const std::string INT_BITWISE_OR = "orr w0, w1, w2"; // Bitwise OR for 32-bit integers 138 | const std::string LONG_BITWISE_OR = "orr x0, x1, x2"; // Bitwise OR for 64-bit integers 139 | const std::string INT_BITWISE_XOR = "eor w0, w1, w2"; // Bitwise XOR for 32-bit integers 140 | const std::string LONG_BITWISE_XOR = "eor x0, x1, x2"; // Bitwise XOR for 64-bit integers 141 | } // namespace ASM 142 | -------------------------------------------------------------------------------- /Source/Memory/Hook/Hook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Hook.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main hook header for SilentPwn iOS modification 10 | */ 11 | 12 | 13 | // Hook.h 14 | #import 15 | #import "../Kitty/MemoryPatch.hpp" 16 | #import "../../UI/Menu.h" 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | typedef void (*HookCallback)(void); 21 | 22 | @interface Hook : NSObject 23 | 24 | // Basic hooking 25 | + (BOOL)hook:(uint64_t)address callback:(void * _Nonnull)callback original:(void * _Nullable * _Nullable)original; 26 | + (BOOL)hookSymbol:(NSString *)symbol callback:(void * _Nonnull)callback original:(void * _Nullable * _Nullable)original; 27 | 28 | // Advanced hooking with toggle support 29 | + (BOOL)hookAt:(uint64_t)address 30 | callback:(void * _Nonnull)callback 31 | original:(void * _Nullable * _Nullable)original 32 | withName:(NSString *)name; 33 | 34 | + (BOOL)hookSymbol:(NSString *)symbol 35 | callback:(void * _Nonnull)callback 36 | original:(void * _Nullable * _Nullable)original 37 | withName:(NSString *)name; 38 | 39 | // Hook management 40 | + (BOOL)toggleHookWithName:(NSString *)name enabled:(BOOL)enabled; 41 | + (BOOL)removeHookWithName:(NSString *)name; 42 | + (void)removeAllHooks; 43 | 44 | // Hook status 45 | + (BOOL)isHookEnabledWithName:(NSString *)name; 46 | + (NSArray *)activeHooks; 47 | 48 | // Utilities 49 | + (void * _Nullable)getOriginalFromName:(NSString *)name; 50 | + (uint64_t)getRealAddress:(uint64_t)address; 51 | 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /Source/Memory/Hook/Hook.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Hook.mm 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Memory hooking implementation for SilentPwn iOS modification 10 | */ 11 | 12 | 13 | // Hook.mm 14 | #import "Hook.h" 15 | #import 16 | #import 17 | 18 | @interface HookInfo : NSObject 19 | @property (nonatomic, assign) uint64_t address; 20 | @property (nonatomic, assign) void *callback; 21 | @property (nonatomic, assign) void *original; 22 | @property (nonatomic, assign) BOOL isSymbol; 23 | @property (nonatomic, strong) NSString *symbolName; 24 | @property (nonatomic, assign) BOOL isEnabled; 25 | @end 26 | 27 | @implementation HookInfo 28 | @end 29 | 30 | @implementation Hook { 31 | NSMutableDictionary *_hooks; 32 | } 33 | 34 | #pragma mark - Initialization 35 | 36 | + (instancetype)shared { 37 | static Hook *instance = nil; 38 | static dispatch_once_t onceToken; 39 | dispatch_once(&onceToken, ^{ 40 | instance = [[Hook alloc] init]; 41 | }); 42 | return instance; 43 | } 44 | 45 | - (instancetype)init { 46 | if (self = [super init]) { 47 | _hooks = [NSMutableDictionary dictionary]; 48 | } 49 | return self; 50 | } 51 | 52 | #pragma mark - Basic Hooking 53 | 54 | + (BOOL)hook:(uint64_t)address callback:(void *)callback original:(void **)original { 55 | NSString *name = [NSString stringWithFormat:@"hook_%llx", address]; 56 | return [self hookAt:address callback:callback original:original withName:name]; 57 | } 58 | 59 | + (BOOL)hookSymbol:(NSString *)symbol callback:(void *)callback original:(void **)original { 60 | return [self hookSymbol:symbol callback:callback original:original withName:symbol]; 61 | } 62 | 63 | #pragma mark - Advanced Hooking 64 | 65 | + (BOOL)hookAt:(uint64_t)address 66 | callback:(void *)callback 67 | original:(void **)original 68 | withName:(NSString *)name { 69 | if (!callback || !name.length) return NO; 70 | 71 | Hook *instance = [Hook shared]; 72 | 73 | // Check if hook already exists 74 | if (instance->_hooks[name]) { 75 | NSLog(@"Hook already exists with name: %@", name); 76 | return NO; 77 | } 78 | 79 | void *targetAddress = (void *)KittyMemory::getRealOffset(address); 80 | if (!targetAddress) { 81 | NSLog(@"Failed to get real address for: 0x%llx", address); 82 | return NO; 83 | } 84 | 85 | // Create hook info 86 | HookInfo *info = [[HookInfo alloc] init]; 87 | info.address = address; 88 | info.callback = callback; 89 | info.isSymbol = NO; 90 | info.isEnabled = YES; 91 | 92 | // Apply hook 93 | void *originalFunc = NULL; 94 | MSHookFunction(targetAddress, callback, &originalFunc); 95 | 96 | if (!originalFunc) { 97 | NSLog(@"Failed to hook address: 0x%llx", address); 98 | return NO; 99 | } 100 | 101 | info.original = originalFunc; 102 | if (original) *original = originalFunc; 103 | 104 | // Store hook info 105 | instance->_hooks[name] = info; 106 | 107 | NSLog(@"Successfully hooked address: 0x%llx with name: %@", address, name); 108 | return YES; 109 | } 110 | 111 | + (BOOL)hookSymbol:(NSString *)symbol 112 | callback:(void *)callback 113 | original:(void **)original 114 | withName:(NSString *)name { 115 | if (!callback || !symbol.length || !name.length) return NO; 116 | 117 | Hook *instance = [Hook shared]; 118 | 119 | // Check if hook already exists 120 | if (instance->_hooks[name]) { 121 | NSLog(@"Hook already exists with name: %@", name); 122 | return NO; 123 | } 124 | 125 | void *targetAddress = dlsym(RTLD_DEFAULT, symbol.UTF8String); 126 | if (!targetAddress) { 127 | NSLog(@"Failed to find symbol: %@", symbol); 128 | return NO; 129 | } 130 | 131 | // Create hook info 132 | HookInfo *info = [[HookInfo alloc] init]; 133 | info.symbolName = symbol; 134 | info.callback = callback; 135 | info.isSymbol = YES; 136 | info.isEnabled = YES; 137 | 138 | // Apply hook 139 | void *originalFunc = NULL; 140 | MSHookFunction(targetAddress, callback, &originalFunc); 141 | 142 | if (!originalFunc) { 143 | NSLog(@"Failed to hook symbol: %@", symbol); 144 | return NO; 145 | } 146 | 147 | info.original = originalFunc; 148 | if (original) *original = originalFunc; 149 | 150 | // Store hook info 151 | instance->_hooks[name] = info; 152 | 153 | NSLog(@"Successfully hooked symbol: %@ with name: %@", symbol, name); 154 | return YES; 155 | } 156 | 157 | #pragma mark - Hook Management 158 | 159 | + (BOOL)toggleHookWithName:(NSString *)name enabled:(BOOL)enabled { 160 | if (!name.length) return NO; 161 | 162 | Hook *instance = [Hook shared]; 163 | HookInfo *info = instance->_hooks[name]; 164 | 165 | if (!info) { 166 | NSLog(@"No hook found with name: %@", name); 167 | return NO; 168 | } 169 | 170 | if (info.isEnabled == enabled) return YES; 171 | 172 | void *targetAddress; 173 | if (info.isSymbol) { 174 | targetAddress = dlsym(RTLD_DEFAULT, [info.symbolName UTF8String]); 175 | } else { 176 | targetAddress = (void *)KittyMemory::getRealOffset(info.address); 177 | } 178 | 179 | if (!targetAddress) return NO; 180 | 181 | if (enabled) { 182 | MSHookFunction(targetAddress, info.callback, NULL); 183 | } else { 184 | MSHookFunction(targetAddress, info.original, NULL); 185 | } 186 | 187 | info.isEnabled = enabled; 188 | return YES; 189 | } 190 | 191 | + (BOOL)removeHookWithName:(NSString *)name { 192 | if (!name.length) return NO; 193 | 194 | Hook *instance = [Hook shared]; 195 | HookInfo *info = instance->_hooks[name]; 196 | 197 | if (!info) return NO; 198 | 199 | // Restore original function 200 | if (info.isEnabled) { 201 | [self toggleHookWithName:name enabled:NO]; 202 | } 203 | 204 | [instance->_hooks removeObjectForKey:name]; 205 | return YES; 206 | } 207 | 208 | + (void)removeAllHooks { 209 | Hook *instance = [Hook shared]; 210 | NSArray *hookNames = instance->_hooks.allKeys; 211 | 212 | for (NSString *name in hookNames) { 213 | [self removeHookWithName:name]; 214 | } 215 | } 216 | 217 | #pragma mark - Hook Status 218 | 219 | + (BOOL)isHookEnabledWithName:(NSString *)name { 220 | Hook *instance = [Hook shared]; 221 | HookInfo *info = instance->_hooks[name]; 222 | return info ? info.isEnabled : NO; 223 | } 224 | 225 | + (NSArray *)activeHooks { 226 | Hook *instance = [Hook shared]; 227 | return instance->_hooks.allKeys; 228 | } 229 | 230 | #pragma mark - Utilities 231 | 232 | + (void *)getOriginalFromName:(NSString *)name { 233 | Hook *instance = [Hook shared]; 234 | HookInfo *info = instance->_hooks[name]; 235 | return info ? info.original : NULL; 236 | } 237 | 238 | + (uint64_t)getRealAddress:(uint64_t)address { 239 | return KittyMemory::getRealOffset(address); 240 | } 241 | 242 | @end 243 | -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyArm64.cpp: -------------------------------------------------------------------------------- 1 | #include "KittyArm64.hpp" 2 | 3 | // refs to 4 | // https://github.com/CAS-Atlantic/AArch64-Encoding 5 | // https://github.com/bminor/binutils-gdb 6 | // https://github.com/capstone-engine/capstone 7 | // https://github.com/qemu/QEMU 8 | // https://reverseengineering.stackexchange.com/questions/15418/getting-function-address-by-reading-adrp-and-add-instruction-values 9 | // https://stackoverflow.com/questions/41906688/what-are-the-semantics-of-adrp-and-adrl-instructions-in-arm-assembly 10 | 11 | namespace KittyArm64 12 | { 13 | 14 | int32_t bit_from(uint32_t insn, int pos) 15 | { 16 | return ((1 << pos) & insn) >> pos; 17 | } 18 | 19 | int32_t bits_from(uint32_t insn, int pos, int l) 20 | { 21 | return (insn >> pos) & ((1 << l) - 1); 22 | } 23 | 24 | bool is_insn_adr(uint32_t insn) 25 | { 26 | return (insn & 0x9F000000) == 0x10000000; 27 | } 28 | 29 | bool is_insn_adrp(uint32_t insn) 30 | { 31 | return (insn & 0x9F000000) == 0x90000000; 32 | } 33 | 34 | // decode adr/adrp 35 | bool decode_adr_imm(uint32_t insn, int64_t *imm) 36 | { 37 | if (is_insn_adr(insn) || is_insn_adrp(insn)) 38 | { 39 | // 21-bit imm encoded in adrp. 40 | int64_t imm_val = bits_from(insn, 5, 19) << 2; // immhi 41 | imm_val |= bits_from(insn, 29, 2); // immlo 42 | 43 | if (is_insn_adrp(insn)) 44 | { 45 | // Retrieve msb of 21-bit-signed imm for sign extension. 46 | uint64_t msbt = (imm_val >> 20) & 1; 47 | 48 | // Real value is imm multiplied by 4k. Value now has 33-bit information. 49 | imm_val <<= 12; 50 | 51 | // Sign extend to 64-bit by repeating msbt 31 (64-33) times and merge it 52 | // with value. 53 | *imm = ((((uint64_t)(1) << 32) - msbt) << 33) | imm_val; 54 | } 55 | else // adr 56 | { 57 | // Sign-extend the 21-bit immediate. 58 | if (imm_val & (1 << (21 - 1))) 59 | imm_val |= ~((1LL << 21) - 1); 60 | 61 | *imm = imm_val; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | return false; 68 | } 69 | 70 | /* 71 | * 31 30 29 28 23 22 21 10 9 5 4 0 72 | * +--+--+--+-------------+--+-------------+-----+-----+ 73 | * |sf|op| S| 1 0 0 0 1 0 |sh| imm12 | Rn | Rd | 74 | * +--+--+--+-------------+--+-------------+-----+-----+ 75 | * 76 | * sf: 0 -> 32bit, 1 -> 64bit 77 | * op: 0 -> add , 1 -> sub 78 | * S: 1 -> set flags 79 | * sh: 1 -> LSL imm by 12 80 | */ 81 | 82 | int32_t decode_addsub_imm(uint32_t insn) 83 | { 84 | int32_t imm12 = bits_from(insn, 10, 12); 85 | 86 | bool shift = bit_from(insn, 22) == 1; 87 | 88 | if (shift) 89 | { 90 | imm12 <<= 12; 91 | } 92 | 93 | return imm12; 94 | } 95 | 96 | bool is_insn_ld(uint32_t insn) 97 | { 98 | // L bit 99 | return bit_from(insn, 22) == 1; 100 | } 101 | 102 | bool is_insn_ldst(uint32_t insn) 103 | { 104 | return (insn & 0x0a000000) == 0x08000000; 105 | } 106 | 107 | bool is_insn_ldst_uimm(uint32_t insn) 108 | { 109 | return (insn & 0x3b000000) == 0x39000000; 110 | } 111 | 112 | // decode Load/store unsigned immediate 113 | bool decode_ldrstr_uimm(uint32_t insn, int32_t *imm12) 114 | { 115 | if (is_insn_ldst_uimm(insn)) 116 | { 117 | *imm12 = bits_from(insn, 10, 12); 118 | // shift with scale value 119 | *imm12 <<= bits_from(insn, 30, 2); // size bits 120 | 121 | return true; 122 | } 123 | 124 | return false; 125 | } 126 | 127 | } 128 | 129 | namespace KittyArm 130 | { 131 | int32_t decode_ldr_literal(uint32_t insn) 132 | { 133 | return KittyArm64::bits_from(insn, 0, 12); 134 | } 135 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyArm64.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace KittyArm64 8 | { 9 | 10 | int32_t bit_from(uint32_t insn, int pos); 11 | 12 | int32_t bits_from(uint32_t insn, int pos, int l); 13 | 14 | bool is_insn_adr(uint32_t insn); 15 | 16 | bool is_insn_adrp(uint32_t insn); 17 | 18 | bool decode_adr_imm(uint32_t insn, int64_t *imm); 19 | 20 | int32_t decode_addsub_imm(uint32_t insn); 21 | 22 | bool is_insn_ld(uint32_t insn); 23 | 24 | bool is_insn_ldst(uint32_t insn); 25 | 26 | bool is_insn_ldst_uimm(uint32_t insn); 27 | 28 | bool decode_ldrstr_uimm(uint32_t insn, int32_t *offset); 29 | 30 | } 31 | 32 | namespace KittyArm 33 | { 34 | int32_t decode_ldr_literal(uint32_t insn); 35 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyInclude.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "KittyUtils.hpp" 4 | #include "KittyMemory.hpp" 5 | #include "MemoryPatch.hpp" 6 | #include "KittyScanner.hpp" 7 | #include "KittyArm64.hpp" 8 | 9 | #ifdef __ANDROID__ 10 | using KittyMemory::ProcMap; 11 | using KittyScanner::RegisterNativeFn; 12 | using KittyScanner::ElfScanner; 13 | 14 | #elif __APPLE__ 15 | #include "writeData.hpp" 16 | using KittyMemory::seg_data_t; 17 | using KittyMemory::MemoryFileInfo; 18 | #endif -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyMemory.hpp: -------------------------------------------------------------------------------- 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 | #ifdef __ANDROID__ 16 | #include 17 | #include 18 | 19 | #elif __APPLE__ 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #endif 28 | 29 | #include "../../Config.h" 30 | #include "KittyUtils.hpp" 31 | 32 | #define KT_PAGE_SIZE (sysconf(_SC_PAGE_SIZE)) 33 | 34 | #define KT_PAGE_START(x) (uintptr_t(x) & ~(KT_PAGE_SIZE - 1)) 35 | #define KT_PAGE_END(x) (KT_PAGE_START(uintptr_t(x) + KT_PAGE_SIZE - 1)) 36 | #define KT_PAGE_OFFSET(x) (uintptr_t(x) - KT_PAGE_START(x)) 37 | #define KT_PAGE_LEN(x) (size_t(KT_PAGE_SIZE - KT_PAGE_OFFSET(x))) 38 | 39 | #define KT_PAGE_END2(x, len) (KT_PAGE_START(uintptr_t(x) + len - 1)) 40 | #define KT_PAGE_LEN2(x, len) \ 41 | (KT_PAGE_END2(x, len) - KT_PAGE_START(x) + KT_PAGE_SIZE) 42 | 43 | #define _PROT_RWX_ (PROT_READ | PROT_WRITE | PROT_EXEC) 44 | #define _PROT_RX_ (PROT_READ | PROT_EXEC) 45 | #define _PROT_RW_ (PROT_READ | PROT_WRITE) 46 | 47 | #define KITTY_LOG_TAG "KittyMemory" 48 | 49 | #ifdef __ANDROID__ 50 | #include 51 | 52 | #ifdef kITTYMEMORY_DEBUG 53 | #define KITTY_LOGD(fmt, ...) \ 54 | ((void)__android_log_print(ANDROID_LOG_DEBUG, KITTY_LOG_TAG, fmt, \ 55 | ##__VA_ARGS__)) 56 | #else 57 | #define KITTY_LOGD(fmt, ...) \ 58 | do { \ 59 | } while (0) 60 | #endif 61 | 62 | #define KITTY_LOGI(fmt, ...) \ 63 | ((void)__android_log_print(ANDROID_LOG_INFO, KITTY_LOG_TAG, fmt, \ 64 | ##__VA_ARGS__)) 65 | #define KITTY_LOGE(fmt, ...) \ 66 | ((void)__android_log_print(ANDROID_LOG_ERROR, KITTY_LOG_TAG, fmt, \ 67 | ##__VA_ARGS__)) 68 | 69 | #elif __APPLE__ 70 | #include 71 | 72 | #ifdef kITTYMEMORY_DEBUG 73 | #define KITTY_LOGD(fmt, ...) \ 74 | os_log(OS_LOG_DEFAULT, "D " KITTY_LOG_TAG ": " fmt, ##__VA_ARGS__) 75 | #else 76 | #define KITTY_LOGD(fmt, ...) \ 77 | do { \ 78 | } while (0) 79 | #endif 80 | 81 | #define KITTY_LOGI(fmt, ...) \ 82 | os_log(OS_LOG_DEFAULT, "I " KITTY_LOG_TAG ": " fmt, ##__VA_ARGS__) 83 | #define KITTY_LOGE(fmt, ...) \ 84 | os_log_error(OS_LOG_DEFAULT, "E " KITTY_LOG_TAG ": " fmt, ##__VA_ARGS__) 85 | 86 | #endif 87 | 88 | namespace KittyMemory { 89 | /* 90 | * Reads an address content into a buffer 91 | */ 92 | bool memRead(const void *address, void *buffer, size_t len); 93 | 94 | #ifdef __ANDROID__ 95 | 96 | class ProcMap { 97 | public: 98 | unsigned long long startAddress; 99 | unsigned long long endAddress; 100 | size_t length; 101 | int protection; 102 | bool readable, writeable, executable, is_private, is_shared, is_ro, is_rw, 103 | is_rx; 104 | unsigned long long offset; 105 | std::string dev; 106 | unsigned long inode; 107 | std::string pathname; 108 | 109 | ProcMap() 110 | : startAddress(0), endAddress(0), length(0), protection(0), 111 | readable(false), writeable(false), executable(false), is_private(false), 112 | is_shared(false), is_ro(false), is_rw(false), is_rx(false), offset(0), 113 | inode(0) {} 114 | 115 | inline bool isValid() const { return (startAddress && endAddress && length); } 116 | inline bool isUnknown() const { return pathname.empty(); } 117 | inline bool isValidELF() const { 118 | return isValid() && length > 4 && readable && 119 | memcmp((const void *)startAddress, "\177ELF", 4) == 0; 120 | } 121 | inline bool contains(uintptr_t address) const { 122 | return address >= startAddress && address < endAddress; 123 | } 124 | inline std::string toString() { 125 | return KittyUtils::String::Fmt( 126 | "%llx-%llx %c%c%c%c %llx %s %lu %s", startAddress, endAddress, 127 | readable ? 'r' : '-', writeable ? 'w' : '-', executable ? 'x' : '-', 128 | is_private ? 'p' : 's', offset, dev.c_str(), inode, pathname.c_str()); 129 | } 130 | }; 131 | 132 | /* 133 | * mprotect wrapper 134 | */ 135 | int setAddressProtection(const void *address, size_t length, int protection); 136 | 137 | /* 138 | * Writes buffer content to an address 139 | */ 140 | bool memWrite(void *address, const void *buffer, size_t len); 141 | 142 | /* 143 | * /proc/self/cmdline 144 | */ 145 | std::string getProcessName(); 146 | 147 | /* 148 | * Gets info of all maps in current process 149 | */ 150 | std::vector getAllMaps(); 151 | 152 | /* 153 | * Gets info of all maps which pathname equals @name in current process 154 | */ 155 | std::vector getMapsEqual(const std::vector &maps, 156 | const std::string &name); 157 | 158 | /* 159 | * Gets info of all maps which pathname contains @name in current process 160 | */ 161 | std::vector getMapsContain(const std::vector &maps, 162 | const std::string &name); 163 | 164 | /* 165 | * Gets info of all maps which pathname ends with @name in current process 166 | */ 167 | std::vector getMapsEndWith(const std::vector &maps, 168 | const std::string &name); 169 | 170 | /* 171 | * Gets map info of an address in self process 172 | */ 173 | ProcMap getAddressMap(const std::vector &maps, const void *address); 174 | 175 | /* 176 | * Gets info of all maps which pathname equals @name in current process 177 | */ 178 | inline std::vector getMapsEqual(const std::string &name) { 179 | return getMapsEqual(getAllMaps(), name); 180 | } 181 | 182 | /* 183 | * Gets info of all maps which pathname contains @name in current process 184 | */ 185 | inline std::vector getMapsContain(const std::string &name) { 186 | return getMapsContain(getAllMaps(), name); 187 | } 188 | 189 | /* 190 | * Gets info of all maps which pathname ends with @name in current process 191 | */ 192 | inline std::vector getMapsEndWith(const std::string &name) { 193 | return getMapsEndWith(getAllMaps(), name); 194 | } 195 | 196 | /* 197 | * Gets map info of an address in self process 198 | */ 199 | inline ProcMap getAddressMap(const void *address) { 200 | return getAddressMap(getAllMaps(), address); 201 | } 202 | 203 | /* 204 | * Gets the base map of a loaded shared object 205 | */ 206 | ProcMap getElfBaseMap(const std::string &name); 207 | 208 | #elif __APPLE__ 209 | 210 | enum Memory_Status { 211 | KMS_FAILED = 0, 212 | KMS_SUCCESS, 213 | KMS_INV_ADDR, 214 | KMS_INV_LEN, 215 | KMS_INV_BUF, 216 | KMS_ERR_PROT, 217 | KMS_ERR_GET_PAGEINFO, 218 | KMS_ERR_VMWRITE, 219 | }; 220 | 221 | struct seg_data_t { 222 | uintptr_t start, end; 223 | unsigned long size; 224 | seg_data_t() : start(0), end(0), size(0) {} 225 | }; 226 | 227 | class MemoryFileInfo { 228 | public: 229 | uint32_t index; 230 | #ifdef __LP64__ 231 | const mach_header_64 *header; 232 | #else 233 | const mach_header *header; 234 | #endif 235 | const char *name; 236 | intptr_t address; 237 | 238 | MemoryFileInfo() : index(0), header(nullptr), name(nullptr), address(0) {} 239 | 240 | inline seg_data_t getSegment(const char *seg_name) const { 241 | seg_data_t data{}; 242 | if (!header || !seg_name) 243 | return data; 244 | data.start = uintptr_t(getsegmentdata(header, seg_name, &data.size)); 245 | data.end = data.start + data.size; 246 | return data; 247 | } 248 | 249 | inline seg_data_t getSection(const char *seg_name, 250 | const char *sect_name) const { 251 | seg_data_t data{}; 252 | if (!header || !seg_name || !sect_name) 253 | return data; 254 | data.start = 255 | uintptr_t(getsectiondata(header, seg_name, sect_name, &data.size)); 256 | data.end = data.start + data.size; 257 | return data; 258 | } 259 | }; 260 | 261 | /* 262 | * Writes buffer content to an address 263 | */ 264 | Memory_Status memWrite(void *address, const void *buffer, size_t len); 265 | 266 | /* 267 | * vm_region_recurse_64 wrapper 268 | */ 269 | kern_return_t getPageInfo(vm_address_t region, 270 | vm_region_submap_short_info_64 *info_out); 271 | 272 | /* 273 | * returns base executable info 274 | */ 275 | MemoryFileInfo getBaseInfo(); 276 | 277 | /* 278 | * find in memory file info by checking if target loaded object file ends with 279 | * @fileName 280 | */ 281 | MemoryFileInfo getMemoryFileInfo(const std::string &fileName); 282 | 283 | /* 284 | * returns the absolue address of a relative offset of a file in memory or NULL 285 | * as fileName for base executable 286 | */ 287 | uintptr_t getAbsoluteAddress(const char *fileName, uintptr_t address); 288 | 289 | inline uint64_t getRealOffset(uint64_t offset) { 290 | return getAbsoluteAddress(frameWork, offset); 291 | } 292 | 293 | #endif 294 | 295 | } // namespace KittyMemory 296 | 297 | #ifdef __APPLE__ 298 | 299 | namespace KittyScanner { 300 | uintptr_t findSymbol(const KittyMemory::MemoryFileInfo &info, 301 | const std::string &symbol); 302 | uintptr_t findSymbol(const std::string &lib, const std::string &symbol); 303 | 304 | } // namespace KittyScanner 305 | 306 | #endif // __APPLE__ 307 | -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyScanner.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "KittyMemory.hpp" 9 | 10 | namespace KittyScanner 11 | { 12 | /** 13 | * Search for bytes within a memory range and return all results 14 | * 15 | * @start: search start address 16 | * @end: search end address 17 | * @bytes: bytes to search 18 | * @mask: bytes mask x/? 19 | * 20 | * @return vector list of all found bytes addresses 21 | */ 22 | std::vector findBytesAll(const uintptr_t start, const uintptr_t end, const char *bytes, const std::string& mask); 23 | 24 | /** 25 | * Search for bytes within a memory range and return first result 26 | * 27 | * @start: search start address 28 | * @end: search end address 29 | * @bytes: bytes to search 30 | * @mask: bytes mask x/? 31 | * 32 | * @return first found bytes address 33 | */ 34 | uintptr_t findBytesFirst(const uintptr_t start, const uintptr_t end, const char *bytes, const std::string& mask); 35 | 36 | /** 37 | * Search for hex within a memory range and return all results 38 | * 39 | * @start: search start address 40 | * @end: search end address 41 | * @hex: hex to search 42 | * @mask: hex mask x/? 43 | * 44 | * @return vector list of all found hex addresses 45 | */ 46 | std::vector findHexAll(const uintptr_t start, const uintptr_t end, std::string hex, const std::string& mask); 47 | 48 | /** 49 | * Search for hex within a memory range and return first result 50 | * 51 | * @start: search start address 52 | * @end: search end address 53 | * @hex: hex to search 54 | * @mask: hex mask x/? 55 | * 56 | * @return first found hex address 57 | */ 58 | uintptr_t findHexFirst(const uintptr_t start, const uintptr_t end, std::string hex, const std::string& mask); 59 | 60 | /** 61 | * Search for ida pattern within a memory range and return all results 62 | * 63 | * @param start: search start address 64 | * @param end: search end address 65 | * @param pattern: hex bytes and wildcard "?" ( FF DD ? 99 CC ? 00 ) 66 | * 67 | * @return vector list of all found pattern addresses 68 | */ 69 | std::vector findIdaPatternAll(const uintptr_t start, const uintptr_t end, const std::string& pattern); 70 | 71 | /** 72 | * Search for ida pattern within a memory range and return first result 73 | * 74 | * @param start: search start address 75 | * @param end: search end address 76 | * @param pattern: hex bytes and wildcard "?" ( FF DD ? 99 CC ? 00 ) 77 | * 78 | * @return first found pattern address 79 | */ 80 | uintptr_t findIdaPatternFirst(const uintptr_t start, const uintptr_t end, const std::string& pattern); 81 | 82 | /** 83 | * Search for data within a memory range and return all results 84 | * 85 | * @start: search start address 86 | * @end: search end address 87 | * @data: data to search 88 | * @size: data size 89 | * 90 | * @return vector list of all found data addresses 91 | */ 92 | std::vector findDataAll(const uintptr_t start, const uintptr_t end, const void *data, size_t size); 93 | 94 | 95 | /** 96 | * Search for data within a memory range and return first result 97 | * 98 | * @start: search start address 99 | * @end: search end address 100 | * @data: data to search 101 | * @size: data size 102 | * 103 | * @return first found data address 104 | */ 105 | uintptr_t findDataFirst(const uintptr_t start, const uintptr_t end, const void *data, size_t size); 106 | 107 | #ifdef __ANDROID__ 108 | 109 | class RegisterNativeFn 110 | { 111 | public: 112 | char *name; 113 | char *signature; 114 | void *fnPtr; 115 | 116 | RegisterNativeFn() : name(nullptr), signature(nullptr), fnPtr(nullptr) {} 117 | inline bool isValid() const { return (name != nullptr && signature != nullptr && fnPtr != nullptr); } 118 | }; 119 | 120 | /** 121 | * search for string "name" references to find the JNINativeMethod array 122 | */ 123 | RegisterNativeFn findRegisterNativeFn(const class ElfScanner &elf, const std::string &name); 124 | 125 | class ElfScanner 126 | { 127 | private: 128 | uintptr_t _elfBase; 129 | ElfW_(Ehdr) _ehdr; 130 | uintptr_t _phdr; 131 | std::vector _phdrs; 132 | int _loads; 133 | uintptr_t _loadBias, _loadSize; 134 | uintptr_t _bss; 135 | size_t _bssSize; 136 | uintptr_t _dynamic; 137 | std::vector _dynamics; 138 | uintptr_t _stringTable, _symbolTable, _elfHashTable, _gnuHashTable; 139 | size_t _strsz, _syment; 140 | KittyMemory::ProcMap _base_segment; 141 | std::vector _segments; 142 | 143 | public: 144 | ElfScanner() 145 | : _elfBase(0) 146 | , _phdr(0) 147 | , _loads(0) 148 | , _loadBias(0) 149 | , _loadSize(0) 150 | , _bss(0) 151 | , _bssSize(0) 152 | , _dynamic(0) 153 | , _stringTable(0) 154 | , _symbolTable(0) 155 | , _elfHashTable(0) 156 | , _gnuHashTable(0) 157 | , _strsz(0) 158 | , _syment(0) 159 | { 160 | } 161 | 162 | ElfScanner(uintptr_t elfBase, const std::vector &maps); 163 | ElfScanner(uintptr_t elfBase) : ElfScanner(elfBase, KittyMemory::getAllMaps()) {} 164 | 165 | static inline ElfScanner createWithBase(uintptr_t elfBase) 166 | { 167 | return ElfScanner(elfBase); 168 | } 169 | static inline ElfScanner createWithMap(const KittyMemory::ProcMap& map) 170 | { 171 | return ElfScanner(map.startAddress); 172 | } 173 | static inline ElfScanner createWithPath(const std::string &path) 174 | { 175 | return ElfScanner(KittyMemory::getElfBaseMap(path).startAddress); 176 | } 177 | 178 | inline bool isValid() const 179 | { 180 | return _loads && !_phdrs.empty() && _loadBias && _loadSize && !_dynamics.empty() && _stringTable && _symbolTable && _strsz && _syment; 181 | } 182 | 183 | inline uintptr_t base() const { return _elfBase; } 184 | 185 | inline uintptr_t end() const { return _elfBase + _loadSize; } 186 | 187 | inline ElfW_(Ehdr) header() const { return _ehdr; } 188 | 189 | inline uintptr_t phdr() const { return _phdr; } 190 | 191 | inline std::vector programHeaders() const { return _phdrs; } 192 | 193 | inline int loads() const { return _loads; } 194 | 195 | inline uintptr_t loadBias() const { return _loadBias; } 196 | 197 | inline uintptr_t loadSize() const { return _loadSize; } 198 | 199 | inline uintptr_t bss() const { return _bss; } 200 | 201 | inline size_t bssSize() const { return _bssSize; } 202 | 203 | inline uintptr_t dynamic() const { return _dynamic; } 204 | 205 | inline std::vector dynamics() const { return _dynamics; } 206 | 207 | inline uintptr_t stringTable() const { return _stringTable; } 208 | 209 | inline uintptr_t symbolTable() const { return _symbolTable; } 210 | 211 | inline uintptr_t elfHashTable() const { return _elfHashTable; } 212 | 213 | inline uintptr_t gnuHashTable() const { return _gnuHashTable; } 214 | 215 | inline size_t stringTableSize() const { return _strsz; } 216 | 217 | inline size_t symbolEntrySize() const { return _syment; } 218 | 219 | /** 220 | * lookup symbol name in current ELF 221 | * @return absolute address of symbol 222 | */ 223 | uintptr_t findSymbol(const std::string& symbolName) const; 224 | 225 | inline KittyMemory::ProcMap baseSegment() const { return _base_segment; } 226 | 227 | inline std::vector segments() const { return _segments; } 228 | 229 | inline std::string filePath() const { return _base_segment.pathname; } 230 | 231 | static std::vector getAllELFs(); 232 | 233 | /** 234 | * lookup symbol name in all loaded ELFs 235 | * @return a vector of symbol absolute address and the ELF where the symbol was found in 236 | */ 237 | static std::vector> findSymbolAll(const std::string& symbolName); 238 | }; 239 | 240 | #endif // __ANDROID__ 241 | 242 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "KittyUtils.hpp" 2 | 3 | namespace KittyUtils { 4 | 5 | #ifdef __ANDROID__ 6 | std::string getExternalStorage() 7 | { 8 | char *storage = getenv("EXTERNAL_STORAGE"); 9 | return storage ? storage : "/sdcard"; 10 | } 11 | 12 | int getAndroidVersion() 13 | { 14 | static int ver = 0; 15 | if (ver > 0) 16 | return ver; 17 | 18 | char buf[0xff] = { 0 }; 19 | if (__system_property_get("ro.build.version.release", buf)) 20 | ver = std::atoi(buf); 21 | 22 | return ver; 23 | } 24 | 25 | int getAndroidSDK() 26 | { 27 | static int sdk = 0; 28 | if (sdk > 0) 29 | return sdk; 30 | 31 | char buf[0xff] = { 0 }; 32 | if (__system_property_get("ro.build.version.sdk", buf)) 33 | sdk = std::atoi(buf); 34 | 35 | return sdk; 36 | } 37 | #endif 38 | 39 | std::string fileNameFromPath(const std::string &filePath) 40 | { 41 | std::string filename; 42 | const size_t last_slash_idx = filePath.find_last_of("/\\"); 43 | if (std::string::npos != last_slash_idx) 44 | filename = filePath.substr(last_slash_idx + 1); 45 | return filename; 46 | } 47 | 48 | std::string fileDirectory(const std::string &filePath) 49 | { 50 | std::string directory; 51 | const size_t last_slash_idx = filePath.find_last_of("/\\"); 52 | if (std::string::npos != last_slash_idx) 53 | directory = filePath.substr(0, last_slash_idx); 54 | return directory; 55 | } 56 | 57 | std::string fileExtension(const std::string &filePath) 58 | { 59 | std::string ext; 60 | const size_t last_slash_idx = filePath.find_last_of("."); 61 | if (std::string::npos != last_slash_idx) 62 | ext = filePath.substr(last_slash_idx + 1); 63 | return ext; 64 | } 65 | 66 | void String::Trim(std::string &str) 67 | { 68 | // https://www.techiedelight.com/remove-whitespaces-string-cpp/ 69 | str.erase(std::remove_if(str.begin(), str.end(), [](char c) 70 | { return (c == ' ' || c == '\n' || c == '\r' || 71 | c == '\t' || c == '\v' || c == '\f'); }), 72 | str.end()); 73 | } 74 | 75 | bool String::ValidateHex(std::string &hex) 76 | { 77 | if (hex.empty()) return false; 78 | 79 | if (hex.compare(0, 2, "0x") == 0) 80 | hex.erase(0, 2); 81 | 82 | Trim(hex); // first remove spaces 83 | 84 | if (hex.length() < 2 || hex.length() % 2 != 0) return false; 85 | 86 | for (size_t i = 0; i < hex.length(); i++) { 87 | if (!std::isxdigit((unsigned char) hex[i])) 88 | return false; 89 | } 90 | 91 | return true; 92 | } 93 | 94 | std::string String::Fmt(const char *fmt, ...) 95 | { 96 | if (!fmt) 97 | return ""; 98 | 99 | va_list args; 100 | 101 | va_start(args, fmt); 102 | size_t size = vsnprintf(nullptr, 0, fmt, args) + 1; // extra space for '\0' 103 | va_end(args); 104 | 105 | std::vector buffer(size, '\0'); 106 | 107 | va_start(args, fmt); 108 | vsnprintf(&buffer[0], size, fmt, args); 109 | va_end(args); 110 | 111 | return std::string(&buffer[0]); 112 | } 113 | 114 | std::string String::Random(size_t length) 115 | { 116 | static const std::string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 117 | 118 | thread_local static std::default_random_engine rnd(std::random_device{}()); 119 | thread_local static std::uniform_int_distribution dist(0, chars.size()-1); 120 | 121 | std::string str(length, '\0'); 122 | for (size_t i = 0; i < length; ++i) 123 | str[i] = chars[dist(rnd)]; 124 | 125 | return str; 126 | } 127 | 128 | // https://tweex.net/post/c-anything-tofrom-a-hex-string/ 129 | 130 | /* 131 | Convert a block of data to a hex string 132 | */ 133 | std::string data2Hex( 134 | const void *data, //!< Data to convert 135 | const size_t dataLength //!< Length of the data to convert 136 | ) { 137 | const auto *byteData = reinterpret_cast(data); 138 | std::stringstream hexStringStream; 139 | 140 | hexStringStream << std::hex << std::setfill('0'); 141 | for (size_t index = 0; index < dataLength; ++index) 142 | hexStringStream << std::setw(2) << static_cast(byteData[index]); 143 | return hexStringStream.str(); 144 | } 145 | 146 | /* 147 | Convert a hex string to a block of data 148 | */ 149 | void dataFromHex( 150 | const std::string &in, //!< Input hex string 151 | void *data //!< Data store 152 | ) { 153 | size_t length = in.length(); 154 | auto *byteData = reinterpret_cast(data); 155 | 156 | std::stringstream hexStringStream; 157 | hexStringStream >> std::hex; 158 | for (size_t strIndex = 0, dataIndex = 0; strIndex < length; ++dataIndex) { 159 | // Read out and convert the string two characters at a time 160 | const char tmpStr[3] = {in[strIndex++], in[strIndex++], 0}; 161 | 162 | // Reset and fill the string stream 163 | hexStringStream.clear(); 164 | hexStringStream.str(tmpStr); 165 | 166 | // Do the conversion 167 | int tmpValue = 0; 168 | hexStringStream >> tmpValue; 169 | byteData[dataIndex] = static_cast(tmpValue); 170 | } 171 | } 172 | 173 | #ifdef __ANDROID__ 174 | 175 | // refs to 176 | // https://refspecs.linuxfoundation.org/elf/elf.pdf 177 | // https://flapenguin.me/elf-dt-hash 178 | // https://flapenguin.me/elf-dt-gnu-hash 179 | 180 | namespace Elf { 181 | namespace ElfHash { 182 | uint32_t HashSymName(const char *name) { 183 | uint32_t h = 0, g; 184 | for (; *name; name++) { 185 | h = (h << 4) + *name; 186 | g = h & 0xf0000000; 187 | if (g) 188 | h ^= g >> 24; 189 | h &= ~g; 190 | } 191 | return h; 192 | } 193 | 194 | const ElfW_(Sym) *LookupByName(uintptr_t elfhash, 195 | uintptr_t symtab, 196 | uintptr_t strtab, 197 | size_t syment, 198 | size_t strsz, 199 | const char *symbol_name) { 200 | 201 | const auto *elf_hash = reinterpret_cast(elfhash); 202 | const auto *symbol_table = reinterpret_cast(symtab); 203 | const auto *string_table = reinterpret_cast(strtab); 204 | 205 | const size_t num_bucket = elf_hash[0]; 206 | if (!num_bucket) 207 | return nullptr; 208 | 209 | const size_t num_chain = elf_hash[1]; 210 | if (!num_chain) 211 | return nullptr; 212 | 213 | const uint32_t *bucket = elf_hash + 2; 214 | const uint32_t *chain = bucket + num_bucket; 215 | 216 | const uint32_t name_hash = HashSymName(symbol_name); 217 | for (uint32_t i = bucket[name_hash % num_bucket]; i != 0 && i < num_chain; i = chain[i]) { 218 | const auto *symbol = reinterpret_cast(symbol_table + (syment * i)); 219 | if (!symbol || symbol->st_name >= strsz) 220 | break; 221 | 222 | std::string sym_str = std::string(string_table + symbol->st_name); 223 | if (!sym_str.empty() && sym_str == symbol_name) 224 | return symbol; 225 | } 226 | 227 | return nullptr; 228 | } 229 | } 230 | } 231 | 232 | namespace Elf { 233 | namespace GnuHash { 234 | uint32_t HashSymName(const char *name) { 235 | uint32_t h = 5381; 236 | for (; *name; name++) 237 | h = (h << 5) + h + *name; 238 | return h; 239 | } 240 | 241 | const ElfW_(Sym) *LookupByName(uintptr_t gnuhash, 242 | uintptr_t symtab, 243 | uintptr_t strtab, 244 | size_t syment, 245 | size_t strsz, 246 | const char *symbol_name) { 247 | 248 | const auto *gnu_hash = reinterpret_cast(gnuhash); 249 | const auto *symbol_table = reinterpret_cast(symtab); 250 | const auto *string_table = reinterpret_cast(strtab); 251 | 252 | const uint32_t name_hash = HashSymName(symbol_name); 253 | 254 | const uint32_t num_buckets = gnu_hash[0]; 255 | if (!num_buckets) 256 | return nullptr; 257 | 258 | const uint32_t sym_offset = gnu_hash[1]; 259 | 260 | const uint32_t bloom_size = gnu_hash[2]; 261 | // must be a power of 2 262 | if (!bloom_size || (bloom_size & (bloom_size - 1)) != 0) 263 | return nullptr; 264 | 265 | const uint32_t bloom_shift = gnu_hash[3]; 266 | const auto *bloom = reinterpret_cast(&gnu_hash[4]); 267 | const auto *buckets = reinterpret_cast(&bloom[bloom_size]); 268 | const uint32_t *chain = &buckets[num_buckets]; 269 | 270 | uintptr_t word = bloom[(name_hash / ELFCLASS_BITS_) % bloom_size]; 271 | uintptr_t mask = 0 272 | | (uintptr_t) 1 << (name_hash % ELFCLASS_BITS_) 273 | | (uintptr_t) 1 << ((name_hash >> bloom_shift) % ELFCLASS_BITS_); 274 | 275 | // If at least one bit is not set, a symbol is surely missing. 276 | if ((word & mask) != mask) 277 | return nullptr; 278 | 279 | uint32_t sym_idx = buckets[name_hash % num_buckets]; 280 | if (sym_idx < sym_offset) 281 | return nullptr; 282 | 283 | // Loop through the chain. 284 | while (true) { 285 | const auto *symbol = reinterpret_cast(symbol_table + (syment * sym_idx)); 286 | if (!symbol || symbol->st_name >= strsz) 287 | break; 288 | 289 | const uint32_t hash = chain[sym_idx - sym_offset]; 290 | if ((name_hash | 1) == (hash | 1)) { 291 | std::string sym_str = std::string(string_table + symbol->st_name); 292 | if (!sym_str.empty() && sym_str == symbol_name) 293 | return symbol; 294 | } 295 | 296 | // Chain ends with an element with the lowest bit set to 1. 297 | if (hash & 1) 298 | break; 299 | 300 | sym_idx++; 301 | } 302 | 303 | return nullptr; 304 | } 305 | } 306 | } 307 | 308 | #endif // __ANDROID__ 309 | 310 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/KittyUtils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef __ANDROID__ 14 | 15 | #include 16 | #ifdef __LP64__ 17 | #define ELFCLASS_BITS_ 64 18 | #define ELF_EICLASS_ 2 19 | #define ElfW_(x) Elf64_##x 20 | #define ELFW_(x) ELF64_##x 21 | #else 22 | #define ELFCLASS_BITS_ 32 23 | #define ELF_EICLASS_ 1 24 | #define ElfW_(x) Elf32_##x 25 | #define ELFW_(x) ELF32_##x 26 | #endif 27 | 28 | #endif // __ANDROID__ 29 | 30 | namespace KittyUtils { 31 | 32 | #ifdef __ANDROID__ 33 | std::string getExternalStorage(); 34 | int getAndroidVersion(); 35 | int getAndroidSDK(); 36 | #endif 37 | 38 | std::string fileNameFromPath(const std::string &filePath); 39 | std::string fileDirectory(const std::string &filePath); 40 | std::string fileExtension(const std::string &filePath); 41 | 42 | namespace String 43 | { 44 | static inline bool StartsWith(const std::string &str, const std::string &str2) 45 | { 46 | return str.length() >= str2.length() && str.compare(0, str2.length(), str2) == 0; 47 | } 48 | 49 | static inline bool Contains(const std::string &str, const std::string &str2) 50 | { 51 | return str.length() >= str2.length() && str.find(str2) != std::string::npos; 52 | } 53 | 54 | static inline bool EndsWith(const std::string &str, const std::string &str2) 55 | { 56 | return str.length() >= str2.length() && str.compare(str.length() - str2.length(), str2.length(), str2) == 0; 57 | } 58 | 59 | void Trim(std::string &str); 60 | 61 | bool ValidateHex(std::string &hex); 62 | 63 | std::string Fmt(const char *fmt, ...); 64 | 65 | std::string Random(size_t length); 66 | } // namespace String 67 | 68 | template 69 | T randInt(T min, T max) 70 | { 71 | using param_type = typename std::uniform_int_distribution::param_type; 72 | 73 | thread_local static std::mt19937 gen{std::random_device{}()}; 74 | thread_local static std::uniform_int_distribution dist; 75 | 76 | return dist(gen, param_type{min, max}); 77 | } 78 | 79 | template std::string data2Hex(const T &data) 80 | { 81 | const auto *byteData = reinterpret_cast(&data); 82 | std::stringstream hexStringStream; 83 | 84 | hexStringStream << std::hex << std::setfill('0'); 85 | for (size_t index = 0; index < sizeof(T); ++index) 86 | hexStringStream << std::setw(2) << static_cast(byteData[index]); 87 | 88 | return hexStringStream.str(); 89 | } 90 | 91 | std::string data2Hex(const void *data, const size_t dataLength); 92 | void dataFromHex(const std::string &in, void *data); 93 | 94 | template 95 | std::string HexDump(const void *address, size_t len) 96 | { 97 | if (!address || len == 0 || rowSize == 0) 98 | return ""; 99 | 100 | const unsigned char *data = static_cast(address); 101 | 102 | std::stringstream ss; 103 | ss << std::hex << std::uppercase << std::setfill('0'); 104 | 105 | size_t i, j; 106 | 107 | for (i = 0; i < len; i += rowSize) 108 | { 109 | // offset 110 | ss << std::setw(8) << i << ": "; 111 | 112 | // row bytes 113 | for (j = 0; (j < rowSize) && ((i + j) < len); j++) 114 | ss << std::setw(2) << static_cast(data[i + j]) << " "; 115 | 116 | // fill row empty space 117 | for (; j < rowSize; j++) 118 | ss << " "; 119 | 120 | // ASCII 121 | if (showASCII) 122 | { 123 | ss << " "; 124 | 125 | for (j = 0; (j < rowSize) && ((i + j) < len); j++) 126 | { 127 | if (std::isprint(data[i + j])) 128 | ss << data[i + j]; 129 | else 130 | ss << '.'; 131 | } 132 | } 133 | 134 | ss << std::endl; 135 | } 136 | 137 | return ss.str(); 138 | } 139 | 140 | #ifdef __ANDROID__ 141 | 142 | namespace Elf { 143 | namespace ElfHash { 144 | /** 145 | * Lookup symbol by name in hash table 146 | * 147 | * @elfhash: DT_HASH hash table address 148 | * @symtab: DT_SYMTAB symbol table address 149 | * @strtab: DT_STRTAB string table address 150 | * @syment: DT_SYMENT symbol table entry size address 151 | * @syment: DT_STRSZ string table size 152 | * 153 | * @return ElfSym pointer 154 | */ 155 | const ElfW_(Sym) *LookupByName(uintptr_t elfhash, 156 | uintptr_t symtab, 157 | uintptr_t strtab, 158 | size_t syment, 159 | size_t strsz, 160 | const char *symbol_name); 161 | } 162 | 163 | namespace GnuHash { 164 | /** 165 | * Lookup symbol by name in gnu hash table 166 | * 167 | * @elfhash: DT_GNU_HASH gnu hash table address 168 | * @symtab: DT_SYMTAB symbol table address 169 | * @strtab: DT_STRTAB string table address 170 | * @syment: DT_SYMENT symbol table entry size address 171 | * @syment: DT_STRSZ string table size 172 | * 173 | * @return ElfSym pointer 174 | */ 175 | const ElfW_(Sym) *LookupByName(uintptr_t gnuhash, 176 | uintptr_t symtab, 177 | uintptr_t strtab, 178 | size_t syment, 179 | size_t strsz, 180 | const char *symbol_name); 181 | } 182 | } 183 | 184 | #endif // __ANDROID__ 185 | 186 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/MemoryBackup.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.cpp 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #include "MemoryBackup.hpp" 8 | #include "KittyUtils.hpp" 9 | 10 | 11 | MemoryBackup::MemoryBackup() 12 | { 13 | _address = 0; 14 | _size = 0; 15 | _orig_code.clear(); 16 | } 17 | 18 | MemoryBackup::~MemoryBackup() 19 | { 20 | // clean up 21 | _orig_code.clear(); 22 | _orig_code.shrink_to_fit(); 23 | } 24 | 25 | 26 | MemoryBackup MemoryBackup::createBackup(uintptr_t absolute_address, size_t backup_size) 27 | { 28 | MemoryBackup backup; 29 | 30 | if (!absolute_address || !backup_size) return backup; 31 | 32 | backup._address = absolute_address; 33 | 34 | backup._size = backup_size; 35 | 36 | backup._orig_code.resize(backup_size); 37 | 38 | // backup current content 39 | KittyMemory::memRead(reinterpret_cast(backup._address), &backup._orig_code[0], backup_size); 40 | 41 | return backup; 42 | } 43 | 44 | #ifdef __ANDROID__ 45 | MemoryBackup MemoryBackup::createBackup(const KittyMemory::ProcMap &map, uintptr_t address, size_t backup_size) 46 | { 47 | if (!map.isValid() || !address || !backup_size) 48 | return MemoryBackup(); 49 | 50 | return createBackup(map.startAddress + address, backup_size); 51 | } 52 | 53 | #elif __APPLE__ 54 | MemoryBackup MemoryBackup::createBackup(const char *fileName, uintptr_t address, size_t backup_size) 55 | { 56 | if (!address || !backup_size) 57 | return MemoryBackup(); 58 | 59 | return createBackup(KittyMemory::getAbsoluteAddress(fileName, address), backup_size); 60 | } 61 | #endif 62 | 63 | bool MemoryBackup::isValid() const 64 | { 65 | return (_address != 0 && _size > 0 && _orig_code.size() == _size); 66 | } 67 | 68 | size_t MemoryBackup::get_BackupSize() const 69 | { 70 | return _size; 71 | } 72 | 73 | uintptr_t MemoryBackup::get_TargetAddress() const 74 | { 75 | return _address; 76 | } 77 | 78 | bool MemoryBackup::Restore() 79 | { 80 | if (!isValid()) return false; 81 | 82 | #ifdef __ANDROID__ 83 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size); 84 | #elif __APPLE__ 85 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == KittyMemory::KMS_SUCCESS; 86 | #endif 87 | } 88 | 89 | std::string MemoryBackup::get_CurrBytes() const 90 | { 91 | if (!isValid()) return ""; 92 | 93 | return KittyUtils::data2Hex(reinterpret_cast(_address), _size); 94 | } 95 | 96 | std::string MemoryBackup::get_OrigBytes() const 97 | { 98 | if (!isValid()) return ""; 99 | 100 | return KittyUtils::data2Hex(_orig_code.data(), _orig_code.size()); 101 | } -------------------------------------------------------------------------------- /Source/Memory/Kitty/MemoryBackup.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.h 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "KittyMemory.hpp" 14 | 15 | 16 | class MemoryBackup 17 | { 18 | private: 19 | uintptr_t _address; 20 | size_t _size; 21 | 22 | std::vector _orig_code; 23 | 24 | public: 25 | MemoryBackup(); 26 | ~MemoryBackup(); 27 | 28 | static MemoryBackup createBackup(uintptr_t absolute_address, size_t backup_size); 29 | 30 | #ifdef __ANDROID__ 31 | static MemoryBackup createBackup(const KittyMemory::ProcMap &map, uintptr_t address, size_t backup_size); 32 | #elif __APPLE__ 33 | static MemoryBackup createBackup(const char *fileName, uintptr_t address, size_t backup_size); 34 | #endif 35 | 36 | bool isValid() const; 37 | size_t get_BackupSize() const; 38 | uintptr_t get_TargetAddress() const; 39 | 40 | /* 41 | * Restores backup code 42 | */ 43 | bool Restore(); 44 | 45 | /* 46 | * Returns hex string of the current target address bytes 47 | */ 48 | std::string get_CurrBytes() const; 49 | 50 | /* 51 | * Returns hex string of the original bytes 52 | */ 53 | std::string get_OrigBytes() const; 54 | }; 55 | -------------------------------------------------------------------------------- /Source/Memory/Kitty/MemoryPatch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.cpp 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #include "MemoryPatch.hpp" 8 | #include "KittyUtils.hpp" 9 | 10 | #ifndef kNO_KEYSTONE 11 | #include "../../../Lib/Keystone/includes/keystone.h" 12 | #endif 13 | 14 | MemoryPatch::MemoryPatch() { 15 | _address = 0; 16 | _size = 0; 17 | _orig_code.clear(); 18 | _patch_code.clear(); 19 | } 20 | 21 | MemoryPatch::~MemoryPatch() { 22 | // clean up 23 | _orig_code.clear(); 24 | _orig_code.shrink_to_fit(); 25 | 26 | _patch_code.clear(); 27 | _patch_code.shrink_to_fit(); 28 | } 29 | 30 | MemoryPatch MemoryPatch::createWithBytes(uintptr_t absolute_address, 31 | const void *patch_code, 32 | size_t patch_size) { 33 | MemoryPatch patch; 34 | 35 | if (!absolute_address || !patch_code || patch_size < 1) 36 | return patch; 37 | 38 | patch._address = absolute_address; 39 | patch._size = patch_size; 40 | 41 | patch._orig_code.resize(patch_size); 42 | patch._patch_code.resize(patch_size); 43 | 44 | // initialize patch & backup current content 45 | KittyMemory::memRead(patch_code, &patch._patch_code[0], patch_size); 46 | KittyMemory::memRead(reinterpret_cast(patch._address), 47 | &patch._orig_code[0], patch_size); 48 | return patch; 49 | } 50 | 51 | MemoryPatch MemoryPatch::createWithHex(uintptr_t absolute_address, 52 | std::string hex) { 53 | MemoryPatch patch; 54 | 55 | if (!absolute_address || !KittyUtils::String::ValidateHex(hex)) 56 | return patch; 57 | 58 | patch._address = absolute_address; 59 | patch._size = hex.length() / 2; 60 | 61 | patch._orig_code.resize(patch._size); 62 | patch._patch_code.resize(patch._size); 63 | 64 | // initialize patch 65 | KittyUtils::dataFromHex(hex, &patch._patch_code[0]); 66 | 67 | // backup current content 68 | KittyMemory::memRead(reinterpret_cast(patch._address), 69 | &patch._orig_code[0], patch._size); 70 | return patch; 71 | } 72 | 73 | #ifndef kNO_KEYSTONE 74 | MemoryPatch MemoryPatch::createWithAsm(uintptr_t absolute_address, 75 | MP_ASM_ARCH asm_arch, 76 | const std::string &asm_code, 77 | uintptr_t asm_address) { 78 | MemoryPatch patch; 79 | 80 | if (!absolute_address || asm_code.empty()) 81 | return patch; 82 | 83 | ks_engine *ks = nullptr; 84 | ks_err err = KS_ERR_ARCH; 85 | 86 | switch (asm_arch) { 87 | case MP_ASM_ARM32: 88 | err = ks_open(KS_ARCH_ARM, KS_MODE_LITTLE_ENDIAN, &ks); 89 | break; 90 | case MP_ASM_ARM64: 91 | err = ks_open(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN, &ks); 92 | break; 93 | case MP_ASM_x86: 94 | err = ks_open(KS_ARCH_X86, KS_MODE_32, &ks); 95 | break; 96 | case MP_ASM_x86_64: 97 | err = ks_open(KS_ARCH_X86, KS_MODE_64, &ks); 98 | break; 99 | default: 100 | KITTY_LOGE("Unknown MP_ASM_ARCH '%d'.", asm_arch); 101 | return patch; 102 | } 103 | 104 | if (err != KS_ERR_OK) { 105 | KITTY_LOGE("ks_open failed with error = '%s'.", ks_strerror(err)); 106 | return patch; 107 | } 108 | 109 | unsigned char *insn_bytes = nullptr; 110 | size_t insn_count = 0, insn_size = 0; 111 | int rt = ks_asm(ks, asm_code.c_str(), asm_address, &insn_bytes, &insn_size, 112 | &insn_count); 113 | 114 | if (rt == 0 && insn_bytes != nullptr && insn_size) { 115 | patch = createWithBytes(absolute_address, insn_bytes, insn_size); 116 | } 117 | 118 | if (insn_bytes != nullptr) { 119 | ks_free(insn_bytes); 120 | } 121 | 122 | ks_close(ks); 123 | 124 | if (rt) { 125 | KITTY_LOGE( 126 | "ks_asm failed (asm: %s, count = %zu, error = '%s') (code = %u).", 127 | asm_code.c_str(), insn_count, ks_strerror(ks_errno(ks)), ks_errno(ks)); 128 | } 129 | 130 | return patch; 131 | } 132 | #endif // kNO_KEYSTONE 133 | 134 | #ifdef __ANDROID__ 135 | 136 | MemoryPatch MemoryPatch::createWithBytes(const KittyMemory::ProcMap &map, 137 | uintptr_t address, 138 | const void *patch_code, 139 | size_t patch_size) { 140 | if (!address || !map.startAddress || !map.isValid()) 141 | return MemoryPatch(); 142 | 143 | return createWithBytes(map.startAddress + address, patch_code, patch_size); 144 | } 145 | 146 | MemoryPatch MemoryPatch::createWithHex(const KittyMemory::ProcMap &map, 147 | uintptr_t address, 148 | const std::string &hex) { 149 | if (!address || !map.startAddress || !map.isValid()) 150 | return MemoryPatch(); 151 | 152 | return createWithHex(map.startAddress + address, hex); 153 | } 154 | 155 | #elif __APPLE__ 156 | 157 | MemoryPatch MemoryPatch::createWithBytes(const char *fileName, 158 | uintptr_t address, 159 | const void *patch_code, 160 | size_t patch_size) { 161 | if (!address || !patch_code || !patch_size) 162 | return MemoryPatch(); 163 | 164 | uintptr_t absolute_address = 165 | KittyMemory::getAbsoluteAddress(fileName, address); 166 | return createWithBytes(absolute_address, patch_code, patch_size); 167 | } 168 | 169 | MemoryPatch MemoryPatch::createWithHex(const char *fileName, uintptr_t address, 170 | const std::string &hex) { 171 | if (!address || hex.empty()) 172 | return MemoryPatch(); 173 | 174 | uintptr_t absolute_address = 175 | KittyMemory::getAbsoluteAddress(fileName, address); 176 | return createWithHex(absolute_address, hex); 177 | } 178 | 179 | #endif 180 | 181 | #ifndef kNO_KEYSTONE 182 | 183 | #ifdef __ANDROID__ 184 | MemoryPatch MemoryPatch::createWithAsm(const KittyMemory::ProcMap &map, 185 | uintptr_t address, MP_ASM_ARCH asm_arch, 186 | const std::string &asm_code, 187 | uintptr_t asm_address) { 188 | if (!address || !map.startAddress || !map.isValid()) 189 | return MemoryPatch(); 190 | 191 | return createWithAsm(map.startAddress + address, asm_arch, asm_code, 192 | asm_address); 193 | } 194 | 195 | #elif __APPLE__ 196 | MemoryPatch MemoryPatch::createWithAsm(const char *fileName, uintptr_t address, 197 | MP_ASM_ARCH asm_arch, 198 | const std::string &asm_code, 199 | uintptr_t asm_address) { 200 | if (!address || asm_code.empty()) 201 | return MemoryPatch(); 202 | 203 | uintptr_t absolute_address = 204 | KittyMemory::getAbsoluteAddress(fileName, address); 205 | return createWithAsm(absolute_address, asm_arch, asm_code, asm_address); 206 | } 207 | #endif 208 | 209 | #endif // kNO_KEYSTONE 210 | 211 | bool MemoryPatch::isValid() const { 212 | return (_address != 0 && _size > 0 && _orig_code.size() == _size && 213 | _patch_code.size() == _size); 214 | } 215 | 216 | size_t MemoryPatch::get_PatchSize() const { return _size; } 217 | 218 | uintptr_t MemoryPatch::get_TargetAddress() const { return _address; } 219 | 220 | bool MemoryPatch::Restore() { 221 | if (!isValid()) 222 | return false; 223 | 224 | #ifdef __ANDROID__ 225 | return KittyMemory::memWrite(reinterpret_cast(_address), 226 | &_orig_code[0], _size); 227 | #elif __APPLE__ 228 | return KittyMemory::memWrite(reinterpret_cast(_address), 229 | &_orig_code[0], 230 | _size) == KittyMemory::KMS_SUCCESS; 231 | #endif 232 | } 233 | 234 | bool MemoryPatch::Modify() { 235 | if (!isValid()) 236 | return false; 237 | 238 | #ifdef __ANDROID__ 239 | return KittyMemory::memWrite(reinterpret_cast(_address), 240 | &_patch_code[0], _size); 241 | #elif __APPLE__ 242 | return KittyMemory::memWrite(reinterpret_cast(_address), 243 | &_patch_code[0], 244 | _size) == KittyMemory::KMS_SUCCESS; 245 | #endif 246 | } 247 | 248 | std::string MemoryPatch::get_CurrBytes() const { 249 | if (!isValid()) 250 | return ""; 251 | 252 | return KittyUtils::data2Hex(reinterpret_cast(_address), _size); 253 | } 254 | 255 | std::string MemoryPatch::get_OrigBytes() const { 256 | if (!isValid()) 257 | return ""; 258 | 259 | return KittyUtils::data2Hex(_orig_code.data(), _orig_code.size()); 260 | } 261 | 262 | std::string MemoryPatch::get_PatchBytes() const { 263 | if (!isValid()) 264 | return ""; 265 | 266 | return KittyUtils::data2Hex(_patch_code.data(), _patch_code.size()); 267 | } 268 | -------------------------------------------------------------------------------- /Source/Memory/Kitty/MemoryPatch.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.h 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "KittyMemory.hpp" 14 | 15 | enum MP_ASM_ARCH { 16 | MP_ASM_ARM32 = 0, 17 | MP_ASM_ARM64, 18 | MP_ASM_x86, 19 | MP_ASM_x86_64, 20 | }; 21 | 22 | class MemoryPatch 23 | { 24 | private: 25 | uintptr_t _address; 26 | size_t _size; 27 | 28 | std::vector _orig_code; 29 | std::vector _patch_code; 30 | 31 | public: 32 | MemoryPatch(); 33 | ~MemoryPatch(); 34 | 35 | static MemoryPatch createWithBytes(uintptr_t absolute_address, const void *patch_code, size_t patch_size); 36 | static MemoryPatch createWithHex(uintptr_t absolute_address, std::string hex); 37 | 38 | #ifndef kNO_KEYSTONE 39 | /** 40 | * Keystone assembler 41 | */ 42 | static MemoryPatch createWithAsm(uintptr_t absolute_address, MP_ASM_ARCH asm_arch, const std::string &asm_code, uintptr_t asm_address=0); 43 | #endif 44 | 45 | #ifdef __ANDROID__ 46 | 47 | static MemoryPatch createWithBytes(const KittyMemory::ProcMap &map, uintptr_t address, const void *patch_code, size_t patch_size); 48 | static MemoryPatch createWithHex(const KittyMemory::ProcMap &map, uintptr_t address, const std::string &hex); 49 | 50 | #ifndef kNO_KEYSTONE 51 | /** 52 | * Keystone assembler 53 | */ 54 | static MemoryPatch createWithAsm(const KittyMemory::ProcMap &map, uintptr_t address, MP_ASM_ARCH asm_arch, const std::string &asm_code, uintptr_t asm_address=0); 55 | #endif 56 | 57 | #elif __APPLE__ 58 | 59 | static MemoryPatch createWithBytes(const char *fileName, uintptr_t address, const void *patch_code, size_t patch_size); 60 | static MemoryPatch createWithHex(const char *fileName, uintptr_t address, const std::string &hex); 61 | 62 | #ifndef kNO_KEYSTONE 63 | /** 64 | * Keystone assembler 65 | */ 66 | static MemoryPatch createWithAsm(const char *fileName, uintptr_t address, MP_ASM_ARCH asm_arch, const std::string &asm_code, uintptr_t asm_address=0); 67 | #endif 68 | 69 | #endif 70 | 71 | 72 | bool isValid() const; 73 | size_t get_PatchSize() const; 74 | uintptr_t get_TargetAddress() const; 75 | 76 | /* 77 | * Restores the patch to the original value 78 | */ 79 | bool Restore(); 80 | 81 | /* 82 | * Applies patch modifications to the target address 83 | */ 84 | bool Modify(); 85 | 86 | /* 87 | * Returns hex string of the current target address bytes 88 | */ 89 | std::string get_CurrBytes() const; 90 | 91 | /* 92 | * Returns hex string of the original bytes 93 | */ 94 | std::string get_OrigBytes() const; 95 | 96 | /* 97 | * Returns hex string of the patch bytes 98 | */ 99 | std::string get_PatchBytes() const; 100 | }; 101 | -------------------------------------------------------------------------------- /Source/Memory/Kitty/writeData.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is an alternative for the old writeData that was made by HackJack & Razzile 3 | */ 4 | 5 | #pragma once 6 | 7 | #ifdef __APPLE__ 8 | 9 | #include 10 | #include 11 | 12 | #include "MemoryPatch.hpp" 13 | #include 14 | 15 | /* 16 | * expects file name and relative offset, you can pass NULL as filename for base executable 17 | */ 18 | static inline bool writeData8(const char *fileName, uintptr_t offset, uint8_t data) 19 | { 20 | return MemoryPatch::createWithBytes(fileName, offset, &data, 1).Modify(); 21 | } 22 | 23 | static inline bool writeData8(uintptr_t address, uint8_t data) 24 | { 25 | return MemoryPatch::createWithBytes(address, &data, 1).Modify(); 26 | } 27 | 28 | /* 29 | * expects file name and relative offset, you can pass NULL as filename for base executable 30 | */ 31 | static inline bool writeData16(const char *fileName, uintptr_t offset, uint16_t data) 32 | { 33 | uint16_t tmp_data = _OSSwapInt16(data); 34 | return MemoryPatch::createWithBytes(fileName, offset, &tmp_data, 2).Modify(); 35 | } 36 | 37 | static inline bool writeData16(uintptr_t address, uint16_t data) 38 | { 39 | uint16_t tmp_data = _OSSwapInt16(data); 40 | return MemoryPatch::createWithBytes(address, &tmp_data, 2).Modify(); 41 | } 42 | 43 | /* 44 | * expects file name and relative offset, you can pass NULL as filename for base executable 45 | */ 46 | static inline bool writeData32(const char *fileName, uintptr_t offset, uint32_t data) 47 | { 48 | uint32_t tmp_data = _OSSwapInt32(data); 49 | return MemoryPatch::createWithBytes(fileName, offset, &tmp_data, 4).Modify(); 50 | } 51 | 52 | static inline bool writeData32(uintptr_t address, uint32_t data) 53 | { 54 | uint32_t tmp_data = _OSSwapInt32(data); 55 | return MemoryPatch::createWithBytes(address, &tmp_data, 4).Modify(); 56 | } 57 | 58 | /* 59 | * expects file name and relative offset, you can pass NULL as filename for base executable 60 | */ 61 | static inline bool writeData64(const char *fileName, uintptr_t offset, uint64_t data) 62 | { 63 | uint64_t tmp_data = _OSSwapInt64(data); 64 | return MemoryPatch::createWithBytes(fileName, offset, &tmp_data, 8).Modify(); 65 | } 66 | 67 | static inline bool writeData64(uintptr_t address, uint64_t data) 68 | { 69 | uint64_t tmp_data = _OSSwapInt64(data); 70 | return MemoryPatch::createWithBytes(address, &tmp_data, 8).Modify(); 71 | } 72 | 73 | #endif -------------------------------------------------------------------------------- /Source/Memory/Memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Memory.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main memory header for SilentPwn iOS modification 10 | */ 11 | 12 | 13 | #pragma once 14 | 15 | // Core Memory Utilities 16 | #import "Kitty/KittyMemory.hpp" 17 | #import "Kitty/KittyUtils.hpp" 18 | #import "Kitty/MemoryPatch.hpp" 19 | 20 | // Helper Utilities 21 | #import "Helper.h" 22 | 23 | // Patching & Hooking 24 | #import "Hook/Hook.h" 25 | #import "Patch/Patch.h" 26 | 27 | // Thread 28 | #import "Thread/Thread.h" 29 | 30 | // Common namespace for easy access to ASM patterns 31 | using namespace ASM; 32 | -------------------------------------------------------------------------------- /Source/Memory/Patch/Patch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Patch.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main patch header for SilentPwn iOS modification 10 | */ 11 | 12 | 13 | #import 14 | #import "../Kitty/MemoryPatch.hpp" 15 | #import "../../Config.h" 16 | 17 | @interface Patch : NSObject 18 | 19 | // Single patch (uses default framework from Config.h) 20 | + (BOOL)offset:(uint64_t)offset patch:(NSString *)hexString; 21 | 22 | // Multiple patches (uses default framework from Config.h) 23 | + (BOOL)patches:(NSDictionary *)patches; 24 | 25 | // Assembly patch (uses default framework from Config.h) 26 | + (BOOL)offsetAsm:(uintptr_t)address asm_arch:(MP_ASM_ARCH)asm_arch asm_code:(const std::string &)asm_code; 27 | 28 | // Assembly patches using NSDictionary 29 | + (BOOL)patchesAsm:(NSDictionary *)patches asm_arch:(MP_ASM_ARCH)asm_arch; 30 | 31 | // Revert patches 32 | + (BOOL)revertOffset:(uint64_t)offset; 33 | + (void)revertAll; 34 | 35 | // Get bytes 36 | + (NSString *)getCurrentBytesAtOffset:(uint64_t)offset; 37 | + (NSString *)getOriginalBytesAtOffset:(uint64_t)offset; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Source/Memory/Patch/Patch.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Patch.mm 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Patching system for SilentPwn 10 | */ 11 | 12 | 13 | #import "Patch.h" 14 | #import 15 | 16 | // Store patches to allow reverting 17 | static std::map, MemoryPatch> patches; 18 | 19 | @implementation Patch 20 | 21 | #pragma mark - Single Patch 22 | 23 | + (BOOL)offset:(uint64_t)offset patch:(NSString *)hexString { 24 | if (!hexString) return NO; 25 | 26 | const char *hex = [hexString UTF8String]; 27 | 28 | MemoryPatch patch = MemoryPatch::createWithHex(frameWork, offset, hex); 29 | if (!patch.isValid()) return NO; 30 | 31 | patches[std::make_pair(frameWork, offset)] = patch; 32 | 33 | return patch.Modify(); 34 | } 35 | 36 | + (BOOL)offsetAsm:(uintptr_t)address asm_arch:(MP_ASM_ARCH)asm_arch asm_code:(const std::string &)asm_code { 37 | MemoryPatch patch = MemoryPatch::createWithAsm(frameWork, address, asm_arch, asm_code); 38 | if (!patch.isValid()) return NO; 39 | 40 | patches[std::make_pair(frameWork, address)] = patch; 41 | 42 | return patch.Modify(); 43 | } 44 | 45 | #pragma mark - Multiple Patches 46 | 47 | + (BOOL)patches:(NSDictionary *)patches { 48 | if (!patches || patches.count == 0) return NO; 49 | 50 | BOOL success = YES; 51 | for (NSNumber *offset in patches) { 52 | NSString *hex = patches[offset]; 53 | success &= [self offset:offset.unsignedLongLongValue patch:hex]; 54 | } 55 | return success; 56 | } 57 | 58 | + (BOOL)patchesAsm:(NSDictionary *)patches asm_arch:(MP_ASM_ARCH)asm_arch { 59 | if (!patches || patches.count == 0) return NO; 60 | 61 | BOOL success = YES; 62 | for (NSNumber *offset in patches) { 63 | NSString *asmCode = patches[offset]; 64 | success &= [self offsetAsm:offset.unsignedLongLongValue 65 | asm_arch:asm_arch 66 | asm_code:[asmCode UTF8String]]; 67 | } 68 | return success; 69 | } 70 | 71 | #pragma mark - Revert Patches 72 | 73 | + (BOOL)revertOffset:(uint64_t)offset { 74 | auto key = std::make_pair(frameWork, offset); 75 | auto it = patches.find(key); 76 | if (it == patches.end()) return NO; 77 | 78 | BOOL success = it->second.Restore(); 79 | if (success) { 80 | patches.erase(it); 81 | } 82 | return success; 83 | } 84 | 85 | + (void)revertAll { 86 | auto it = patches.begin(); 87 | while (it != patches.end()) { 88 | if (it->first.first == frameWork) { 89 | if (it->second.Restore()) { 90 | it = patches.erase(it); 91 | } else { 92 | ++it; 93 | } 94 | } else { 95 | ++it; 96 | } 97 | } 98 | } 99 | 100 | #pragma mark - Get Bytes 101 | 102 | + (NSString *)getCurrentBytesAtOffset:(uint64_t)offset { 103 | auto key = std::make_pair(frameWork, offset); 104 | auto it = patches.find(key); 105 | if (it == patches.end()) return nil; 106 | 107 | std::string bytes = it->second.get_CurrBytes(); 108 | return [NSString stringWithUTF8String:bytes.c_str()]; 109 | } 110 | 111 | + (NSString *)getOriginalBytesAtOffset:(uint64_t)offset { 112 | auto key = std::make_pair(frameWork, offset); 113 | auto it = patches.find(key); 114 | if (it == patches.end()) return nil; 115 | 116 | std::string bytes = it->second.get_OrigBytes(); 117 | return [NSString stringWithUTF8String:bytes.c_str()]; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Source/Memory/Thread/Thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Thread.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Thread 10 | */ 11 | #include 12 | 13 | namespace Thread { 14 | typedef void* (*ThreadFunction)(void*); 15 | 16 | // Create and start a detached thread with arguments 17 | bool CreateDetachedThread(ThreadFunction func, void* arg = nullptr); 18 | 19 | // Create and start a joinable thread with arguments 20 | pthread_t CreateJoinableThread(ThreadFunction func, void* arg = nullptr); 21 | } 22 | -------------------------------------------------------------------------------- /Source/Memory/Thread/Thread.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Thread.mm 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Thread 10 | */ 11 | #include "Thread.h" 12 | 13 | namespace Thread { 14 | bool CreateDetachedThread(void* (*func)(void*), void* arg) { 15 | pthread_t thread; 16 | pthread_attr_t attr; 17 | 18 | if (pthread_attr_init(&attr) != 0) { 19 | return false; 20 | } 21 | 22 | if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { 23 | pthread_attr_destroy(&attr); 24 | return false; 25 | } 26 | 27 | bool success = (pthread_create(&thread, &attr, func, arg) == 0); 28 | pthread_attr_destroy(&attr); 29 | 30 | return success; 31 | } 32 | 33 | pthread_t CreateJoinableThread(void* (*func)(void*), void* arg) { 34 | pthread_t thread; 35 | if (pthread_create(&thread, NULL, func, arg) != 0) { 36 | return 0; 37 | } 38 | return thread; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Source/UI/Icons.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Icons.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Icon constants for SilentPwn 10 | */ 11 | 12 | 13 | #import 14 | 15 | namespace Icons { 16 | extern NSString *const SETTINGS; // "gear" 17 | extern NSString *const PLAY; // "play.circle" 18 | extern NSString *const PAUSE; // "pause.circle" 19 | extern NSString *const RELOAD; // "arrow.clockwise" 20 | extern NSString *const HOME; // "house" 21 | extern NSString *const PROFILE; // "person.circle" 22 | extern NSString *const EDIT; // "pencil" 23 | extern NSString *const DELETE; // "trash" 24 | extern NSString *const ADD; // "plus.circle" 25 | extern NSString *const MENU; // "line.horizontal.3" 26 | extern NSString *const SEARCH; // "magnifyingglass" 27 | extern NSString *const SHARE; // "square.and.arrow.up" 28 | extern NSString *const FAVORITE; // "star" 29 | extern NSString *const WARNING; // "exclamationmark.triangle" 30 | extern NSString *const INFO; // "info.circle.fill" 31 | extern NSString *const BACK; // "chevron.left" 32 | extern NSString *const FORWARD; // "chevron.right" 33 | extern NSString *const CLOSE; // "xmark" 34 | extern NSString *const DOWNLOAD; // "arrow.down.circle" 35 | extern NSString *const LOCATION; // "location" 36 | extern NSString *const CAMERA; // "camera" 37 | extern NSString *const NOTIFY; // "bell" 38 | extern NSString *const LIST; // "list.bullet" 39 | extern NSString *const GRID; // "square.grid.2x2" 40 | extern NSString *const SORT; // "arrow.up.arrow.down" 41 | extern NSString *const FILTER; // "line.3.horizontal.decrease" 42 | extern NSString *const BLUETOOTH; // "bluetooth" 43 | extern NSString *const WIFI; // "wifi" 44 | extern NSString *const BATTERY; // "battery.75" 45 | extern NSString *const POWER; // "power" 46 | extern NSString *const VOLUME_UP; // "speaker.wave.2.fill" 47 | extern NSString *const VOLUME_DOWN; // "speaker.wave.1.fill" 48 | extern NSString *const VOLUME_MUTE; // "speaker.slash.fill" 49 | extern NSString *const AIRPLANE; // "airplane" 50 | extern NSString *const LOCK; // "lock.fill" 51 | extern NSString *const UNLOCK; // "lock.open.fill" 52 | extern NSString *const CLOUD; // "cloud.fill" 53 | extern NSString *const DOWNLOAD_CLOUD; // "cloud.download.fill" 54 | extern NSString *const UPLOAD_CLOUD; // "cloud.upload.fill" 55 | extern NSString *const MAIL; // "envelope.fill" 56 | extern NSString *const CHAT; // "message.fill" 57 | extern NSString *const PHONE; // "phone.fill" 58 | extern NSString *const CALENDAR; // "calendar" 59 | extern NSString *const TIMER; // "timer" 60 | extern NSString *const STOPWATCH; // "stopwatch.fill" 61 | extern NSString *const GAMEPAD; // "gamecontroller.fill" 62 | extern NSString *const TERMINAL; // "terminal.fill" 63 | extern NSString *const APP_BADGE; // "app.badge.fill" 64 | extern NSString *const MEMORY_CHIP; // "memorychip.fill" 65 | extern NSString *const GRID_3X3; // "square.grid.3x3.fill" 66 | extern NSString *const SWAP; // "arrow.triangle.swap" 67 | extern NSString *const RESET; // "arrow.counterclockwise" 68 | extern NSString *const TRASH; // "trash.fill" 69 | extern NSString *const CLIPBOARD; // "list.bullet.clipboard.fill" 70 | extern NSString *const XMARK_BIN; // "xmark.bin.fill" 71 | extern NSString *const PAPERPLANE; // "paperplane.fill" 72 | extern NSString *const SQUARE_AND_ARROW_DOWN; // "square.and.arrow.down" 73 | extern NSString *const SQUARE_AND_ARROW_UP; // "square.and.arrow.up" 74 | extern NSString *const QUESTIONMARK_CIRCLE; // "questionmark.circle" 75 | } // namespace Icons 76 | -------------------------------------------------------------------------------- /Source/UI/Icons.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Icons.mm 3 | // SilentPwn 4 | // 5 | // Created by Batchh on 2024-12-14. 6 | // Copyright 2024 Batchh. All rights reserved. 7 | 8 | #import "Icons.h" 9 | // Common icon names 10 | namespace Icons { 11 | NSString *const SETTINGS = @"gear"; 12 | NSString *const PLAY = @"play.circle"; 13 | NSString *const PAUSE = @"pause.circle"; 14 | NSString *const RELOAD = @"arrow.clockwise"; 15 | NSString *const HOME = @"house"; 16 | NSString *const PROFILE = @"person.circle"; 17 | NSString *const EDIT = @"pencil"; 18 | NSString *const DELETE = @"trash"; 19 | NSString *const ADD = @"plus.circle"; 20 | NSString *const MENU = @"line.horizontal.3"; 21 | NSString *const SEARCH = @"magnifyingglass"; 22 | NSString *const SHARE = @"square.and.arrow.up"; 23 | NSString *const FAVORITE = @"star"; 24 | NSString *const WARNING = @"exclamationmark.triangle"; 25 | NSString *const INFO = @"info.circle.fill"; 26 | NSString *const BACK = @"chevron.left"; 27 | NSString *const FORWARD = @"chevron.right"; 28 | NSString *const CLOSE = @"xmark"; 29 | NSString *const DOWNLOAD = @"arrow.down.circle"; 30 | NSString *const LOCATION = @"location"; 31 | NSString *const CAMERA = @"camera"; 32 | NSString *const NOTIFY = @"bell"; 33 | NSString *const LIST = @"list.bullet"; 34 | NSString *const GRID = @"square.grid.2x2"; 35 | NSString *const SORT = @"arrow.up.arrow.down"; 36 | NSString *const FILTER = @"line.3.horizontal.decrease"; 37 | NSString *const BLUETOOTH = @"bluetooth"; 38 | NSString *const WIFI = @"wifi"; 39 | NSString *const BATTERY = @"battery.75"; 40 | NSString *const POWER = @"power"; 41 | NSString *const VOLUME_UP = @"speaker.wave.2.fill"; 42 | NSString *const VOLUME_DOWN = @"speaker.wave.1.fill"; 43 | NSString *const VOLUME_MUTE = @"speaker.slash.fill"; 44 | NSString *const AIRPLANE = @"airplane"; 45 | NSString *const LOCK = @"lock.fill"; 46 | NSString *const UNLOCK = @"lock.open.fill"; 47 | NSString *const CLOUD = @"cloud.fill"; 48 | NSString *const DOWNLOAD_CLOUD = @"cloud.download.fill"; 49 | NSString *const UPLOAD_CLOUD = @"cloud.upload.fill"; 50 | NSString *const MAIL = @"envelope.fill"; 51 | NSString *const CHAT = @"message.fill"; 52 | NSString *const PHONE = @"phone.fill"; 53 | NSString *const CALENDAR = @"calendar"; 54 | NSString *const TIMER = @"timer"; 55 | NSString *const STOPWATCH = @"stopwatch.fill"; 56 | NSString *const GAMEPAD = @"gamecontroller.fill"; 57 | NSString *const TERMINAL = @"terminal.fill"; 58 | NSString *const APP_BADGE = @"app.badge.fill"; 59 | NSString *const MEMORY_CHIP = @"memorychip.fill"; 60 | NSString *const GRID_3X3 = @"square.grid.3x3.fill"; 61 | NSString *const SWAP = @"arrow.triangle.swap"; 62 | NSString *const RESET = @"arrow.counterclockwise"; 63 | NSString *const TRASH = @"trash.fill"; 64 | NSString *const CLIPBOARD = @"list.bullet.clipboard.fill"; 65 | NSString *const XMARK_BIN = @"xmark.bin.fill"; 66 | NSString *const PAPERPLANE = @"paperplane.fill"; 67 | NSString *const SQUARE_AND_ARROW_DOWN = @"square.and.arrow.down"; 68 | NSString *const SQUARE_AND_ARROW_UP = @"square.and.arrow.up"; 69 | NSString *const QUESTIONMARK_CIRCLE = @"questionmark.circle"; 70 | } // namespace Icons 71 | -------------------------------------------------------------------------------- /Source/UI/Menu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Menu.h 3 | * Project: SilentPwn 4 | * Author: Batchh 5 | * Created: 2024-12-14 6 | * 7 | * Copyright (c) 2024 Batchh. All rights reserved. 8 | * 9 | * Description: Main menu header for SilentPwn iOS modification 10 | */ 11 | 12 | 13 | #import "../Memory/Patch/Patch.h" 14 | #import 15 | #include 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface ModMenuButton : UIView 20 | 21 | @property(nonatomic, copy) void (^tapHandler)(void); 22 | @property(nonatomic, assign) BOOL isGlowing; 23 | - (void)setupGradientWithColors:(NSArray *)colors; 24 | - (void)showRippleEffect; 25 | 26 | @end 27 | 28 | @interface QuickAction : NSObject 29 | @property(nonatomic, strong) NSString *title; 30 | @property(nonatomic, strong) NSString *iconName; 31 | @property(nonatomic, copy) void (^action)(void); 32 | + (instancetype)actionWithTitle:(NSString *)title 33 | icon:(NSString *)iconName 34 | action:(void (^)(void))action; 35 | @end 36 | 37 | @interface ModMenu : UIView 38 | 39 | typedef NS_ENUM(NSInteger, ModMenuCategory) { 40 | ModMenuCategoryMain, 41 | ModMenuCategoryPlayer, 42 | ModMenuCategoryEnemy, 43 | ModMenuCategoryMisc, 44 | ModMenuCategoryInterface, 45 | ModMenuCategoryDebug 46 | }; 47 | 48 | typedef NS_ENUM(NSInteger, ModMenuLayout) { 49 | ModMenuLayoutRadial, 50 | ModMenuLayoutGrid, 51 | ModMenuLayoutList, 52 | ModMenuLayoutElasticString, 53 | }; 54 | 55 | typedef NS_ENUM(NSInteger, ModMenuTheme) { 56 | ModMenuThemeDark, // Default dark theme 57 | ModMenuThemeCyberpunk, // Vibrant cyberpunk colors 58 | ModMenuThemeNeon, // Bright neon colors 59 | ModMenuThemeMinimal, // Clean minimal design 60 | ModMenuThemePastel, // Soft pastel colors 61 | ModMenuThemeRetro, // Retro-style colors 62 | ModMenuThemeOcean, // Ocean-inspired colors 63 | ModMenuThemeForest, // Nature-inspired colors 64 | ModMenuThemeSunset, // Warm sunset colors 65 | ModMenuThemeMonochrome, // Black and white 66 | ModMenuThemeChristmas, // Christmas-inspired colors 67 | ModMenuThemeLavender, // Soft lavender and purple theme 68 | ModMenuThemeVaporwave, // Nostalgic 80s/90s aesthetic 69 | ModMenuThemeSteampunk, // Industrial metallic theme 70 | ModMenuThemeGalaxy, // Space and cosmic colors 71 | ModMenuThemeAqua, // Water and aquatic theme 72 | }; 73 | 74 | @property(nonatomic, strong) ModMenuButton *hubButton; 75 | @property(nonatomic, strong) NSMutableArray *categoryButtons; 76 | @property(nonatomic, strong) UIVisualEffectView *optionsPanel; 77 | @property(nonatomic, assign) BOOL isOpen; 78 | @property(nonatomic, assign) ModMenuCategory selectedCategory; 79 | @property(nonatomic, assign) NSInteger maxVisibleOptions; 80 | @property(nonatomic, assign) ModMenuLayout currentLayout; 81 | @property(nonatomic, assign) ModMenuTheme currentTheme; 82 | @property(nonatomic, strong) NSMutableArray *quickActions; 83 | @property(nonatomic, assign) NSInteger maxButtons; 84 | @property(nonatomic, strong) NSMutableArray *debugLogs; 85 | @property(nonatomic, strong) UITextView *logTextView; 86 | @property(nonatomic, strong) 87 | NSMutableDictionary *categoryIcons; 88 | @property(nonatomic, strong) NSMutableArray *memoryPatches; 89 | 90 | + (instancetype)shared; 91 | - (void)show; 92 | - (void)hide; 93 | - (void)savePosition; 94 | - (void)loadSavedPosition; 95 | - (void)setupCategoryButtons; 96 | - (void)toggleMenu; 97 | - (void)updateCategoryButtonPositions; 98 | 99 | - (void)addSlider:(NSString *)title 100 | initialValue:(float)value 101 | minValue:(float)min 102 | maxValue:(float)max 103 | forCategory:(NSInteger)category; 104 | - (void)addToggle:(NSString *)title 105 | initialValue:(BOOL)value 106 | forCategory:(NSInteger)category; 107 | 108 | - (float)getSliderValueFloat:(NSInteger)category 109 | withTitle:(NSString *)title; 110 | - (BOOL)getToggleValue:(NSInteger)category 111 | withTitle:(NSString *)title; 112 | - (NSInteger)getSliderValueInt:(NSInteger)category 113 | withTitle:(NSString *)title; 114 | 115 | - (void)addTextInput:(NSString *)title 116 | initialValue:(NSString *)value 117 | forCategory:(NSInteger)category; 118 | - (void)addIndexSwitch:(NSString *)title 119 | options:(NSArray *)options 120 | initialIndex:(NSInteger)index 121 | forCategory:(NSInteger)category; 122 | - (NSString *)getTextValueForCategory:(NSInteger)category 123 | withTitle:(NSString *)title; 124 | - (NSInteger)getIndexValueForCategory:(NSInteger)category 125 | withTitle:(NSString *)title; 126 | - (void)addTextInput:(NSString *)title 127 | initialValue:(NSString *)value 128 | callback:(void (^)(void))callback 129 | forCategory:(NSInteger)category; 130 | 131 | - (void)addButton:(NSString *)title 132 | icon:(NSString *)iconName 133 | callback:(void (^)(void))callback 134 | forCategory:(NSInteger)category; 135 | 136 | - (void)setContainerTitle:(NSString *)title forCategory:(NSInteger)category; 137 | - (void)showMessage:(NSString *)message 138 | duration:(NSTimeInterval)duration 139 | credits:(NSString *)credits; 140 | 141 | - (void)addStepper:(NSString *)title 142 | initialValue:(double)value 143 | minValue:(double)min 144 | maxValue:(double)max 145 | increment:(double)step 146 | forCategory:(NSInteger)category; 147 | 148 | - (void)addMultiSelect:(NSString *)title 149 | options:(NSArray *)options 150 | selectedIndices:(NSArray *)selectedIndices 151 | forCategory:(NSInteger)category; 152 | 153 | - (NSArray *)getMultiSelectValuesForCategory:(NSInteger)category 154 | withTitle:(NSString *)title; 155 | 156 | - (double)getStepperValueDouble:(NSInteger)category 157 | withTitle:(NSString *)title; 158 | - (NSInteger)getStepperIntValue:(NSInteger)category 159 | withTitle:(NSString *)title; 160 | - (float)getStepperFloatValue:(NSInteger)category 161 | withTitle:(NSString *)title; 162 | 163 | - (void)switchTo:(ModMenuLayout)layout animated:(BOOL)animated; 164 | 165 | - (void)setTheme:(ModMenuTheme)theme animated:(BOOL)animated; 166 | 167 | - (void)addQuickAction:(NSString *)title 168 | icon:(NSString *)iconName 169 | action:(void (^)(void))action; 170 | - (void)showQuickActionsMenu; 171 | 172 | 173 | - (BOOL)isOptionSelected:(NSString *)option 174 | inMultiSelect:(NSString *)title 175 | forCategory:(NSInteger)category; 176 | - (BOOL)isIndexSelected:(NSInteger)index 177 | inMultiSelect:(NSString *)title 178 | forCategory:(NSInteger)category; 179 | - (NSArray *)getSelectedOptionsForMultiSelect:(NSString *)title 180 | forCategory:(NSInteger)category; 181 | 182 | - (void)addDebugLog:(NSString *)log; 183 | - (void)clearDebugLogs; 184 | - (void)showDebugConsole; 185 | 186 | - (void)addCallback:(void (^)(id))callback forKey:(NSString *)key; 187 | - (void)resetPosition; 188 | - (void)previewCurrentLayout; 189 | - (NSString *)keyForSetting:(NSString *)title inCategory:(NSInteger)category; 190 | 191 | - (void)segmentedControlValueChanged:(UISegmentedControl *)segmentedControl; 192 | - (void)sliderValueChanged:(UISlider *)slider; 193 | 194 | - (UIView *)viewForCategory:(NSInteger)category; 195 | - (void)showQuickMessage:(NSString *)message; 196 | 197 | - (void)setCategoryIcon:(NSString *)iconName forCategory:(NSInteger)category; 198 | 199 | - (void)showPopupMessage:(NSString *)message 200 | title:(NSString *)title 201 | icon:(NSString *)iconName; 202 | 203 | 204 | - (void)showAlert:(NSString *)message 205 | title:(NSString *)title 206 | okButton:(NSString *)okTitle 207 | cancelButton:(NSString *)cancelTitle 208 | callback:(void (^)(BOOL confirmed))callback; 209 | 210 | - (void)showPatchManager:(NSString *)title icon:(NSString *)iconName; 211 | - (void)togglePatch:(NSInteger)index enabled:(BOOL)enabled; 212 | - (void)deletePatch:(NSInteger)index; 213 | 214 | 215 | - (UITextField *)createStylizedTextField:(CGRect)frame 216 | placeholder:(NSString *)placeholder; 217 | - (UIButton *)createStylizedButton:(CGRect)frame title:(NSString *)title; 218 | 219 | - (NSString *)getTextValue:(NSInteger)index withTitle:(NSString *)title; 220 | 221 | - (void)startInactivityTimer; 222 | - (void)updateButtonSizes:(CGFloat)size; 223 | 224 | - (void)updatePopupColors:(NSDictionary *)colors; 225 | - (void)handleHubLongPress:(UILongPressGestureRecognizer *)gesture; 226 | 227 | - (CGPoint)constrainPointToBounds:(CGPoint)point forView:(UIView *)view; 228 | 229 | - (void)updatePatchList:(UIScrollView *)scrollView; 230 | - (void)addPatchView:(NSDictionary *)patch 231 | toScrollView:(UIScrollView *)scrollView 232 | atOffset:(CGFloat *)yOffset; 233 | 234 | - (void)addTogglePatch:(NSString *)title 235 | initialValue:(BOOL)value 236 | offset:(NSArray *)offsets 237 | patch:(NSArray *)patches 238 | forCategory:(NSInteger)category 239 | withAsm:(BOOL)withAsm; 240 | 241 | - (void)addDefaultOptions:(BOOL)developerMode; 242 | - (void)createMessage:(NSString *)message; 243 | 244 | - (void)saveSettings; 245 | - (void)loadSettings; 246 | 247 | @end 248 | 249 | NS_ASSUME_NONNULL_END 250 | -------------------------------------------------------------------------------- /Source/UI/UI.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * File: UI.h 4 | * Project: SilentPwn 5 | * Author: Batchh 6 | * Created: 2024-12-14 7 | * 8 | * Copyright (c) 2024 Batchh. All rights reserved. 9 | * 10 | * Description: Main UI header for SilentPwn iOS modification 11 | */ 12 | 13 | #import "Icons.h" 14 | #import "Menu.h" 15 | 16 | static ModMenu *menu; 17 | -------------------------------------------------------------------------------- /Upload.sh: -------------------------------------------------------------------------------- 1 | IP="" # IP address of the phone 2 | 3 | # Check if sshpass is installed 4 | if command -v sshpass >/dev/null 2>&1; then 5 | USE_SSHPASS=true 6 | printf "\033[34m[SilentPwn]\033[0m Using sshpass for authentication...\n" 7 | printf "\033[34m[SilentPwn]\033[0m Enter password: " 8 | read -s password 9 | echo 10 | else 11 | USE_SSHPASS=false 12 | printf "\033[34m[SilentPwn]\033[0m sshpass not found, using regular ssh...\n" 13 | fi 14 | 15 | printf "\033[34m[SilentPwn]\033[0m Cleaning up packages directory...\n" 16 | rm packages/* # Clean up all packages 17 | printf "\033[34m[SilentPwn]\033[0m Building package...\n" 18 | make clean && make package 19 | 20 | printf "\033[34m[SilentPwn]\033[0m Removing existing com.* files on the device...\n" 21 | if [ "$USE_SSHPASS" = true ]; then 22 | sshpass -p "$password" ssh mobile@$IP 'rm ~/com.*' 23 | else 24 | ssh mobile@$IP 'rm ~/com.*' 25 | fi 26 | 27 | printf "\033[34m[SilentPwn]\033[0m Uploading package to device...\n" 28 | if [ "$USE_SSHPASS" = true ]; then 29 | sshpass -p "$password" scp packages/com.* mobile@$IP:~ 30 | else 31 | scp packages/com.* mobile@$IP:~ 32 | fi 33 | 34 | printf "\033[34m[SilentPwn]\033[0m Upload complete.\n" 35 | printf "\033[34m[SilentPwn]\033[0m Do you want to install the package? (y/n): " 36 | read -r install_choice 37 | if [ "$install_choice" = "y" ] || [ "$install_choice" = "Y" ]; then # install & respring 38 | if [ "$USE_SSHPASS" = false ]; then 39 | printf "\033[34m[SilentPwn]\033[0m Enter sudo password: " 40 | read -s password 41 | echo 42 | fi 43 | printf "\033[34m[SilentPwn]\033[0m Installing package...\n" 44 | if [ "$USE_SSHPASS" = true ]; then 45 | sshpass -p "$password" ssh mobile@$IP "echo '$password' | sudo -S dpkg -i com.*" 46 | else 47 | ssh mobile@$IP "echo '$password' | sudo -S dpkg -i com.*" 48 | fi 49 | printf "\033[34m[SilentPwn]\033[0m Installation complete.\n" 50 | printf "\033[34m[SilentPwn]\033[0m Respring device? (y/n): " 51 | read -r respring_choice 52 | if [ "$respring_choice" = "y" ] || [ "$respring_choice" = "Y" ]; then 53 | if [ "$USE_SSHPASS" = true ]; then 54 | sshpass -p "$password" ssh mobile@$IP "echo '$password' | sudo -S killall -9 SpringBoard" 55 | else 56 | ssh mobile@$IP "echo '$password' | sudo -S killall -9 SpringBoard" 57 | fi 58 | printf "\033[34m[SilentPwn]\033[0m Device resprung.\n" 59 | else 60 | printf "\033[34m[SilentPwn]\033[0m Device not resprung.\n" 61 | fi 62 | else 63 | printf "\033[34m[SilentPwn]\033[0m Package not installed.\n" 64 | fi -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: @@PACKAGENAME@@ 2 | Name: @@APPNAME@@ Mod Menu @@APPVERSION@@ - @@USER@@ for iOSGods.com 3 | Version: @@APPVERSION@@ 4 | Architecture: iphoneos-arm 5 | Description: Feature-rich mod menu for @@APPNAME@@. Unlock new possibilities and enhance your gameplay. Designed for iOSGods.com users. 6 | Maintainer: Batchh (https://iosgods.com/profile/10738750-batchh/) 7 | Author: @@USER@@ 8 | Section: Tweaks 9 | Depends: mobilesubstrate 10 | Homepage: iOSGods.com 11 | --------------------------------------------------------------------------------