Created
March 8, 2026 05:00
-
-
Save Randomblock1/e6b9f46fbc170dac45df2920724eb976 to your computer and use it in GitHub Desktop.
Metashape Pro patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // gcc -shared -fPIC -o patcher.so patcher.c -ldl -O2 | |
| // Run with LD_PRELOAD=/path/to/patch.so metashape | |
| #define _GNU_SOURCE | |
| #include <stdbool.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| static const char* SIG_PRO = | |
| "41 57 41 56 41 55 41 89 ?? 41 54 49 89 ?? 55 48 " | |
| "89 ?? 53 48 89 ?? 48 89 ?? 48 83 EC 68"; | |
| typedef struct { | |
| size_t length; | |
| size_t capacity; | |
| int32_t refcount; | |
| int32_t padding; | |
| char data[1]; | |
| } gnu_string_t; | |
| struct license_result_pro { | |
| int32_t status; | |
| int32_t padding; | |
| char* message_ptr; | |
| }; | |
| static struct license_result_pro* | |
| validator_proxy_pro(struct license_result_pro* res) { | |
| res->status = 0; | |
| gnu_string_t* s = calloc(1, sizeof(*s) + 7); | |
| if (s) { | |
| s->refcount = 0x7FFFFFFF; | |
| s->data[0] = '\0'; | |
| res->message_ptr = s->data; | |
| } | |
| return res; | |
| } | |
| static uintptr_t find_pattern(const char* module, const char* pattern) { | |
| uint8_t bytes[64]; | |
| bool mask[64]; | |
| size_t n = 0; | |
| for (size_t i = 0, len = strlen(pattern); i < len; i++) { | |
| if (pattern[i] == ' ') | |
| continue; | |
| if (pattern[i] == '?') { | |
| mask[n] = false; | |
| bytes[n] = 0; | |
| if (pattern[i + 1] == '?') | |
| i++; | |
| } else { | |
| mask[n] = true; | |
| bytes[n] = (uint8_t)strtol(&pattern[i], NULL, 16); | |
| i++; | |
| } | |
| n++; | |
| } | |
| uintptr_t result = 0; | |
| FILE* maps = fopen("/proc/self/maps", "r"); | |
| if (!maps) | |
| return 0; | |
| char line[512]; | |
| while (fgets(line, sizeof(line), maps)) { | |
| if (!strstr(line, "r-xp") || !strstr(line, module)) | |
| continue; | |
| uintptr_t start, end; | |
| sscanf(line, "%lx-%lx", &start, &end); | |
| for (size_t i = 0; i < (end - start) - n; i++) { | |
| bool found = true; | |
| for (size_t j = 0; j < n; j++) { | |
| if (mask[j] && ((uint8_t*)start)[i + j] != bytes[j]) { | |
| found = false; | |
| break; | |
| } | |
| } | |
| if (found) { | |
| result = start + i; | |
| break; | |
| } | |
| } | |
| if (result) | |
| break; | |
| } | |
| fclose(maps); | |
| return result; | |
| } | |
| __attribute__((constructor)) static void initialize_module(void) { | |
| char path[512]; | |
| ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1); | |
| if (len == -1) | |
| return; | |
| path[len] = '\0'; | |
| if (!strstr(path, "metashape") || strstr(path, "crashreporter")) | |
| return; | |
| printf("[*] Patcher: Context %s\n", path); | |
| size_t pg = sysconf(_SC_PAGESIZE); | |
| uintptr_t target_pro = find_pattern("metashape", SIG_PRO); | |
| if (target_pro) { | |
| printf("[+] Patcher: Detected Professional Edition at 0x%lx\n", target_pro); | |
| uintptr_t proxy_func = (uintptr_t)validator_proxy_pro; | |
| uint8_t jmp[12] = {0x48, 0xB8, [10] = 0xFF, [11] = 0xE0}; | |
| memcpy(&jmp[2], &proxy_func, 8); | |
| void* base = (void*)(target_pro & ~(pg - 1)); | |
| mprotect(base, pg * 2, PROT_READ | PROT_WRITE | PROT_EXEC); | |
| memcpy((void*)target_pro, jmp, sizeof(jmp)); | |
| mprotect(base, pg * 2, PROT_READ | PROT_EXEC); | |
| printf("[+] Patcher: Successfully redirected license check.\n"); | |
| return; | |
| } | |
| fprintf(stderr, | |
| "[!] Patcher: Failed to locate any known validator signature.\n"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment