├── Headers └── Il2Cpp │ ├── Il2Cpp.cpp │ ├── Il2Cpp.h │ └── Il2CppType.h ├── Il2CppSDK ├── .vs │ └── Il2CppSDK │ │ └── v16 │ │ └── .suo ├── Il2CppSDK.sln ├── Il2CppSDK │ ├── App.config │ ├── Il2Cpp │ │ ├── Il2Cpp.cpp │ │ ├── Il2Cpp.h │ │ └── SymbolFinder │ │ │ ├── SymbolFinder.cpp │ │ │ └── SymbolFinder.h │ ├── Il2CppSDK.csproj │ ├── Il2CppSDK.csproj.user │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── obj │ │ └── Debug │ │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ │ ├── DesignTimeResolveAssemblyReferencesInput.cache │ │ │ ├── Il2CppSDK.csproj.CopyComplete │ │ │ ├── Il2CppSDK.csproj.CoreCompileInputs.cache │ │ │ ├── Il2CppSDK.csproj.FileListAbsolute.txt │ │ │ ├── Il2CppSDK.csprojAssemblyReference.cache │ │ │ ├── Il2CppSDK.exe │ │ │ └── Il2CppSDK.pdb │ └── packages.config └── packages │ └── dnlib.3.3.2 │ ├── .signature.p7s │ ├── LICENSE.txt │ ├── dnlib.3.3.2.nupkg │ └── lib │ ├── net35 │ ├── dnlib.dll │ └── dnlib.xml │ ├── net45 │ ├── dnlib.dll │ └── dnlib.xml │ └── netstandard2.0 │ ├── dnlib.dll │ └── dnlib.xml └── README.md /Headers/Il2Cpp/Il2Cpp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 12/28/2019. 3 | // 4 | 5 | #include "Il2Cpp.h" 6 | // ========================================================================================================================================== // 7 | #define IL2CPP__TAG "Il2CppSdk" 8 | #define IL2CPP_LOGI(...) __android_log_print(ANDROID_LOG_INFO,IL2CPP__TAG,__VA_ARGS__) 9 | #define IL2CPP_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,IL2CPP__TAG,__VA_ARGS__) 10 | #define IL2CPP_LOGW(...) __android_log_print(ANDROID_LOG_WARN,IL2CPP__TAG,__VA_ARGS__) 11 | #define IL2CPP_LOGE(...) __android_log_print(ANDROID_LOG_ERROR,IL2CPP__TAG,__VA_ARGS__) 12 | // ========================================================================================================================================== // 13 | map m_cacheFields; 14 | map m_cacheMethods; 15 | map m_cacheClasses; 16 | // ========================================================================================================================================== // 17 | namespace { 18 | const void *(*il2cpp_assembly_get_image)(const void *assembly); 19 | 20 | void *(*il2cpp_domain_get)(); 21 | 22 | void **(*il2cpp_domain_get_assemblies)(const void *domain, size_t *size); 23 | 24 | const char *(*il2cpp_image_get_name)(void *image); 25 | 26 | void *(*il2cpp_class_from_name)(const void *image, const char *namespaze, const char *name); 27 | 28 | void *(*il2cpp_class_get_field_from_name)(void *klass, const char *name); 29 | 30 | void *(*il2cpp_class_get_method_from_name)(void *klass, const char *name, int argsCount); 31 | 32 | size_t (*il2cpp_field_get_offset)(void *field); 33 | 34 | void (*il2cpp_field_static_get_value)(void *field, void *value); 35 | 36 | void (*il2cpp_field_static_set_value)(void *field, void *value); 37 | 38 | void *(*il2cpp_array_new)(void *elementTypeInfo, size_t length); 39 | 40 | char *(*il2cpp_type_get_name)(void *type); 41 | 42 | void* (*il2cpp_method_get_param)(void *method, uint32_t index); 43 | 44 | void* (*il2cpp_class_get_methods)(void *klass, void* *iter); 45 | 46 | const char* (*il2cpp_method_get_name)(void *method); 47 | 48 | const char *(*il2cpp_class_get_name)(void *klass); 49 | 50 | void *(*il2cpp_class_get_nested_types)(void *, void **); 51 | 52 | void *(*il2cpp_object_new)(void *); 53 | 54 | Il2CppString *(*il2cpp_string_new)(const char *); 55 | 56 | Il2CppString *(*il2cpp_string_new_utf16)(const wchar_t *, size_t len); 57 | } 58 | // ========================================================================================================================================== // 59 | vector split_string(string str, string token) { 60 | vector result; 61 | while (str.size()) { 62 | int index = str.find(token); 63 | if (index != string::npos) { 64 | result.push_back(str.substr(0, index)); 65 | str = str.substr(index + token.size()); 66 | if (str.size() == 0) 67 | result.push_back(str); 68 | } else { 69 | result.push_back(str); 70 | str = ""; 71 | } 72 | } 73 | return result; 74 | } 75 | // ========================================================================================================================================== // 76 | int not_found_export = 0; 77 | 78 | void *get_export_function(const char *lib, const char *name) 79 | { 80 | void *handle = dlopen(lib, 4); 81 | if(handle) { 82 | void *fn = dlsym(handle, name); 83 | if (fn) { 84 | return fn; 85 | } 86 | } 87 | not_found_export++; 88 | return 0; 89 | } 90 | // ========================================================================================================================================== // 91 | #define GAME_LIB_ENGINE "libil2cpp.so" 92 | uintptr_t lib_addr = 0; 93 | 94 | uintptr_t Il2CppBase(){ 95 | if(lib_addr) 96 | { 97 | return lib_addr; 98 | } 99 | 100 | char line[512]; 101 | 102 | FILE *f = fopen("/proc/self/maps", "r"); 103 | 104 | if (!f) 105 | return 0; 106 | 107 | while (fgets(line, sizeof line, f)) { 108 | uintptr_t base; 109 | char tmp[64]; 110 | sscanf(line, "%" PRIXPTR "-%*" PRIXPTR " %*s %*s %*s %*s %s", &base, tmp); 111 | if (strstr(tmp, GAME_LIB_ENGINE)) { 112 | fclose(f); 113 | lib_addr = base; 114 | return base; 115 | } 116 | } 117 | fclose(f); 118 | return 0; 119 | } 120 | // ========================================================================================================================================== // 121 | typedef unsigned short UTF16; 122 | typedef wchar_t UTF32; 123 | typedef char UTF8; 124 | 125 | int is_surrogate(UTF16 uc) { 126 | return (uc - 0xd800u) < 2048u; 127 | } 128 | 129 | int is_high_surrogate(UTF16 uc) { 130 | return (uc & 0xfffffc00) == 0xd800; 131 | } 132 | 133 | int is_low_surrogate(UTF16 uc) { 134 | return (uc & 0xfffffc00) == 0xdc00; 135 | } 136 | 137 | UTF32 surrogate_to_utf32(UTF16 high, UTF16 low) { 138 | return (high << 10) + low - 0x35fdc00; 139 | } 140 | 141 | const char* utf16_to_utf8(const UTF16* source, size_t len) { 142 | std::u16string s(source, source + len); 143 | std::wstring_convert, char16_t> convert; 144 | return convert.to_bytes(s).c_str(); 145 | } 146 | 147 | const wchar_t* utf16_to_utf32(const UTF16* source, size_t len) { 148 | UTF32* output = new UTF32[len + 1]; 149 | 150 | for (int i = 0; i < len; i++) { 151 | const UTF16 uc = source[i]; 152 | if (!is_surrogate(uc)) { 153 | output[i] = uc; 154 | } 155 | else { 156 | if (is_high_surrogate(uc) && is_low_surrogate(source[i])) 157 | output[i] = surrogate_to_utf32(uc, source[i]); 158 | else 159 | output[i] = L'?'; 160 | } 161 | } 162 | 163 | output[len] = L'\0'; 164 | return output; 165 | } 166 | // ========================================================================================================================================== // 167 | const char* Il2CppString::CString() { 168 | return utf16_to_utf8(&this->start_char, this->length); 169 | } 170 | // ========================================================================================================================================== // 171 | const wchar_t* Il2CppString::WCString() { 172 | return utf16_to_utf32(&this->start_char, this->length); 173 | } 174 | // ========================================================================================================================================== // 175 | int Il2Cpp::Attach(const char *libname) { 176 | if(!libname) return -1; 177 | 178 | il2cpp_assembly_get_image = (const void *(*)(const void *)) get_export_function(libname, "il2cpp_assembly_get_image"); 179 | 180 | il2cpp_domain_get = (void *(*)()) get_export_function(libname, "il2cpp_domain_get"); 181 | 182 | il2cpp_domain_get_assemblies = (void **(*)(const void* , size_t*)) get_export_function(libname, "il2cpp_domain_get_assemblies"); 183 | 184 | il2cpp_image_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_image_get_name"); 185 | 186 | il2cpp_class_from_name = (void* (*)(const void*, const char*, const char *)) get_export_function(libname, "il2cpp_class_from_name"); 187 | 188 | il2cpp_class_get_field_from_name = (void* (*)(void*, const char *)) get_export_function(libname, "il2cpp_class_get_field_from_name");; 189 | 190 | il2cpp_class_get_method_from_name = (void* (*)(void *, const char*, int)) get_export_function(libname, "il2cpp_class_get_method_from_name");; 191 | 192 | il2cpp_field_get_offset = (size_t (*)(void *)) get_export_function(libname, "il2cpp_field_get_offset");; 193 | 194 | il2cpp_field_static_get_value = (void (*)(void*, void *)) get_export_function(libname, "il2cpp_field_static_get_value");; 195 | 196 | il2cpp_field_static_set_value = (void (*)(void*, void *)) get_export_function(libname, "il2cpp_field_static_set_value");; 197 | 198 | il2cpp_array_new = (void *(*)(void*, size_t)) get_export_function(libname, "il2cpp_array_new");; 199 | 200 | il2cpp_type_get_name = (char *(*)(void *)) get_export_function(libname, "il2cpp_type_get_name");; 201 | 202 | il2cpp_method_get_param = (void *(*)(void *, uint32_t)) get_export_function(libname, "il2cpp_method_get_param");; 203 | 204 | il2cpp_class_get_methods = (void *(*)(void *, void **)) get_export_function(libname, "il2cpp_class_get_methods");; 205 | 206 | il2cpp_method_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_method_get_name");; 207 | 208 | il2cpp_class_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_class_get_name"); 209 | 210 | il2cpp_class_get_nested_types = (void *(*)(void *, void **)) get_export_function(libname, "il2cpp_class_get_nested_types"); 211 | 212 | il2cpp_object_new = (void *(*)(void *)) get_export_function(libname, "il2cpp_object_new"); 213 | 214 | il2cpp_string_new = (Il2CppString *(*)(const char *)) get_export_function(libname, "il2cpp_string_new"); 215 | 216 | il2cpp_string_new_utf16 = (Il2CppString *(*)(const wchar_t *, size_t)) get_export_function(libname, "il2cpp_string_new_utf16"); 217 | 218 | if(not_found_export) 219 | { 220 | return -1; 221 | } 222 | return 0; 223 | 224 | } 225 | // ========================================================================================================================================== // 226 | void *Il2Cpp::GetImage(const char *image) { 227 | size_t size; 228 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 229 | for(int i = 0; i < size; ++i) 230 | { 231 | void *img = (void *)il2cpp_assembly_get_image(assemblies[i]); 232 | 233 | const char *img_name = il2cpp_image_get_name(img); 234 | 235 | if(strcmp(img_name, image) == 0) 236 | { 237 | return img; 238 | } 239 | } 240 | return 0; 241 | } 242 | // ========================================================================================================================================== // 243 | void Il2Cpp::GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output) { 244 | void *img = GetImage(image); 245 | if(!img) { 246 | IL2CPP_LOGI("Can't find image %s!", image); 247 | return; 248 | } 249 | void *klass = GetClass(image, namespaze, clazz); 250 | if(!klass) { 251 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 252 | return; 253 | } 254 | 255 | void *field = il2cpp_class_get_field_from_name(klass, name); 256 | if(!field) { 257 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 258 | return; 259 | } 260 | 261 | il2cpp_field_static_get_value(field, output); 262 | } 263 | // ========================================================================================================================================== // 264 | void Il2Cpp::SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void* value) { 265 | void *img = GetImage(image); 266 | if(!img) { 267 | IL2CPP_LOGI("Can't find image %s!", image); 268 | return; 269 | } 270 | void *klass = GetClass(image, namespaze, clazz); 271 | if(!klass) { 272 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 273 | return; 274 | } 275 | 276 | void *field = il2cpp_class_get_field_from_name(klass, name); 277 | if(!field) { 278 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 279 | return; 280 | } 281 | 282 | il2cpp_field_static_set_value(field, value); 283 | } 284 | // ========================================================================================================================================== // 285 | void *Il2Cpp::GetClass(const char *image, const char *namespaze, const char *clazz) { 286 | string _sig = image; 287 | _sig += namespaze; 288 | _sig += clazz; 289 | 290 | if(m_cacheClasses.count(_sig) > 0) 291 | { 292 | return m_cacheClasses[_sig]; 293 | } 294 | 295 | void *img = GetImage(image); 296 | if(!img) { 297 | IL2CPP_LOGI("Can't find image %s!", image); 298 | return 0; 299 | } 300 | 301 | vector classes = split_string(clazz, "."); 302 | 303 | void *klass = il2cpp_class_from_name(img, namespaze, classes[0].c_str()); 304 | if(!klass) { 305 | IL2CPP_LOGI("Can't find class %s!", clazz); 306 | return 0; 307 | } 308 | 309 | if(classes.size() > 1) 310 | { 311 | void *iter = 0; 312 | void *nest = il2cpp_class_get_nested_types(klass, &iter); 313 | while(nest) 314 | { 315 | const char *name = il2cpp_class_get_name(nest); 316 | if(strcmp(name, classes[1].c_str()) == 0) 317 | { 318 | return nest; 319 | } 320 | 321 | nest = il2cpp_class_get_nested_types(klass, &iter); 322 | } 323 | IL2CPP_LOGI("Can't find subclass %s in class %s!", classes[1].c_str(), classes[0].c_str()); 324 | return 0; 325 | } 326 | 327 | return klass; 328 | } 329 | // ========================================================================================================================================== // 330 | void *Il2Cpp::NewClassObject(const char *image, const char *namespaze, const char *clazz) { 331 | void *img = GetImage(image); 332 | if(!img) { 333 | IL2CPP_LOGI("Can't find image %s!", image); 334 | return 0; 335 | } 336 | 337 | void *klass = GetClass(image, namespaze, clazz); 338 | if(!klass) { 339 | IL2CPP_LOGI("Can't find class %s!", clazz); 340 | return 0; 341 | } 342 | 343 | void *obj = il2cpp_object_new(klass); 344 | if(!obj) 345 | { 346 | IL2CPP_LOGI("Can't create object for %s", clazz); 347 | return 0; 348 | } 349 | 350 | return obj; 351 | } 352 | // ========================================================================================================================================== // 353 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount) { 354 | string _sig = image; 355 | _sig += namespaze; 356 | _sig += clazz; 357 | _sig += name; 358 | _sig += to_string(argsCount); 359 | 360 | if(m_cacheMethods.count(_sig) > 0) 361 | { 362 | return m_cacheMethods[_sig]; 363 | } 364 | 365 | void *img = GetImage(image); 366 | if(!img) { 367 | IL2CPP_LOGI("Can't find image %s!", image); 368 | return 0; 369 | } 370 | 371 | void *klass = GetClass(image, namespaze, clazz); 372 | if(!klass) { 373 | IL2CPP_LOGI("Can't find class %s for method %s!", clazz, name); 374 | return 0; 375 | } 376 | 377 | void **method = (void**)il2cpp_class_get_method_from_name(klass, name, argsCount); 378 | if(!method) { 379 | IL2CPP_LOGI("Can't find method %s in class %s!", name, clazz); 380 | return 0; 381 | } 382 | 383 | m_cacheMethods[_sig] = *method; 384 | 385 | return *method; 386 | } 387 | // ========================================================================================================================================== // 388 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char** args, int argsCount) { 389 | string _sig = image; 390 | _sig += namespaze; 391 | _sig += clazz; 392 | _sig += name; 393 | for (int i = 0; i < argsCount; i++) { 394 | _sig += args[i]; 395 | } 396 | _sig += to_string(argsCount); 397 | 398 | if(m_cacheMethods.count(_sig) > 0) 399 | { 400 | return m_cacheMethods[_sig]; 401 | } 402 | 403 | void *img = GetImage(image); 404 | if(!img) { 405 | IL2CPP_LOGI("Can't find image %s!", image); 406 | return 0; 407 | } 408 | 409 | void *klass = GetClass(image, namespaze, clazz); 410 | if(!klass) { 411 | IL2CPP_LOGI("Can't find class %s for method %s!", clazz, name); 412 | return 0; 413 | } 414 | 415 | void *iter = 0; 416 | 417 | int score = 0; 418 | 419 | void **method = (void**) il2cpp_class_get_methods(klass, &iter); 420 | while(method) { 421 | const char *fname = il2cpp_method_get_name(method); 422 | if(strcmp(fname, name) == 0) { 423 | for (int i = 0; i < argsCount; i++) { 424 | void *arg = il2cpp_method_get_param(method, i); 425 | if (arg) { 426 | const char *tname = il2cpp_type_get_name(arg); 427 | if (strcmp(tname, args[i]) == 0) { 428 | score++; 429 | } else { 430 | IL2CPP_LOGI("Argument at index %d didn't matched requested argument!\r\n\tRequested: %s\r\n\tActual: %s\r\nSkipping function...", i, args[i], tname); 431 | score = 0; 432 | goto skip; 433 | } 434 | } 435 | } 436 | } 437 | skip: 438 | 439 | if(score == argsCount) 440 | { 441 | IL2CPP_LOGI("Found matched function!"); 442 | 443 | auto result = *method; 444 | m_cacheMethods[_sig] = result; 445 | 446 | return result; 447 | } 448 | 449 | method = (void **) il2cpp_class_get_methods(klass, &iter); 450 | } 451 | IL2CPP_LOGI("Cannot find function %s in class %s!", name, clazz); 452 | return 0; 453 | } 454 | // ========================================================================================================================================== // 455 | uintptr_t Il2Cpp::GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name) { 456 | string _sig = image; 457 | _sig += namespaze; 458 | _sig += clazz; 459 | _sig += name; 460 | 461 | if(m_cacheFields.count(_sig) > 0) 462 | { 463 | return m_cacheFields[_sig]; 464 | } 465 | 466 | void *img = GetImage(image); 467 | if(!img) { 468 | IL2CPP_LOGI("Can't find image %s!", image); 469 | return -1; 470 | } 471 | void *klass = GetClass(image, namespaze, clazz); 472 | if(!klass) { 473 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 474 | return -1; 475 | } 476 | 477 | void *field = il2cpp_class_get_field_from_name(klass, name); 478 | if(!field) { 479 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 480 | return -1; 481 | } 482 | 483 | auto result = il2cpp_field_get_offset(field); 484 | m_cacheFields[_sig] = result; 485 | 486 | return result; 487 | } 488 | // ========================================================================================================================================== // 489 | bool Il2Cpp::IsAssembliesLoaded() { 490 | size_t size; 491 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 492 | 493 | return size != 0 && assemblies != 0; 494 | } 495 | // ========================================================================================================================================== // 496 | void* Il2Cpp::CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length) { 497 | void *img = GetImage(image); 498 | if(!img) { 499 | IL2CPP_LOGI("Can't find image %s!", image); 500 | return 0; 501 | } 502 | void *klass = GetClass(image, namespaze, clazz); 503 | if(!klass) { 504 | IL2CPP_LOGI("Can't find class %s!", clazz); 505 | return 0; 506 | } 507 | 508 | return il2cpp_array_new(klass, length); 509 | } 510 | // ========================================================================================================================================== // 511 | Il2CppString *Il2Cpp::CreateString(const char *s) 512 | { 513 | return il2cpp_string_new(s); 514 | } 515 | 516 | Il2CppString *Il2Cpp::CreateString(const wchar_t *s, size_t len) 517 | { 518 | return il2cpp_string_new_utf16(s, len); 519 | } -------------------------------------------------------------------------------- /Headers/Il2Cpp/Il2Cpp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 12/28/2019. 3 | // 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | #ifndef IL2CPP_H 20 | #define IL2CPP_H 21 | 22 | #include "Il2CppType.h" 23 | 24 | namespace Il2Cpp { 25 | int Attach(const char *libname = "libil2cpp.so"); 26 | 27 | void *GetImage(const char *image); 28 | 29 | void *GetClass(const char *image, const char *namespaze, const char *clazz); 30 | 31 | void *CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length); 32 | 33 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount = 0); 34 | 35 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char **args, int argsCount = 0); 36 | 37 | uintptr_t GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name); 38 | 39 | void GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output); 40 | 41 | void SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *value); 42 | 43 | void *NewClassObject(const char *image, const char *namespaze, const char *clazz); 44 | 45 | Il2CppString *CreateString(const char *s); 46 | 47 | Il2CppString *CreateString(const wchar_t *s, size_t len); 48 | 49 | bool IsAssembliesLoaded(); 50 | }; 51 | 52 | uintptr_t Il2CppBase(); 53 | 54 | #endif //ML_IL2CPP_H 55 | -------------------------------------------------------------------------------- /Headers/Il2Cpp/Il2CppType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 7/14/2020. 3 | // 4 | 5 | #ifndef CODM_IL2CPPTYPE_H 6 | #define CODM_IL2CPPTYPE_H 7 | 8 | struct VirtualInvokeData { 9 | uintptr_t methodPtr; 10 | void *method; 11 | }; 12 | 13 | struct Il2CppType { 14 | void *data; 15 | unsigned int bits; 16 | }; 17 | 18 | struct Il2CppClass; 19 | 20 | struct Il2CppObject { 21 | Il2CppClass *klass; 22 | void *monitor; 23 | }; 24 | 25 | struct Il2CppArrayBounds { 26 | uintptr_t length; 27 | int32_t lower_bound; 28 | }; 29 | 30 | struct Il2CppClass { 31 | void *image; 32 | void *gc_desc; 33 | const char *name; 34 | const char *namespaze; 35 | Il2CppType *byval_arg; 36 | Il2CppType *this_arg; 37 | Il2CppClass *element_class; 38 | Il2CppClass *castClass; 39 | Il2CppClass *declaringType; 40 | Il2CppClass *parent; 41 | void *generic_class; 42 | void *typeDefinition; 43 | void *interopData; 44 | void *fields; 45 | void *events; 46 | void *properties; 47 | void *methods; 48 | Il2CppClass **nestedTypes; 49 | Il2CppClass **implementedInterfaces; 50 | void *interfaceOffsets; 51 | 52 | void *static_fields; 53 | 54 | void *rgctx_data; 55 | Il2CppClass **typeHierarchy; 56 | uint32_t cctor_started; 57 | uint32_t cctor_finished; 58 | uint64_t cctor_thread; 59 | int32_t genericContainerIndex; 60 | int32_t customAttributeIndex; 61 | uint32_t instance_size; 62 | uint32_t actualSize; 63 | uint32_t element_size; 64 | int32_t native_size; 65 | uint32_t static_fields_size; 66 | uint32_t thread_static_fields_size; 67 | int32_t thread_static_fields_offset; 68 | uint32_t flags; 69 | uint32_t token; 70 | uint16_t method_count; 71 | uint16_t property_count; 72 | uint16_t field_count; 73 | uint16_t event_count; 74 | uint16_t nested_type_count; 75 | uint16_t vtable_count; 76 | uint16_t interfaces_count; 77 | uint16_t interface_offsets_count; 78 | uint8_t typeHierarchyDepth; 79 | uint8_t genericRecursionDepth; 80 | uint8_t rank; 81 | uint8_t minimumAlignment; 82 | uint8_t packingSize; 83 | uint8_t bitflags1; 84 | uint8_t bitflags2; 85 | VirtualInvokeData vtable[255]; 86 | }; 87 | 88 | template struct Il2CppArray { 89 | Il2CppClass *klass; 90 | void *monitor; 91 | void *bounds; 92 | int max_length; 93 | T m_Items[65535]; 94 | 95 | int getLength() { 96 | return max_length; 97 | } 98 | 99 | T *getPointer() { 100 | return (T*)m_Items; 101 | } 102 | }; 103 | 104 | struct Il2CppString { 105 | Il2CppClass* klass; 106 | void* monitor; 107 | int32_t length; 108 | uint16_t start_char; 109 | 110 | int getLength() { 111 | return length; 112 | } 113 | 114 | char *getChars() { 115 | return (char *)&start_char; 116 | } 117 | 118 | const char* CString(); 119 | const wchar_t* WCString(); 120 | }; 121 | 122 | template struct Il2CppList { 123 | Il2CppClass *klass; 124 | void *unk1; 125 | Il2CppArray *items; 126 | int size; 127 | int version; 128 | 129 | T* getItems() { 130 | return items->getPointer(); 131 | } 132 | 133 | int getSize() { 134 | return size; 135 | } 136 | 137 | int getVersion() { 138 | return version; 139 | } 140 | }; 141 | 142 | template struct Il2CppDictionary { 143 | Il2CppClass *klass; 144 | void *unk1; 145 | Il2CppArray *table; 146 | Il2CppArray *linkSlots; 147 | Il2CppArray *keys; 148 | Il2CppArray *values; 149 | int touchedSlots; 150 | int emptySlot; 151 | int size; 152 | 153 | K getKeys() { 154 | return keys->getPointer(); 155 | } 156 | 157 | V getValues() { 158 | return values->getPointer(); 159 | } 160 | 161 | int getNumKeys() { 162 | return keys->getLength(); 163 | } 164 | 165 | int getNumValues() { 166 | return values->getLength(); 167 | } 168 | 169 | int getSize() { 170 | return size; 171 | } 172 | }; 173 | 174 | struct Il2CppRect { 175 | float m_XMin, m_YMin, m_width, m_height; 176 | 177 | static Il2CppRect New(float x, float y, float width, float height) { 178 | Il2CppRect r = {x, y, width, height}; 179 | return r; 180 | } 181 | }; 182 | 183 | struct Il2CppColor { 184 | float r, g, b, a; 185 | 186 | static Il2CppColor Black() { 187 | Il2CppColor c = {0, 0, 0, 1}; 188 | return c; 189 | } 190 | 191 | static Il2CppColor Blue() { 192 | Il2CppColor c = {0, 0, 1, 1}; 193 | return c; 194 | } 195 | 196 | static Il2CppColor Cyan() { 197 | Il2CppColor c = {0, 1, 1, 1}; 198 | return c; 199 | } 200 | 201 | static Il2CppColor Green() { 202 | Il2CppColor c = {0, 1, 0, 1}; 203 | return c; 204 | } 205 | 206 | static Il2CppColor Orange() { 207 | Il2CppColor c = {1, 0.5f, 0, 1}; 208 | return c; 209 | } 210 | 211 | static Il2CppColor Red() { 212 | Il2CppColor c = {1, 0, 0, 1}; 213 | return c; 214 | } 215 | 216 | static Il2CppColor White() { 217 | Il2CppColor c = {1, 1, 1, 1}; 218 | return c; 219 | } 220 | 221 | static Il2CppColor Gray() { 222 | Il2CppColor c = {0.5f, 0.5f, 0.5f, 1}; 223 | return c; 224 | } 225 | 226 | static Il2CppColor Yellow() { 227 | Il2CppColor c = {1, 0.921568632f, 0.0156862754f, 1}; 228 | return c; 229 | } 230 | }; 231 | 232 | struct Il2CppVector2 { 233 | float x, y; 234 | 235 | static Il2CppVector2 Zero() { 236 | Il2CppVector2 v = {0, 0}; 237 | return v; 238 | } 239 | 240 | static Il2CppVector2 Up() { 241 | Il2CppVector2 v = {0, 1}; 242 | return v; 243 | } 244 | 245 | static Il2CppVector2 Down() { 246 | Il2CppVector2 v = {0, -1}; 247 | return v; 248 | } 249 | 250 | static Il2CppVector2 Right() { 251 | Il2CppVector2 v = {1, 0}; 252 | return v; 253 | } 254 | 255 | static Il2CppVector2 Left() { 256 | Il2CppVector2 v = {-1, 0}; 257 | return v; 258 | } 259 | 260 | static float Distance(Il2CppVector2 a, Il2CppVector2 b) { 261 | float dx = a.x - b.x; 262 | float dy = a.y - b.y; 263 | return sqrtf(dx * dx + dy * dy); 264 | } 265 | 266 | Il2CppVector2 operator+(Il2CppVector2 b) { 267 | Il2CppVector2 v = {x + b.x, y + b.y}; 268 | return v; 269 | } 270 | 271 | Il2CppVector2 operator-(Il2CppVector2 b) { 272 | Il2CppVector2 v = {x - b.x, y - b.y}; 273 | return v; 274 | } 275 | }; 276 | 277 | struct Il2CppVector3 { 278 | float x, y, z; 279 | 280 | static Il2CppVector3 Zero() { 281 | Il2CppVector3 v = {0, 0, 0}; 282 | return v; 283 | } 284 | 285 | static Il2CppVector3 Up() { 286 | Il2CppVector3 v = {0, 1, 0}; 287 | return v; 288 | } 289 | 290 | static Il2CppVector3 Down() { 291 | Il2CppVector3 v = {0, -1, 0}; 292 | return v; 293 | } 294 | 295 | static Il2CppVector3 Right() { 296 | Il2CppVector3 v = {1, 0, 0}; 297 | return v; 298 | } 299 | 300 | static Il2CppVector3 Left() { 301 | Il2CppVector3 v = {-1, 0, 0}; 302 | return v; 303 | } 304 | 305 | static Il2CppVector3 Forward() { 306 | Il2CppVector3 v = {0, 0, 1}; 307 | return v; 308 | } 309 | 310 | static Il2CppVector3 Back() { 311 | Il2CppVector3 v = {0, 0, -1}; 312 | return v; 313 | } 314 | 315 | static float Distance(Il2CppVector3 a, Il2CppVector3 b) { 316 | float dx = a.x - b.x; 317 | float dy = a.y - b.y; 318 | float dz = a.z - b.z; 319 | return sqrtf(dx * dx + dy * dy + dz * dz); 320 | } 321 | 322 | static float Magnitude(Il2CppVector3 vector) { 323 | float f = vector.x * vector.x + vector.y * vector.y + vector.z * vector.z; 324 | return sqrtf(f); 325 | } 326 | 327 | static Il2CppVector3 Normalize(Il2CppVector3 value) { 328 | float num = Il2CppVector3::Magnitude(value); 329 | Il2CppVector3 result; 330 | if (num > 1E-05f) { 331 | result = {value.x / num, value.y / num, value.z / num}; 332 | } else { 333 | result = Il2CppVector3::Zero(); 334 | } 335 | return result; 336 | } 337 | 338 | Il2CppVector3 operator+(Il2CppVector3 b) { 339 | Il2CppVector3 v = {x + b.x, y + b.y, z + b.z}; 340 | return v; 341 | } 342 | 343 | Il2CppVector3 operator-(Il2CppVector3 b) { 344 | Il2CppVector3 v = {x - b.x, y - b.y, y - b.y}; 345 | return v; 346 | } 347 | }; 348 | 349 | struct Il2CppQuaternion { 350 | float x, y, z, w; 351 | 352 | static float Dot(Il2CppQuaternion a, Il2CppQuaternion b) { 353 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 354 | } 355 | }; 356 | 357 | #endif //CODM_IL2CPPTYPE_H 358 | -------------------------------------------------------------------------------- /Il2CppSDK/.vs/Il2CppSDK/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/.vs/Il2CppSDK/v16/.suo -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppSDK", "Il2CppSDK\Il2CppSDK.csproj", "{FD21F546-6847-42CE-834D-DF54B8463474}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {FD21F546-6847-42CE-834D-DF54B8463474}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {FD21F546-6847-42CE-834D-DF54B8463474}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {FD21F546-6847-42CE-834D-DF54B8463474}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {FD21F546-6847-42CE-834D-DF54B8463474}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {03467669-1FF8-47D4-8B25-921DFFB0500F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2Cpp/Il2Cpp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 12/28/2019. 3 | // 4 | 5 | #include "../Includes.h" 6 | #include "Il2Cpp.h" 7 | #include "SymbolFinder/SymbolFinder.h" 8 | #define IL2CPP__TAG "Il2CppSdk" 9 | #define IL2CPP_LOGI(...) __android_log_print(ANDROID_LOG_INFO,IL2CPP__TAG,__VA_ARGS__) 10 | #define IL2CPP_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,IL2CPP__TAG,__VA_ARGS__) 11 | #define IL2CPP_LOGW(...) __android_log_print(ANDROID_LOG_WARN,IL2CPP__TAG,__VA_ARGS__) 12 | #define IL2CPP_LOGE(...) __android_log_print(ANDROID_LOG_ERROR,IL2CPP__TAG,__VA_ARGS__) 13 | 14 | map m_cacheFields; 15 | map m_cacheMethods; 16 | 17 | namespace { 18 | const void *(*il2cpp_assembly_get_image)(const void *assembly); 19 | 20 | void *(*il2cpp_domain_get)(); 21 | 22 | void **(*il2cpp_domain_get_assemblies)(const void *domain, size_t *size); 23 | 24 | const char *(*il2cpp_image_get_name)(void *image); 25 | 26 | void *(*il2cpp_class_from_name)(const void *image, const char *namespaze, const char *name); 27 | 28 | void *(*il2cpp_class_get_property_from_name)(void *klass, const char *name); 29 | 30 | void *(*il2cpp_class_get_field_from_name)(void *klass, const char *name); 31 | 32 | void *(*il2cpp_class_get_method_from_name)(void *klass, const char *name, int argsCount); 33 | 34 | void *(*il2cpp_property_get_get_method)(void *prop); 35 | 36 | void *(*il2cpp_property_get_set_method)(void *prop); 37 | 38 | size_t (*il2cpp_field_get_offset)(void *field); 39 | 40 | void (*il2cpp_field_static_get_value)(void *field, void *value); 41 | 42 | void (*il2cpp_field_static_set_value)(void *field, void *value); 43 | 44 | void *(*il2cpp_array_new)(void *elementTypeInfo, size_t length); 45 | 46 | int32_t (*il2cpp_string_length)(void *str); 47 | 48 | uint16_t *(*il2cpp_string_chars)(void *str); 49 | 50 | Il2CppString* (*il2cpp_string_new)(const char* str); 51 | 52 | char *(*il2cpp_type_get_name)(void *type); 53 | 54 | void* (*il2cpp_method_get_param)(void *method, uint32_t index); 55 | 56 | void* (*il2cpp_class_get_methods)(void *klass, void* *iter); 57 | 58 | const char* (*il2cpp_method_get_name)(void *method); 59 | 60 | void *(*il2cpp_class_get_interfaces)(void *klass, void **iter); 61 | 62 | const char *(*il2cpp_class_get_name)(void *klass); 63 | 64 | void *(*il2cpp_class_from_type)(int); 65 | 66 | int (*il2cpp_class_get_type)(void *); 67 | 68 | void *(*il2cpp_class_get_parent)(void *); 69 | 70 | void *(*il2cpp_class_get_declaring_type)(void *); 71 | 72 | void *(*il2cpp_class_get_nested_types)(void *, void **); 73 | 74 | void *(*il2cpp_object_new)(void *); 75 | } 76 | 77 | vector split_string(string str, string token) { 78 | vector result; 79 | while (str.size()) { 80 | int index = str.find(token); 81 | if (index != string::npos) { 82 | result.push_back(str.substr(0, index)); 83 | str = str.substr(index + token.size()); 84 | if (str.size() == 0) 85 | result.push_back(str); 86 | } else { 87 | result.push_back(str); 88 | str = ""; 89 | } 90 | } 91 | return result; 92 | } 93 | 94 | inline const char* GetFilename(const char* filename) 95 | { 96 | const char* basename = filename + strlen(filename); 97 | 98 | for(; *basename != '/' && *basename != '\\' && basename != filename; basename--) {} 99 | 100 | if(basename != filename) return basename + 1; 101 | else return filename; 102 | } 103 | 104 | int not_found_export = 0; 105 | 106 | void *get_export_function(const char *lib, const char *name) 107 | { 108 | void *handle = dlopen(lib, 4); 109 | if(handle) { 110 | void *fn = dlsym(handle, name); 111 | if (fn) { 112 | return fn; 113 | } 114 | } 115 | not_found_export++; 116 | return 0; 117 | } 118 | 119 | void *get_export_function(void *handle, const char *name) 120 | { 121 | void *fn = dlsym(handle, name); 122 | if (fn) { 123 | return fn; 124 | } 125 | 126 | IL2CPP_LOGI("%s: %p %s", __FUNCTION__, handle, name); 127 | 128 | not_found_export++; 129 | return 0; 130 | } 131 | 132 | uintptr_t get_lib_addr(const char *name){ 133 | char line[512]; 134 | 135 | FILE *f = fopen("/proc/self/maps", "r"); 136 | 137 | if (!f) 138 | return 0; 139 | 140 | while (fgets(line, sizeof line, f)) { 141 | uintptr_t base; 142 | char tmp[64]; 143 | sscanf(line, "%" PRIXPTR "-%*" PRIXPTR " %*s %*s %*s %*s %s", &base, tmp); 144 | if (strstr(tmp, name)) { 145 | fclose(f); 146 | return base; 147 | } 148 | } 149 | fclose(f); 150 | return 0; 151 | } 152 | 153 | int Il2Cpp::Attach(const char *libname) { 154 | if(!libname) return -1; 155 | 156 | m_gIl2cppBase = get_lib_addr(libname); 157 | while(!m_gIl2cppBase) 158 | { 159 | m_gIl2cppBase = get_lib_addr(libname); 160 | sleep(1); 161 | } 162 | 163 | il2cpp_assembly_get_image = (const void *(*)(const void *)) get_export_function(libname, "il2cpp_assembly_get_image"); 164 | 165 | il2cpp_domain_get = (void *(*)()) get_export_function(libname, "il2cpp_domain_get"); 166 | 167 | il2cpp_domain_get_assemblies = (void **(*)(const void* , size_t*)) get_export_function(libname, "il2cpp_domain_get_assemblies"); 168 | 169 | il2cpp_image_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_image_get_name"); 170 | 171 | il2cpp_class_from_name = (void* (*)(const void*, const char*, const char *)) get_export_function(libname, "il2cpp_class_from_name"); 172 | 173 | il2cpp_class_get_property_from_name = (void* (*)(void *, const char *)) get_export_function(libname, "il2cpp_class_get_property_from_name");; 174 | 175 | il2cpp_class_get_field_from_name = (void* (*)(void*, const char *)) get_export_function(libname, "il2cpp_class_get_field_from_name");; 176 | 177 | il2cpp_class_get_method_from_name = (void* (*)(void *, const char*, int)) get_export_function(libname, "il2cpp_class_get_method_from_name");; 178 | 179 | il2cpp_property_get_get_method = (void* (*)(void *)) get_export_function(libname, "il2cpp_property_get_get_method");; 180 | 181 | il2cpp_property_get_set_method = (void* (*)(void *)) get_export_function(libname, "il2cpp_property_get_set_method");; 182 | 183 | il2cpp_field_get_offset = (size_t (*)(void *)) get_export_function(libname, "il2cpp_field_get_offset");; 184 | 185 | il2cpp_field_static_get_value = (void (*)(void*, void *)) get_export_function(libname, "il2cpp_field_static_get_value");; 186 | 187 | il2cpp_field_static_set_value = (void (*)(void*, void *)) get_export_function(libname, "il2cpp_field_static_set_value");; 188 | 189 | il2cpp_array_new = (void *(*)(void*, size_t)) get_export_function(libname, "il2cpp_array_new");; 190 | 191 | il2cpp_string_chars = (uint16_t *(*)(void*)) get_export_function(libname, "il2cpp_string_chars");; 192 | 193 | il2cpp_string_length = (int32_t (*)(void*)) get_export_function(libname, "il2cpp_string_length");; 194 | 195 | il2cpp_string_new = (Il2CppString *(*)(const char *)) get_export_function(libname, "il2cpp_string_new");; 196 | 197 | il2cpp_type_get_name = (char *(*)(void *)) get_export_function(libname, "il2cpp_type_get_name");; 198 | 199 | il2cpp_method_get_param = (void *(*)(void *, uint32_t)) get_export_function(libname, "il2cpp_method_get_param");; 200 | 201 | il2cpp_class_get_methods = (void *(*)(void *, void **)) get_export_function(libname, "il2cpp_class_get_methods");; 202 | 203 | il2cpp_method_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_method_get_name");; 204 | 205 | il2cpp_class_get_interfaces = (void *(*)(void *, void **)) get_export_function(libname, "il2cpp_class_get_interfaces");; 206 | 207 | il2cpp_class_get_name = (const char *(*)(void *)) get_export_function(libname, "il2cpp_class_get_name"); 208 | 209 | il2cpp_class_from_type = (void *(*)(int)) get_export_function(libname, "il2cpp_class_from_type"); 210 | 211 | il2cpp_class_get_type = (int (*)(void *)) get_export_function(libname, "il2cpp_class_get_type"); 212 | 213 | il2cpp_class_get_parent = (void *(*)(void *)) get_export_function(libname, "il2cpp_class_get_parent"); 214 | 215 | il2cpp_class_get_declaring_type = (void *(*)(void *)) get_export_function(libname, "il2cpp_class_get_declaring_type"); 216 | 217 | il2cpp_class_get_nested_types = (void *(*)(void *, void **)) get_export_function(libname, "il2cpp_class_get_nested_types"); 218 | 219 | il2cpp_object_new = (void *(*)(void *)) get_export_function(libname, "il2cpp_object_new"); 220 | 221 | if(not_found_export) 222 | { 223 | return -1; 224 | } 225 | return 0; 226 | 227 | } 228 | 229 | 230 | void *Il2Cpp::GetImageByName(const char *image) { 231 | size_t size; 232 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 233 | for(int i = 0; i < size; ++i) 234 | { 235 | void *img = (void *)il2cpp_assembly_get_image(assemblies[i]); 236 | 237 | const char *img_name = il2cpp_image_get_name(img); 238 | 239 | if(strcmp(img_name, image) == 0) 240 | { 241 | return img; 242 | } 243 | } 244 | return 0; 245 | } 246 | 247 | void Il2Cpp::GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output) { 248 | void *img = GetImageByName(image); 249 | if(!img) { 250 | IL2CPP_LOGI("Can't find image %s!", image); 251 | return; 252 | } 253 | void *klass = GetStaticClass(image, namespaze, clazz); 254 | if(!klass) { 255 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 256 | return; 257 | } 258 | 259 | void *field = il2cpp_class_get_field_from_name(klass, name); 260 | if(!field) { 261 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 262 | return; 263 | } 264 | 265 | il2cpp_field_static_get_value(field, output); 266 | } 267 | 268 | void Il2Cpp::SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void* value) { 269 | void *img = GetImageByName(image); 270 | if(!img) { 271 | IL2CPP_LOGI("Can't find image %s!", image); 272 | return; 273 | } 274 | void *klass = GetStaticClass(image, namespaze, clazz); 275 | if(!klass) { 276 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 277 | return; 278 | } 279 | 280 | void *field = il2cpp_class_get_field_from_name(klass, name); 281 | if(!field) { 282 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 283 | return; 284 | } 285 | 286 | il2cpp_field_static_set_value(field, value); 287 | } 288 | 289 | void *Il2Cpp::GetStaticClass(const char *image, const char *namespaze, const char *clazz) { 290 | void *img = GetImageByName(image); 291 | if(!img) { 292 | IL2CPP_LOGI("Can't find image %s!", image); 293 | return 0; 294 | } 295 | 296 | vector classes = split_string(clazz, "."); 297 | 298 | void *klass = il2cpp_class_from_name(img, namespaze, classes[0].c_str()); 299 | if(!klass) { 300 | IL2CPP_LOGI("Can't find class %s!", clazz); 301 | return 0; 302 | } 303 | 304 | if(classes.size() > 1) 305 | { 306 | void *iter = 0; 307 | void *nest = il2cpp_class_get_nested_types(klass, &iter); 308 | while(nest) 309 | { 310 | const char *name = il2cpp_class_get_name(nest); 311 | if(strcmp(name, classes[1].c_str()) == 0) 312 | { 313 | return nest; 314 | } 315 | 316 | nest = il2cpp_class_get_nested_types(klass, &iter); 317 | } 318 | IL2CPP_LOGI("Can't find subclass %s in class %s!", classes[1].c_str(), classes[0].c_str()); 319 | return 0; 320 | } 321 | 322 | return klass; 323 | } 324 | 325 | void *Il2Cpp::CreateClassObject(const char *image, const char *namespaze, const char *clazz) { 326 | void *img = GetImageByName(image); 327 | if(!img) { 328 | IL2CPP_LOGI("Can't find image %s!", image); 329 | return 0; 330 | } 331 | 332 | void *klass = GetStaticClass(image, namespaze, clazz); 333 | if(!klass) { 334 | IL2CPP_LOGI("Can't find class %s!", clazz); 335 | return 0; 336 | } 337 | 338 | void *obj = il2cpp_object_new(klass); 339 | if(!obj) 340 | { 341 | IL2CPP_LOGI("Can't create object for %s", clazz); 342 | return 0; 343 | } 344 | 345 | return obj; 346 | } 347 | 348 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount) { 349 | string _sig = image; 350 | _sig += namespaze; 351 | _sig += clazz; 352 | _sig += name; 353 | _sig += to_string(argsCount); 354 | 355 | if(m_cacheMethods.count(_sig) > 0) 356 | { 357 | return m_cacheMethods[_sig]; 358 | } 359 | 360 | void *img = GetImageByName(image); 361 | if(!img) { 362 | IL2CPP_LOGI("Can't find image %s!", image); 363 | return 0; 364 | } 365 | 366 | void *klass = GetStaticClass(image, namespaze, clazz); 367 | if(!klass) { 368 | IL2CPP_LOGI("Can't find class %s for method %s!", clazz, name); 369 | return 0; 370 | } 371 | 372 | void **method = (void**)il2cpp_class_get_method_from_name(klass, name, argsCount); 373 | if(!method) { 374 | IL2CPP_LOGI("Can't find method %s in class %s!", name, clazz); 375 | return 0; 376 | } 377 | 378 | m_cacheMethods[_sig] = *method; 379 | 380 | return *method; 381 | } 382 | 383 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char** args, int argsCount) { 384 | string _sig = image; 385 | _sig += namespaze; 386 | _sig += clazz; 387 | _sig += name; 388 | for (int i = 0; i < argsCount; i++) { 389 | _sig += args[i]; 390 | } 391 | _sig += to_string(argsCount); 392 | 393 | if(m_cacheMethods.count(_sig) > 0) 394 | { 395 | return m_cacheMethods[_sig]; 396 | } 397 | 398 | void *img = GetImageByName(image); 399 | if(!img) { 400 | IL2CPP_LOGI("Can't find image %s!", image); 401 | return 0; 402 | } 403 | 404 | void *klass = GetStaticClass(image, namespaze, clazz); 405 | if(!klass) { 406 | IL2CPP_LOGI("Can't find class %s for method %s!", clazz, name); 407 | return 0; 408 | } 409 | 410 | void *iter = 0; 411 | 412 | int score = 0; 413 | 414 | void **method = (void**) il2cpp_class_get_methods(klass, &iter); 415 | while(method) { 416 | const char *fname = il2cpp_method_get_name(method); 417 | if(strcmp(fname, name) == 0) { 418 | for (int i = 0; i < argsCount; i++) { 419 | void *arg = il2cpp_method_get_param(method, i); 420 | if (arg) { 421 | const char *tname = il2cpp_type_get_name(arg); 422 | if (strcmp(tname, args[i]) == 0) { 423 | score++; 424 | } else { 425 | IL2CPP_LOGI("Argument at index %d didn't matched requested argument!\r\n\tRequested: %s\r\n\tActual: %s\r\nSkipping function...", i, args[i], tname); 426 | score = 0; 427 | goto skip; 428 | } 429 | } 430 | } 431 | } 432 | skip: 433 | 434 | if(score == argsCount) 435 | { 436 | IL2CPP_LOGI("Found matched function!"); 437 | 438 | auto result = *method; 439 | m_cacheMethods[_sig] = result; 440 | 441 | return result; 442 | } 443 | 444 | method = (void **) il2cpp_class_get_methods(klass, &iter); 445 | } 446 | IL2CPP_LOGI("Cannot find function %s in class %s!", name, clazz); 447 | return 0; 448 | } 449 | 450 | uintptr_t Il2Cpp::GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name) { 451 | string _sig = image; 452 | _sig += namespaze; 453 | _sig += clazz; 454 | _sig += name; 455 | 456 | if(m_cacheFields.count(_sig) > 0) 457 | { 458 | return m_cacheFields[_sig]; 459 | } 460 | 461 | void *img = GetImageByName(image); 462 | if(!img) { 463 | IL2CPP_LOGI("Can't find image %s!", image); 464 | return -1; 465 | } 466 | void *klass = GetStaticClass(image, namespaze, clazz); 467 | if(!klass) { 468 | IL2CPP_LOGI("Can't find class %s for field %s!", clazz, name); 469 | return -1; 470 | } 471 | 472 | void *field = il2cpp_class_get_field_from_name(klass, name); 473 | if(!field) { 474 | IL2CPP_LOGI("Can't find field %s in class %s!", name, clazz); 475 | return -1; 476 | } 477 | 478 | auto result = il2cpp_field_get_offset(field); 479 | m_cacheFields[_sig] = result; 480 | 481 | return result; 482 | } 483 | 484 | bool Il2Cpp::IsAssembliesLoaded() { 485 | size_t size; 486 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 487 | 488 | return size != 0 && assemblies != 0; 489 | } 490 | 491 | void* Il2Cpp::CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length) { 492 | void *img = GetImageByName(image); 493 | if(!img) { 494 | IL2CPP_LOGI("Can't find image %s!", image); 495 | return 0; 496 | } 497 | void *klass = GetStaticClass(image, namespaze, clazz); 498 | if(!klass) { 499 | IL2CPP_LOGI("Can't find class %s!", clazz); 500 | return 0; 501 | } 502 | 503 | return il2cpp_array_new(klass, length); 504 | } 505 | 506 | Il2CppString *Il2Cpp::CreateString(const char *str) { 507 | return il2cpp_string_new(str); 508 | } 509 | 510 | wchar_t *Il2Cpp::GetString(Il2CppString *str) { 511 | return (wchar_t *)il2cpp_string_chars(str); 512 | } 513 | 514 | int32_t Il2Cpp::GetStringLength(Il2CppString *str){ 515 | return il2cpp_string_length(str); 516 | } -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2Cpp/Il2Cpp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 12/28/2019. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | #ifndef ML_IL2CPP_H 14 | #define ML_IL2CPP_H 15 | 16 | uintptr_t m_gIl2cppBase = 0; 17 | 18 | struct VirtualInvokeData { 19 | uintptr_t methodPtr; 20 | void *method; 21 | }; 22 | 23 | struct Il2CppType { 24 | void *data; 25 | unsigned int bits; 26 | }; 27 | 28 | struct Il2CppClass; 29 | 30 | struct Il2CppObject { 31 | Il2CppClass *klass; 32 | void *monitor; 33 | }; 34 | 35 | struct Il2CppArrayBounds { 36 | uintptr_t length; 37 | int32_t lower_bound; 38 | }; 39 | 40 | struct Il2CppClass { 41 | void *image; 42 | void *gc_desc; 43 | const char *name; 44 | const char *namespaze; 45 | Il2CppType *byval_arg; 46 | Il2CppType *this_arg; 47 | Il2CppClass *element_class; 48 | Il2CppClass *castClass; 49 | Il2CppClass *declaringType; 50 | Il2CppClass *parent; 51 | void *generic_class; 52 | void *typeDefinition; 53 | void *interopData; 54 | void *fields; 55 | void *events; 56 | void *properties; 57 | void *methods; 58 | Il2CppClass **nestedTypes; 59 | Il2CppClass **implementedInterfaces; 60 | void *interfaceOffsets; 61 | 62 | void *static_fields; 63 | 64 | void *rgctx_data; 65 | Il2CppClass **typeHierarchy; 66 | uint32_t cctor_started; 67 | uint32_t cctor_finished; 68 | uint64_t cctor_thread; 69 | int32_t genericContainerIndex; 70 | int32_t customAttributeIndex; 71 | uint32_t instance_size; 72 | uint32_t actualSize; 73 | uint32_t element_size; 74 | int32_t native_size; 75 | uint32_t static_fields_size; 76 | uint32_t thread_static_fields_size; 77 | int32_t thread_static_fields_offset; 78 | uint32_t flags; 79 | uint32_t token; 80 | uint16_t method_count; 81 | uint16_t property_count; 82 | uint16_t field_count; 83 | uint16_t event_count; 84 | uint16_t nested_type_count; 85 | uint16_t vtable_count; 86 | uint16_t interfaces_count; 87 | uint16_t interface_offsets_count; 88 | uint8_t typeHierarchyDepth; 89 | uint8_t genericRecursionDepth; 90 | uint8_t rank; 91 | uint8_t minimumAlignment; 92 | uint8_t packingSize; 93 | uint8_t bitflags1; 94 | uint8_t bitflags2; 95 | VirtualInvokeData vtable[255]; 96 | }; 97 | 98 | template struct Il2CppArray { 99 | Il2CppClass *klass; 100 | void *monitor; 101 | void *bounds; 102 | int max_length; 103 | void *vector[1]; 104 | 105 | int getLength() { 106 | return max_length; 107 | } 108 | 109 | T getPointer() { 110 | return (T)vector; 111 | } 112 | }; 113 | 114 | struct Il2CppString { 115 | Il2CppClass *klass; 116 | void *monitor; 117 | int length; 118 | char chars[1]; 119 | 120 | int getLength() { 121 | return length; 122 | } 123 | 124 | char *getChars() { 125 | return chars; 126 | } 127 | }; 128 | 129 | template struct Il2CppList { 130 | void *unk0; 131 | void *unk1; 132 | Il2CppArray *items; 133 | int size; 134 | int version; 135 | 136 | T getItems() { 137 | return items->getPointer(); 138 | } 139 | 140 | int getSize() { 141 | return size; 142 | } 143 | 144 | int getVersion() { 145 | return version; 146 | } 147 | }; 148 | 149 | template struct Il2CppDictionary { 150 | void *unk0; 151 | void *unk1; 152 | Il2CppArray *table; 153 | Il2CppArray *linkSlots; 154 | Il2CppArray *keys; 155 | Il2CppArray *values; 156 | int touchedSlots; 157 | int emptySlot; 158 | int size; 159 | 160 | K getKeys() { 161 | return keys->getPointer(); 162 | } 163 | 164 | V getValues() { 165 | return values->getPointer(); 166 | } 167 | 168 | int getNumKeys() { 169 | return keys->getLength(); 170 | } 171 | 172 | int getNumValues() { 173 | return values->getLength(); 174 | } 175 | 176 | int getSize() { 177 | return size; 178 | } 179 | }; 180 | 181 | struct Il2CppRect { 182 | float m_XMin, m_YMin, m_width, m_height; 183 | 184 | static Il2CppRect New(float x, float y, float width, float height) { 185 | Il2CppRect r = {x, y, width, height}; 186 | return r; 187 | } 188 | }; 189 | 190 | struct Il2CppColor { 191 | float r, g, b, a; 192 | 193 | static Il2CppColor black() { 194 | Il2CppColor c = {0, 0, 0, 1}; 195 | return c; 196 | } 197 | 198 | static Il2CppColor blue() { 199 | Il2CppColor c = {0, 0, 1, 1}; 200 | return c; 201 | } 202 | 203 | static Il2CppColor cyan() { 204 | Il2CppColor c = {0, 1, 1, 1}; 205 | return c; 206 | } 207 | 208 | static Il2CppColor green() { 209 | Il2CppColor c = {0, 1, 0, 1}; 210 | return c; 211 | } 212 | 213 | static Il2CppColor orange() { 214 | Il2CppColor c = {1, 0.5f, 0, 1}; 215 | return c; 216 | } 217 | 218 | static Il2CppColor red() { 219 | Il2CppColor c = {1, 0, 0, 1}; 220 | return c; 221 | } 222 | 223 | static Il2CppColor white() { 224 | Il2CppColor c = {1, 1, 1, 1}; 225 | return c; 226 | } 227 | 228 | static Il2CppColor gray() { 229 | Il2CppColor c = {0.5f, 0.5f, 0.5f, 1}; 230 | return c; 231 | } 232 | 233 | static Il2CppColor yellow() { 234 | Il2CppColor c = {1, 0.921568632f, 0.0156862754f, 1}; 235 | return c; 236 | } 237 | }; 238 | 239 | struct Il2CppVector2 { 240 | float x, y; 241 | 242 | static Il2CppVector2 zero() { 243 | Il2CppVector2 v = {0, 0}; 244 | return v; 245 | } 246 | 247 | static Il2CppVector2 up() { 248 | Il2CppVector2 v = {0, 1}; 249 | return v; 250 | } 251 | 252 | static Il2CppVector2 down() { 253 | Il2CppVector2 v = {0, -1}; 254 | return v; 255 | } 256 | 257 | static Il2CppVector2 right() { 258 | Il2CppVector2 v = {1, 0}; 259 | return v; 260 | } 261 | 262 | static Il2CppVector2 left() { 263 | Il2CppVector2 v = {-1, 0}; 264 | return v; 265 | } 266 | 267 | static float Distance(Il2CppVector2 a, Il2CppVector2 b) { 268 | float dx = a.x - b.x; 269 | float dy = a.y - b.y; 270 | return sqrtf(dx * dx + dy * dy); 271 | } 272 | 273 | Il2CppVector2 operator+(Il2CppVector2 b) { 274 | Il2CppVector2 v = {x + b.x, y + b.y}; 275 | return v; 276 | } 277 | 278 | Il2CppVector2 operator-(Il2CppVector2 b) { 279 | Il2CppVector2 v = {x - b.x, y - b.y}; 280 | return v; 281 | } 282 | }; 283 | 284 | struct Il2CppVector3 { 285 | float x, y, z; 286 | 287 | static Il2CppVector3 zero() { 288 | Il2CppVector3 v = {0, 0, 0}; 289 | return v; 290 | } 291 | 292 | static Il2CppVector3 up() { 293 | Il2CppVector3 v = {0, 1, 0}; 294 | return v; 295 | } 296 | 297 | static Il2CppVector3 down() { 298 | Il2CppVector3 v = {0, -1, 0}; 299 | return v; 300 | } 301 | 302 | static Il2CppVector3 right() { 303 | Il2CppVector3 v = {1, 0, 0}; 304 | return v; 305 | } 306 | 307 | static Il2CppVector3 left() { 308 | Il2CppVector3 v = {-1, 0, 0}; 309 | return v; 310 | } 311 | 312 | static Il2CppVector3 forward() { 313 | Il2CppVector3 v = {0, 0, 1}; 314 | return v; 315 | } 316 | 317 | static Il2CppVector3 back() { 318 | Il2CppVector3 v = {0, 0, -1}; 319 | return v; 320 | } 321 | 322 | static float Distance(Il2CppVector3 a, Il2CppVector3 b) { 323 | float dx = a.x - b.x; 324 | float dy = a.y - b.y; 325 | float dz = a.z - b.z; 326 | return sqrtf(dx * dx + dy * dy + dz * dz); 327 | } 328 | 329 | static float Magnitude(Il2CppVector3 vector) { 330 | float f = vector.x * vector.x + vector.y * vector.y + vector.z * vector.z; 331 | return sqrtf(f); 332 | } 333 | 334 | static Il2CppVector3 Normalize(Il2CppVector3 value) { 335 | float num = Il2CppVector3::Magnitude(value); 336 | Il2CppVector3 result; 337 | if (num > 1E-05f) { 338 | result = {value.x / num, value.y / num, value.z / num}; 339 | } else { 340 | result = Il2CppVector3::zero(); 341 | } 342 | return result; 343 | } 344 | 345 | Il2CppVector3 operator+(Il2CppVector3 b) { 346 | Il2CppVector3 v = {x + b.x, y + b.y, z + b.z}; 347 | return v; 348 | } 349 | 350 | Il2CppVector3 operator-(Il2CppVector3 b) { 351 | Il2CppVector3 v = {x - b.x, y - b.y, y - b.y}; 352 | return v; 353 | } 354 | }; 355 | 356 | struct Il2CppQuaternion { 357 | float x, y, z, w; 358 | 359 | static float Dot(Il2CppQuaternion a, Il2CppQuaternion b) { 360 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 361 | } 362 | }; 363 | 364 | 365 | namespace Il2Cpp { 366 | int Attach(const char *libname = "libil2cpp.so"); 367 | 368 | int Attach(void *handle); 369 | 370 | void *GetImageByName(const char *image); 371 | 372 | void *GetStaticClass(const char *image, const char *namespaze, const char *clazz); 373 | 374 | void *CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length); 375 | 376 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount = 0); 377 | 378 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char **args, int argsCount = 0); 379 | 380 | uintptr_t GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name); 381 | 382 | void GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output); 383 | 384 | void SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *value); 385 | 386 | void *CreateClassObject(const char *image, const char *namespaze, const char *clazz); 387 | 388 | bool IsAssembliesLoaded(); 389 | 390 | Il2CppString *CreateString(const char *str); 391 | 392 | int32_t GetStringLength(Il2CppString *str); 393 | 394 | wchar_t *GetString(Il2CppString *str); 395 | }; 396 | 397 | #endif //ML_IL2CPP_H 398 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2Cpp/SymbolFinder/SymbolFinder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../../Includes.h" 8 | #include "SymbolFinder.h" 9 | 10 | #define LOG_TAG "SymbolFinder" 11 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 12 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) 13 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) 14 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 15 | 16 | /* memory map for libraries */ 17 | #define MAX_NAME_LEN 256 18 | #define MEMORY_ONLY "[memory]" 19 | struct mm { 20 | char name[MAX_NAME_LEN]; 21 | uintptr_t start, end; 22 | }; 23 | 24 | typedef struct symtab *symtab_t; 25 | struct symlist { 26 | Elf32_Sym *sym; /* symbols */ 27 | char *str; /* symbol strings */ 28 | unsigned num; /* number of symbols */ 29 | }; 30 | struct symtab { 31 | struct symlist *st; /* "static" symbols */ 32 | struct symlist *dyn; /* dynamic symbols */ 33 | }; 34 | 35 | static void *xmalloc(size_t size) { 36 | void *p; 37 | p = malloc(size); 38 | if (!p) { 39 | printf("Out of memory\n"); 40 | exit(1); 41 | } 42 | return p; 43 | } 44 | 45 | static int my_pread(int fd, void *buf, size_t count, off_t offset) { 46 | lseek(fd, offset, SEEK_SET); 47 | return read(fd, buf, count); 48 | } 49 | 50 | static struct symlist *get_syms(int fd, Elf32_Shdr *symh, Elf32_Shdr *strh) { 51 | struct symlist *sl, *ret; 52 | int rv; 53 | 54 | ret = NULL; 55 | sl = (struct symlist *)xmalloc(sizeof(struct symlist)); 56 | sl->str = NULL; 57 | sl->sym = NULL; 58 | 59 | /* sanity */ 60 | if (symh->sh_size % sizeof(Elf32_Sym)) { 61 | //printf("elf_error\n"); 62 | goto out; 63 | } 64 | 65 | /* symbol table */ 66 | sl->num = symh->sh_size / sizeof(Elf32_Sym); 67 | sl->sym = (Elf32_Sym *)xmalloc(symh->sh_size); 68 | rv = my_pread(fd, sl->sym, symh->sh_size, symh->sh_offset); 69 | if (0 > rv) { 70 | //perror("read"); 71 | goto out; 72 | } 73 | if (rv != symh->sh_size) { 74 | //printf("elf error\n"); 75 | goto out; 76 | } 77 | 78 | /* string table */ 79 | sl->str = (char *)xmalloc(strh->sh_size); 80 | rv = my_pread(fd, sl->str, strh->sh_size, strh->sh_offset); 81 | if (0 > rv) { 82 | //perror("read"); 83 | goto out; 84 | } 85 | if (rv != strh->sh_size) { 86 | //printf("elf error"); 87 | goto out; 88 | } 89 | 90 | ret = sl; 91 | out: 92 | return ret; 93 | } 94 | 95 | static int do_load(int fd, symtab_t symtab) { 96 | int rv; 97 | size_t size; 98 | Elf32_Ehdr ehdr; 99 | Elf32_Shdr *shdr = NULL, *p; 100 | Elf32_Shdr *dynsymh, *dynstrh; 101 | Elf32_Shdr *symh, *strh; 102 | char *shstrtab = NULL; 103 | int i; 104 | int ret = -1; 105 | 106 | /* elf header */ 107 | rv = read(fd, &ehdr, sizeof(ehdr)); 108 | if (0 > rv) { 109 | LOGD("read\n"); 110 | goto out; 111 | } 112 | if (rv != sizeof(ehdr)) { 113 | LOGD("elf error 1\n"); 114 | goto out; 115 | } 116 | if (strncmp((const char *)ELFMAG, (const char *)ehdr.e_ident, SELFMAG)) { /* sanity */ 117 | LOGD("not an elf\n"); 118 | goto out; 119 | } 120 | if (sizeof(Elf32_Shdr) != ehdr.e_shentsize) { /* sanity */ 121 | LOGD("elf error 2\n"); 122 | goto out; 123 | } 124 | 125 | /* section header table */ 126 | size = ehdr.e_shentsize * ehdr.e_shnum; 127 | shdr = (Elf32_Shdr *)xmalloc(size); 128 | rv = my_pread(fd, shdr, size, ehdr.e_shoff); 129 | if (0 > rv) { 130 | LOGD("read\n"); 131 | goto out; 132 | } 133 | if (rv != size) { 134 | LOGD("elf error 3 %d %d\n", rv, size); 135 | goto out; 136 | } 137 | 138 | /* section header string table */ 139 | size = shdr[ehdr.e_shstrndx].sh_size; 140 | shstrtab = (char *)xmalloc(size); 141 | rv = my_pread(fd, shstrtab, size, shdr[ehdr.e_shstrndx].sh_offset); 142 | if (0 > rv) { 143 | LOGD("read\n"); 144 | goto out; 145 | } 146 | if (rv != size) { 147 | LOGD("elf error 4 %d %d\n", rv, size); 148 | goto out; 149 | } 150 | 151 | /* symbol table headers */ 152 | symh = dynsymh = NULL; 153 | strh = dynstrh = NULL; 154 | for (i = 0, p = shdr; i < ehdr.e_shnum; i++, p++) 155 | if (SHT_SYMTAB == p->sh_type) { 156 | if (symh) { 157 | LOGD("too many symbol tables\n"); 158 | goto out; 159 | } 160 | symh = p; 161 | } else if (SHT_DYNSYM == p->sh_type) { 162 | if (dynsymh) { 163 | LOGD("too many symbol tables\n"); 164 | goto out; 165 | } 166 | dynsymh = p; 167 | } else if (SHT_STRTAB == p->sh_type && !strncmp(shstrtab + p->sh_name, ".strtab", 7)) { 168 | if (strh) { 169 | LOGD("too many string tables\n"); 170 | goto out; 171 | } 172 | strh = p; 173 | } else if (SHT_STRTAB == p->sh_type && !strncmp(shstrtab + p->sh_name, ".dynstr", 7)) { 174 | if (dynstrh) { 175 | LOGD("too many string tables\n"); 176 | goto out; 177 | } 178 | dynstrh = p; 179 | } 180 | /* sanity checks */ 181 | if ((!dynsymh && dynstrh) || (dynsymh && !dynstrh)) { 182 | LOGD("bad dynamic symbol table\n"); 183 | goto out; 184 | } 185 | if ((!symh && strh) || (symh && !strh)) { 186 | LOGD("bad symbol table\n"); 187 | goto out; 188 | } 189 | if (!dynsymh && !symh) { 190 | LOGD("no symbol table\n"); 191 | goto out; 192 | } 193 | 194 | /* symbol tables */ 195 | if (dynsymh) 196 | symtab->dyn = get_syms(fd, dynsymh, dynstrh); 197 | if (symh) 198 | symtab->st = get_syms(fd, symh, strh); 199 | ret = 0; 200 | out: 201 | free(shstrtab); 202 | free(shdr); 203 | return ret; 204 | } 205 | 206 | static symtab_t load_symtab(char *filename) { 207 | int fd; 208 | symtab_t symtab; 209 | 210 | symtab = (symtab_t)xmalloc(sizeof(*symtab)); 211 | memset(symtab, 0, sizeof(*symtab)); 212 | 213 | fd = open(filename, O_RDONLY); 214 | if (0 > fd) { 215 | LOGE("%s open\n", __func__); 216 | return NULL; 217 | } 218 | if (0 > do_load(fd, symtab)) { 219 | LOGE("Error ELF parsing %s\n", filename); 220 | free(symtab); 221 | symtab = NULL; 222 | } 223 | close(fd); 224 | return symtab; 225 | } 226 | 227 | static int load_memmap(pid_t pid, struct mm *mm, int *nmmp) { 228 | size_t buf_size = 0xFFFFFF; 229 | char *p_buf = (char *)malloc(buf_size); // increase this if needed for larger "maps" 230 | char name[MAX_NAME_LEN] = {0}; 231 | char *p; 232 | uintptr_t start, end; 233 | struct mm *m; 234 | int nmm = 0; 235 | int fd, rv; 236 | int i; 237 | 238 | sprintf(p_buf, "/proc/%d/maps", pid); 239 | fd = open(p_buf, O_RDONLY); 240 | if (0 > fd) { 241 | LOGE("Can't open %s for reading\n", p_buf); 242 | free(p_buf); 243 | return -1; 244 | } 245 | 246 | /* Zero to ensure data is null terminated */ 247 | memset(p_buf, 0, buf_size); 248 | 249 | p = p_buf; 250 | while (1) { 251 | rv = read(fd, p, buf_size - (p - p_buf)); 252 | if (0 > rv) { 253 | LOGE("%s read", __FUNCTION__); 254 | free(p_buf); 255 | return -1; 256 | } 257 | if (0 == rv) 258 | break; 259 | p += rv; 260 | if (p - p_buf >= buf_size) { 261 | LOGE("Too many memory mapping\n"); 262 | free(p_buf); 263 | return -1; 264 | } 265 | } 266 | close(fd); 267 | 268 | p = strtok(p_buf, "\n"); 269 | m = mm; 270 | while (p) { 271 | /* parse current map line */ 272 | rv = sscanf(p, "%08lx-%08lx %*s %*s %*s %*s %s\n", &start, &end, name); 273 | 274 | p = strtok(NULL, "\n"); 275 | 276 | if (rv == 2) { 277 | m = &mm[nmm++]; 278 | m->start = start; 279 | m->end = end; 280 | memcpy(m->name, MEMORY_ONLY, sizeof(MEMORY_ONLY)); 281 | continue; 282 | } 283 | 284 | /* search backward for other mapping with same name */ 285 | for (i = nmm - 1; i >= 0; i--) { 286 | m = &mm[i]; 287 | if (!strcmp(m->name, name)) 288 | break; 289 | } 290 | 291 | if (i >= 0) { 292 | if (start < m->start) 293 | m->start = start; 294 | if (end > m->end) 295 | m->end = end; 296 | } else { 297 | /* new entry */ 298 | m = &mm[nmm++]; 299 | m->start = start; 300 | m->end = end; 301 | memcpy(m->name, name, strlen(name)); 302 | } 303 | } 304 | 305 | *nmmp = nmm; 306 | free(p_buf); 307 | return 0; 308 | } 309 | 310 | /* Find libc in MM, storing no more than LEN-1 chars of 311 | its name in NAME and set START to its starting 312 | address. If libc cannot be found return -1 and 313 | leave NAME and START untouched. Otherwise return 0 314 | and null-terminated NAME. */ 315 | static int find_libname(const char *libn, char *name, int len, uintptr_t *start, struct mm *mm, int nmm) { 316 | int i; 317 | struct mm *m; 318 | char *p; 319 | for (i = 0, m = mm; i < nmm; i++, m++) { 320 | if(!strcmp(libn, m->name)) 321 | { 322 | break; 323 | } 324 | } 325 | if (i >= nmm) 326 | /* not found */ 327 | return -1; 328 | 329 | *start = m->start; 330 | strncpy(name, m->name, len); 331 | if (strlen(m->name) >= len) 332 | name[len - 1] = '\0'; 333 | 334 | mprotect((void *)m->start, m->end - m->start, PROT_READ | PROT_WRITE | PROT_EXEC); 335 | return 0; 336 | } 337 | 338 | static int lookup2(struct symlist *sl, unsigned char type, char *name, uintptr_t *val) { 339 | Elf32_Sym *p; 340 | int len; 341 | int i; 342 | 343 | len = strlen(name); 344 | for (i = 0, p = sl->sym; i < sl->num; i++, p++) { 345 | //LOGD("name: %s %x\n", sl->str+p->st_name, p->st_value) 346 | if (!strncmp(sl->str + p->st_name, name, len) && *(sl->str + p->st_name + len) == 0 && ELF32_ST_TYPE(p->st_info) == type) { 347 | //if (p->st_value != 0) { 348 | *val = p->st_value; 349 | return 0; 350 | //} 351 | } 352 | } 353 | return -1; 354 | } 355 | 356 | static int lookup_sym(symtab_t s, unsigned char type, char *name, uintptr_t *val) { 357 | if (s->dyn && !lookup2(s->dyn, type, name, val)) 358 | return 0; 359 | if (s->st && !lookup2(s->st, type, name, val)) 360 | return 0; 361 | return -1; 362 | } 363 | 364 | static int lookup_func_sym(symtab_t s, char *name, uintptr_t *val) { 365 | return lookup_sym(s, STT_FUNC, name, val); 366 | } 367 | 368 | void GetLibBaseAddress(const char *lib, uintptr_t *result) { 369 | struct mm mm[1000] = {0}; 370 | int nmm = 0; 371 | char libname[1024] = {0}; 372 | symtab_t s; 373 | 374 | uintptr_t addr = 0; 375 | 376 | if (load_memmap(getpid(), mm, &nmm)) { 377 | LOGD("Failed to read mmap!\n"); 378 | return; 379 | } 380 | if (find_libname(lib, libname, sizeof(libname), &addr, mm, nmm)) { 381 | LOGD("Cannot find lib %s!\n", libname); 382 | return; 383 | } 384 | if(result) 385 | { 386 | *result = addr; 387 | } 388 | } 389 | 390 | void GetSymbolAddress(const char *lib, const char *name, uintptr_t *result) { 391 | struct mm mm[0xFFFFF] = {0}; 392 | int nmm = 0; 393 | char libname[1024] = {0}; 394 | symtab_t s; 395 | 396 | uintptr_t base = 0, addr = 0; 397 | 398 | if (load_memmap(getpid(), mm, &nmm)) { 399 | LOGD("Failed to read mmap!\n"); 400 | return; 401 | } 402 | if (find_libname(lib, libname, sizeof(libname), &base, mm, nmm)) { 403 | LOGD("Cannot find lib %s!\n", lib); 404 | return; 405 | } 406 | s = load_symtab(libname); 407 | if (!s) { 408 | LOGD("Cannot read symbol table\n"); 409 | return; 410 | } 411 | if (lookup_func_sym(s, (char *)name, &addr)) { 412 | LOGD("Cannot find function %s!\n", name); 413 | return; 414 | } 415 | 416 | if(result) 417 | *result = base + addr; 418 | } -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2Cpp/SymbolFinder/SymbolFinder.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_FINDER 2 | #define SYMBOL_FINDER 3 | 4 | #include 5 | void GetSymbolAddress(const char *lib, const char *name, uintptr_t *result); 6 | void GetLibBaseAddress(const char *lib, uintptr_t *result); 7 | #endif 8 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2CppSDK.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FD21F546-6847-42CE-834D-DF54B8463474} 8 | Exe 9 | Il2CppSDK 10 | Il2CppSDK 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\dnlib.3.3.2\lib\net45\dnlib.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Il2CppSDK.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | DummyDll 5 | 6 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | using dnlib.DotNet; 8 | using dnlib.IO; 9 | using dnlib.Utils; 10 | using System.Text.RegularExpressions; 11 | namespace Il2CppSDK 12 | { 13 | class Program 14 | { 15 | static Dictionary m_DuplicateMethodTable = new Dictionary(); 16 | static string OUTPUT_DIR = "SDK"; 17 | static ModuleDefMD currentModule = null; 18 | static StreamWriter currentFile = null; 19 | 20 | static string Il2CppTypeToCppType(TypeSig type) 21 | { 22 | if (type.IsGenericInstanceType) 23 | { 24 | return FormatIl2CppGeneric(type); 25 | } 26 | 27 | string result = "uintptr_t"; 28 | 29 | if (type.FullName.Equals("System.Int8")) 30 | result = "int8_t"; 31 | 32 | if (type.FullName.Equals("System.UInt8")) 33 | result = "uint8_t"; 34 | 35 | if (type.FullName.Equals("System.Int16")) 36 | result = "int16_t"; 37 | 38 | if (type.FullName.Equals("System.UInt16")) 39 | result = "uint16_t"; 40 | 41 | if (type.FullName.Equals("System.Int32")) 42 | result = "int32_t"; 43 | 44 | if (type.FullName.Equals("System.UInt32")) 45 | result = "uint32_t"; 46 | 47 | if (type.FullName.Equals("System.Int64")) 48 | result = "int64_t"; 49 | 50 | if (type.FullName.Equals("System.UInt64")) 51 | result = "uint64_t"; 52 | 53 | if (type.FullName.Equals("System.Single")) 54 | result = "float"; 55 | 56 | if (type.FullName.Equals("System.Double")) 57 | result = "double"; 58 | 59 | if (type.FullName.Equals("System.Boolean")) 60 | result = "bool"; 61 | 62 | if (type.FullName.Equals("System.Char")) 63 | result = "char"; 64 | 65 | if (type.FullName.Equals("System.Byte")) 66 | result = "unsigned char"; 67 | 68 | if (type.FullName.Equals("System.SByte")) 69 | result = "signed char"; 70 | 71 | if (type.FullName.Equals("System.String")) 72 | result = "Il2CppString*"; 73 | 74 | if (type.FullName.Equals("UnityEngine.Vector2")) 75 | result = "Il2CppVector2"; 76 | 77 | if (type.FullName.Equals("UnityEngine.Vector3")) 78 | result = "Il2CppVector3"; 79 | 80 | if (type.FullName.Equals("UnityEngine.Quaternion")) 81 | result = "Il2CppQuaternion"; 82 | 83 | if (type.FullName.Equals("UnityEngine.Rect")) 84 | result = "Il2CppRect"; 85 | 86 | if (type.FullName.Equals("System.Void")) 87 | result = "void"; 88 | 89 | if (type.FullName.Contains("[]")) 90 | result = "Il2CppArray<" + result + ">*"; 91 | 92 | return result; 93 | } 94 | static string GetFieldOffset(FieldDef field) 95 | { 96 | foreach (var attr in field.CustomAttributes) 97 | { 98 | if (attr.AttributeType.Name.Equals("FieldOffsetAttribute")) 99 | { 100 | var Offset = attr.GetField("Offset"); 101 | if (Offset != null && Offset.Value != null) 102 | { 103 | return Offset.Value.ToString(); 104 | } 105 | } 106 | } 107 | return "0x0"; 108 | } 109 | static string GetMethodOffset(MethodDef method) 110 | { 111 | foreach (var attr in method.CustomAttributes) 112 | { 113 | if (attr.AttributeType.Name.Equals("AddressAttribute")) 114 | { 115 | var Offset = attr.GetField("Offset"); 116 | if (Offset != null && Offset.Value != null) 117 | { 118 | return Offset.Value.ToString(); 119 | } 120 | } 121 | } 122 | return "0x0"; 123 | } 124 | static string FormatIl2CppGeneric(TypeSig type) 125 | { 126 | string result = ""; 127 | if (type.GetName().StartsWith("List")) 128 | { 129 | result = "Il2CppList<"; 130 | } 131 | else 132 | if (type.GetName().StartsWith("Dictionary")) 133 | { 134 | result = "Il2CppDictionary<"; 135 | } 136 | else 137 | { 138 | return "void*"; 139 | } 140 | List args = new List(); 141 | foreach (var arg in type.ToGenericInstSig().GenericArguments) 142 | { 143 | if (arg.IsGenericInstanceType) 144 | { 145 | args.Add(FormatIl2CppGeneric(arg)); 146 | } 147 | else args.Add(Il2CppTypeToCppType(arg)); 148 | } 149 | result += string.Join(", ", args.ToArray()); 150 | result += ">*"; 151 | return result; 152 | } 153 | static string FormatToValidClassname(string className) 154 | { 155 | Regex rgx = new Regex("[^a-zA-Z0-9]"); 156 | return rgx.Replace(className, ""); 157 | } 158 | 159 | static void ParseFields(TypeDef clazz) 160 | { 161 | foreach(var rid in currentModule.Metadata.GetFieldRidList(clazz.Rid)) 162 | { 163 | var field = currentModule.ResolveField(rid); 164 | 165 | if(field == null) 166 | { 167 | continue; 168 | } 169 | 170 | var fieldName = field.Name.Replace("::", "_").Replace("<", "").Replace(">", "").Replace("k__BackingField", "").Replace(".", "_").Replace("`", "_"); 171 | 172 | if (fieldName.Equals("auto") || fieldName.Equals("register")) 173 | fieldName += "_"; 174 | 175 | var fieldType = Il2CppTypeToCppType(field.FieldType); 176 | var fieldOffset = GetFieldOffset(field); 177 | 178 | currentFile.Write(string.Format("\ttemplate ", fieldType)); 179 | currentFile.WriteLine(string.Format(" {0}{1}& {2}() {{", (field.IsStatic ? "static " : ""), "T", fieldName)); 180 | if(field.IsStatic) 181 | { 182 | currentFile.WriteLine(string.Format("\t\treturn *({0}*)((uintptr_t)StaticClass()->static_fields + {1});", "T", fieldOffset)); 183 | } 184 | else 185 | { 186 | currentFile.WriteLine(string.Format("\t\treturn *({0}*)((uintptr_t)this + {1});", "T", fieldOffset)); 187 | } 188 | currentFile.WriteLine("\t}"); 189 | } 190 | } 191 | static void ParseMethods(TypeDef clazz) 192 | { 193 | foreach (var rid in currentModule.Metadata.GetMethodRidList(clazz.Rid)) 194 | { 195 | var method = currentModule.ResolveMethod(rid); 196 | 197 | if (method == null || method.IsConstructor || method.IsStaticConstructor) 198 | { 199 | continue; 200 | } 201 | 202 | var methodName = method.Name.Replace("::", "_").Replace("<", "").Replace(">", "").Replace(".", "_").Replace("`", "_"); 203 | 204 | if (methodName.Equals("auto") || methodName.Equals("register")) 205 | methodName += "_"; 206 | 207 | var methodType = Il2CppTypeToCppType(method.ReturnType); 208 | var methodOffset = GetMethodOffset(method); 209 | 210 | string methodKey = clazz.Namespace + clazz.FullName + method.Name; 211 | if (m_DuplicateMethodTable.ContainsKey(methodKey)) 212 | { 213 | methodName += "_" + m_DuplicateMethodTable[methodKey]++; 214 | } else 215 | { 216 | m_DuplicateMethodTable.Add(methodKey, 1); 217 | } 218 | 219 | List methodParams = new List(); 220 | List paramTypes = new List(); 221 | List paramNames = new List(); 222 | 223 | foreach (var param in method.Parameters) 224 | { 225 | if (param.IsNormalMethodParameter) 226 | { 227 | var paramType = Il2CppTypeToCppType(param.Type); 228 | 229 | if (param.HasParamDef) 230 | { 231 | if (param.ParamDef.IsOut) 232 | { 233 | paramType += "*"; 234 | } 235 | } 236 | 237 | if (param.Name.Equals("auto") || param.Name.Equals("register")) 238 | param.Name += "_"; 239 | 240 | paramTypes.Add(paramType); 241 | paramNames.Add(param.Name); 242 | 243 | methodParams.Add(paramType + " " + param.Name); 244 | } 245 | } 246 | 247 | currentFile.Write(string.Format("\ttemplate ", methodType)); 248 | currentFile.WriteLine(string.Format(" {0}{1} {2}({3}) {{", (method.IsStatic ? "static " : ""), "T", methodName, string.Join(", ", methodParams))); 249 | if (!method.IsStatic) 250 | { 251 | if (methodParams.Count > 0) 252 | { 253 | currentFile.WriteLine("\t\treturn (({0} (*)({1}*, {2}))(Il2CppBase() + {3}))(this, {4});", "T", FormatToValidClassname(clazz.Name), string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames)); 254 | } else currentFile.WriteLine("\t\treturn (({0} (*)({1}*))(Il2CppBase() + {3}))(this);", "T", FormatToValidClassname(clazz.Name), string.Join(", ", paramTypes), methodOffset); 255 | } 256 | else 257 | { 258 | if (methodParams.Count > 0) 259 | { 260 | currentFile.WriteLine("\t\treturn (({0} (*)(void *, {1}))(Il2CppBase() + {2}))(0, {3});", "T", string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames)); 261 | } 262 | else 263 | { 264 | currentFile.WriteLine("\t\treturn (({0} (*)(void *))(Il2CppBase() + {2}))(0);", "T", string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames)); 265 | } 266 | } 267 | currentFile.WriteLine("\t}"); 268 | } 269 | } 270 | static void ParseClass(TypeDef clazz) 271 | { 272 | var module = clazz.Module; 273 | var namespaze = clazz.Namespace; 274 | var className = (string)clazz.Name; 275 | var classFilename = string.Concat(className.Split(Path.GetInvalidFileNameChars())); 276 | var validClassname = FormatToValidClassname(className); 277 | 278 | currentFile.WriteLine("#pragma once"); 279 | currentFile.WriteLine("#include "); 280 | 281 | bool useNamespace = namespaze.Length > 0; 282 | 283 | if (useNamespace) 284 | { 285 | currentFile.WriteLine("namespace " + namespaze + " {"); 286 | } 287 | 288 | currentFile.WriteLine(); 289 | 290 | currentFile.WriteLine("class " + validClassname); 291 | currentFile.WriteLine("{"); 292 | currentFile.WriteLine("public: "); 293 | 294 | currentFile.WriteLine(); 295 | 296 | currentFile.WriteLine("\tstatic Il2CppClass *StaticClass() {"); 297 | currentFile.WriteLine(string.Format("\t\treturn (Il2CppClass *)(Il2Cpp::GetClass(\"{0}\", \"{1}\", \"{2}\"));", module.Name, namespaze, className)); 298 | currentFile.WriteLine("\t}"); 299 | 300 | currentFile.WriteLine(); 301 | 302 | ParseFields(clazz); 303 | 304 | currentFile.WriteLine(); 305 | 306 | ParseMethods(clazz); 307 | 308 | currentFile.WriteLine(); 309 | 310 | currentFile.WriteLine("};"); 311 | currentFile.WriteLine(); 312 | currentFile.WriteLine("}"); 313 | 314 | } 315 | static void ParseClasses() 316 | { 317 | if (currentModule == null) 318 | return; 319 | 320 | foreach(var rid in currentModule.Metadata.GetTypeDefRidList()) 321 | { 322 | var type = currentModule.ResolveTypeDef(rid); 323 | 324 | if (type == null) 325 | continue; 326 | 327 | var module = type.Module; 328 | var namespaze = type.Namespace.Replace("<", "").Replace(">", ""); 329 | var className = (string)type.Name.Replace("<", "").Replace(">", ""); 330 | var classFilename = string.Concat(className.Split(Path.GetInvalidFileNameChars())); 331 | var validClassname = FormatToValidClassname(className); 332 | 333 | string outputPath = OUTPUT_DIR; 334 | outputPath += "\\" + module.Name; 335 | 336 | if (!Directory.Exists(outputPath)) 337 | Directory.CreateDirectory(outputPath); 338 | 339 | if (namespaze.Length > 0) 340 | { 341 | File.AppendAllText(outputPath + "\\" + namespaze + ".h", string.Format("#include \"Includes/{0}/{1}.h\"\r\n", namespaze, classFilename)); 342 | } 343 | else 344 | { 345 | File.AppendAllText(outputPath + "\\-.h", string.Format("#include \"Includes/{0}.h\"\r\n", classFilename)); 346 | } 347 | 348 | outputPath += "\\Includes"; 349 | 350 | if(namespaze.Length > 0) 351 | { 352 | outputPath += "\\" + namespaze; 353 | } 354 | 355 | if (!Directory.Exists(outputPath)) 356 | Directory.CreateDirectory(outputPath); 357 | 358 | outputPath += "\\" + classFilename + ".h"; 359 | 360 | currentFile = new StreamWriter(outputPath); 361 | 362 | ParseClass(type); 363 | currentFile.Close(); 364 | } 365 | } 366 | static void ParseModule(string moduleFile) 367 | { 368 | Console.WriteLine("Generating SDK for {0}...", Path.GetFileName(moduleFile)); 369 | 370 | ModuleContext modCtx = ModuleDef.CreateModuleContext(); 371 | currentModule = ModuleDefMD.Load(moduleFile, modCtx); 372 | 373 | string moduleOutput = OUTPUT_DIR + "\\" + currentModule.Name; 374 | 375 | if (!Directory.Exists(moduleOutput)) 376 | Directory.CreateDirectory(moduleOutput); 377 | 378 | ParseClasses(); 379 | } 380 | static void Main(string[] args) 381 | { 382 | if(args.Length < 1) 383 | { 384 | Console.WriteLine("Invalid Arguments!"); 385 | return; 386 | } 387 | 388 | if (Directory.Exists(OUTPUT_DIR)) 389 | Directory.Delete(OUTPUT_DIR, true); 390 | 391 | if (Directory.Exists(args[0])) 392 | { 393 | foreach(var file in Directory.GetFiles(args[0])) 394 | { 395 | ParseModule(file); 396 | } 397 | } 398 | else 399 | { 400 | ParseModule(args[0]); 401 | } 402 | } 403 | } 404 | } 405 | ; -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Il2CppSDK")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Il2CppSDK")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fd21f546-6847-42ce-834d-df54b8463474")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/Il2CppSDK/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csproj.CopyComplete: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csproj.CopyComplete -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csproj.CoreCompileInputs.cache: -------------------------------------------------------------------------------- 1 | 9f776780c895b2196a0711fe39a0c1e662d15032 2 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\bin\Debug\Il2CppSDK.exe.config 2 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\bin\Debug\Il2CppSDK.exe 3 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\bin\Debug\Il2CppSDK.pdb 4 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\bin\Debug\dnlib.dll 5 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\bin\Debug\dnlib.xml 6 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\obj\Debug\Il2CppSDK.csprojAssemblyReference.cache 7 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\obj\Debug\Il2CppSDK.csproj.CoreCompileInputs.cache 8 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\obj\Debug\Il2CppSDK.csproj.CopyComplete 9 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\obj\Debug\Il2CppSDK.exe 10 | C:\Users\aimar\source\repos\Il2CppSDK\Il2CppSDK\obj\Debug\Il2CppSDK.pdb 11 | -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csprojAssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.csprojAssemblyReference.cache -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.exe -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/Il2CppSDK/obj/Debug/Il2CppSDK.pdb -------------------------------------------------------------------------------- /Il2CppSDK/Il2CppSDK/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/.signature.p7s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/packages/dnlib.3.3.2/.signature.p7s -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012-2019 de4dot@gmail.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/dnlib.3.3.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/packages/dnlib.3.3.2/dnlib.3.3.2.nupkg -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/lib/net35/dnlib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/packages/dnlib.3.3.2/lib/net35/dnlib.dll -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/lib/net45/dnlib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/packages/dnlib.3.3.2/lib/net45/dnlib.dll -------------------------------------------------------------------------------- /Il2CppSDK/packages/dnlib.3.3.2/lib/netstandard2.0/dnlib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Octowolve/Il2CppSDKGenerator/35634c897241d2c293f31817c5d549611218d7eb/Il2CppSDK/packages/dnlib.3.3.2/lib/netstandard2.0/dnlib.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Il2CppSDKGenerator 2 | An Il2Cpp SDK generator for Android (And probably IOS) 3 | 4 | # How to use 5 | 1. Compile Il2CppSDK generator (or use release version) 6 | 2. Get your DummyDll from using [Il2CppDumper](https://github.com/Perfare/Il2CppDumper/) 7 | 3. Drag the whole folder of DummyDll to Il2CppSDK.exe 8 | 4. Wait for your SDK to be generated 9 | 5. Copy the result to your project 10 | 6. Copy precoded Il2Cpp Headers to your project (And include it to your Android.mk or CMakeList.txt) 11 | 12 | Done! 13 | 14 | # How to use the SDK 15 | You can include an namespace header to compile whole classes within a namespace or just compile a single class, for example take a look at SDK result. 16 | 17 | Please read how to Initialize Il2Cpp Functions first before using any of the SDK/Il2Cpp Functions. 18 | 19 | **Example:** 20 | ```c++ 21 | #include "SDK/Assembly-CSharp.dll/GameBase.h" 22 | #include "SDK/Assembly-CSharp.dll/GameEngine.h" 23 | 24 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Component.h" 25 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Transform.h" 26 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Screen.h" 27 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Camera.h" 28 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Physics.h" 29 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/RaycastHit.h" 30 | #include "SDK/UnityEngine.dll/Includes/UnityEngine/Object.h" 31 | 32 | using namespace UnityEngine; 33 | using namespace GameBase; 34 | using namespace GameEngine; 35 | 36 | void PrintLocation() 37 | { 38 | auto baseGame = GamePlay::get_Game(); 39 | if (baseGame) { 40 | auto localPawn = GamePlay::get_LocalPawn(); 41 | if(localPawn){ 42 | auto pawnTransform = ((Component *)localPawn)->get_transform(); 43 | LOG("Local Pawn: %f %f %f", pawnTransform->get_position().x, pawnTransform->get_position().y, pawnTransform->get_position().z); 44 | localPawn->m_Health() = 9999.9f; 45 | } 46 | } 47 | } 48 | ``` 49 | # Initiating Il2Cpp Functions 50 | Before you use any `Il2Cpp` functions, you need to call `Attach` first. 51 | 52 | ```c++ 53 | ... 54 | void WaitForAttach() 55 | { 56 | waitUntilLoaded(); // TODO: create function that loops when libil2cpp.so is not loaded yet. 57 | if(Il2Cpp::Attach() != 0) 58 | { 59 | // Something goes wrong here... 60 | exit(0); 61 | } 62 | // Attached! 63 | // You can call any Il2Cpp functions now. 64 | } 65 | ``` 66 | # Changelogs 67 | 7 July 2020: 68 | ``` 69 | - Added CreateString functions to Il2Cpp Header 70 | ``` 71 | # Credits 72 | dnlib: [dnlib](https://github.com/0xd4d/dnlib) 73 | --------------------------------------------------------------------------------