From a257a21e30b1d4c72e7d200a814c2b44c5b8fe35 Mon Sep 17 00:00:00 2001 From: dkeruza Date: Mon, 20 Nov 2023 14:13:29 -0500 Subject: [PATCH] CRC32-Patches --- src/hookcrc32/Makefile | 17 ++++ src/hookcrc32/hookcrc32.c | 95 ++++++++++++++++++ src/libkswapapi/libkswapapi.o | Bin 2372 -> 0 bytes src/lindbergh/config.c | 66 ++++++++----- src/lindbergh/config.h | 6 +- src/lindbergh/hook.c | 116 ++++++++++++++++++++-- src/lindbergh/hook.h | 9 ++ src/lindbergh/patch.c | 180 +++++++++++++++++++++------------- 8 files changed, 389 insertions(+), 100 deletions(-) create mode 100644 src/hookcrc32/Makefile create mode 100644 src/hookcrc32/hookcrc32.c delete mode 100644 src/libkswapapi/libkswapapi.o diff --git a/src/hookcrc32/Makefile b/src/hookcrc32/Makefile new file mode 100644 index 0000000..4a2e6f4 --- /dev/null +++ b/src/hookcrc32/Makefile @@ -0,0 +1,17 @@ +CC=gcc -m32 +CFLAGS = -g -O0 -fPIC -m32 -Wall -Werror -Wno-unused-variable -Wno-unused-function +LD = g++ -m32 +LDFLAGS = -Wl,-z,defs -rdynamic -static-libstdc++ -static-libgcc -lc -ldl -lGL -lglut -lX11 -lm -lpthread -shared -nostdlib + +BUILD = build + +OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) + +all: hookcrc32.so + +hookcrc32.so: $(OBJS) + $(LD) $(OBJS) $(LDFLAGS) $(CFLAGS) -o hookcrc32.so + rm -f *.o + +clean: + rm -f hookcrc32.so diff --git a/src/hookcrc32/hookcrc32.c b/src/hookcrc32/hookcrc32.c new file mode 100644 index 0000000..4181782 --- /dev/null +++ b/src/hookcrc32/hookcrc32.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +static struct { + ElfW(Addr) start, end; +} *segments; +static int n; +static int (*real_main)(int argc,char **argv); + +uint32_t __crc32(const char *s,size_t n) { + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + return ~crc; +} + +static int callback(struct dl_phdr_info *info, size_t size, void *data) { + /*n = info->dlpi_phnum; + segments = malloc(n * sizeof *segments); + for(int i = 0; i < n; ++i) { + segments[i].start = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; + segments[i].end = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr + info->dlpi_phdr[i].p_memsz; + } + char *type; + int p_type; + printf("Name: \"%s\" (%d segments)\n", info->dlpi_name, info->dlpi_phnum); + for (int j = 0; j < info->dlpi_phnum; j++) { + p_type = info->dlpi_phdr[j].p_type; + type = (p_type == PT_LOAD) ? "PT_LOAD" : + (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" : + (p_type == PT_INTERP) ? "PT_INTERP" : + (p_type == PT_NOTE) ? "PT_NOTE" : + (p_type == PT_INTERP) ? "PT_INTERP" : + (p_type == PT_PHDR) ? "PT_PHDR" : + (p_type == PT_TLS) ? "PT_TLS" : + (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" : + (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" : + (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL; + + printf(" %2d: [%14p; memsz:0x%7x; size:0x%7x] flags: 0x%x; ", j, + (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr), + info->dlpi_phdr[j].p_memsz, info->dlpi_phdr[j].p_filesz ,info->dlpi_phdr[j].p_flags); + if (type != NULL) + printf("%s\n", type); + else + printf("[other (0x%x)]\n", p_type);*/ + if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5)) + { + // printf("Aca voy a dumpear el codigo:\n"); + //FILE *file = fopen("dump.bin","w+b"); + + //fwrite((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr)+10,128,1,file); + //fclose(file); + int crc = 0; + crc = __crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128); + printf("Crc32: 0x%x\n",crc); + } + //} + return 1; +} + +__attribute__((__constructor__)) +static void setup(void) { + dl_iterate_phdr(callback, NULL); + //real_main = dlsym(RTLD_NEXT, "main"); + exit(0); +} + +__attribute__((__destructor__)) +static void teardown(void) { + free(segments); +} +/* +__attribute__((__noinline__)) +int main(int argc,char **argv) { + ElfW(Addr) addr = (ElfW(Addr))__builtin_extract_return_addr(__builtin_return_address(0)); + for(int i = 0; i < n; ++i) { + if(addr >= segments[i].start && addr < segments[i].end) { + // Do Nothing + return 0; + } + } + return real_main(argc, argv); +}*/ \ No newline at end of file diff --git a/src/libkswapapi/libkswapapi.o b/src/libkswapapi/libkswapapi.o deleted file mode 100644 index d4806865b4a39307621c0ae291c38e493b109776..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2372 zcma)6O>7%Q6rSCO9pJMYbV`|et8 zT}mkoNMVVgB*fRbfn`yVbK;bESlP!Q|2g^iy}b{AyZhJi@o|npw_d;VQTE9@n_#ob zKP%6Jju&zKpcFzpsA+~&o?srOlb>&avwF}yLN4Bz1*S3D z<%=b&c%|@s;d0^W64lG6KV2!wS;Xgrl^0Z2mBk2eJ)utc#QQL#)MqcY`d+E|rxza3Gw&AwF zv$cxTjgJDa6@@|Ak1PG)W;U!} zj&pcv$!_|I)AO99)ejDA_fR++we6K_HD`N${nfQyXZPAlZOvh-JTQYRPk^4pRoN|x z7O`rHRJ`b=YV?d8u1ArcY?hoaDUWpDQRFMI|t-6F9Qj$>3yRwTCZ|3|5+gOagPZ*19JZ~ z`}Zs~^#3ovDty%a_z?i}@!keZKI#om+b*z1MuV|Ym#(9QWXsU84sI`V^Iq41CI+nd z0=P*=gRupW4NucuV3~{tV|xQ~`nzAH`p3V5`R;q*O$<}yA+Qz$#`ZQ8>3rWJ0q@N^ zxL+pU$KV;mJ`%1&_7#zm$OYLV&iGCL&(~s~Cko`1f`k8+> z?Ytl1M<8R2-z_kFBLl|oJ1Eli-iBccI@Zg-ApKZ>Iu}IoEAmyL #include #include #include @@ -13,6 +15,7 @@ #include #include #include +#include #include "hook.h" @@ -38,19 +41,33 @@ int hooks[5] = {-1, -1, -1, -1}; FILE *fileHooks[2] = {NULL, NULL}; int fileRead[2] = {0, 0}; +uint32_t elf_crc = 0; + +cpuvendor cpu_vendor = {0}; + +static int callback(struct dl_phdr_info *info, size_t size, void *data); uint16_t basePortAddress = 0xFFFF; +/** + * Signal handler for the SIGSEGV signal, which is triggered when a process tries to access an illegal memory location. + * @param signal + * @param info + * @param ptr + */ static void handleSegfault(int signal, siginfo_t *info, void *ptr) { ucontext_t *ctx = ptr; + // Get the address of the instruction causing the segfault uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP]; + printf("Code: 0x%08x - Port: 0x%08x\n", *code, (ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF)); switch (*code) { case 0xED: { + // Get the port number from the EDX register uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; // The first port called is usually random, but everything after that @@ -60,9 +77,11 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) if (basePortAddress == 0xFFFF) basePortAddress = port; + // Adjust the port number if necessary if (port > 0x38) port = port - basePortAddress; + // Call the security board input function with the port number and data securityBoardIn(port, (uint32_t *)&(ctx->uc_mcontext.gregs[REG_EAX])); ctx->uc_mcontext.gregs[REG_EIP]++; @@ -70,15 +89,17 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) } break; - case 0xE7: // OUT IMMIDIATE + case 0xE7: // OUT IMMEDIATE { + // Increment the instruction pointer by two to skip over this instruction ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } break; - case 0xE6: // OUT IMMIDIATE + case 0xE6: // OUT IMMEDIATE { + // Increment the instruction pointer by two to skip over this instruction ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } @@ -108,9 +129,14 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) } } + void __attribute__((constructor)) hook_init() { printf("SEGA Lindbergh Loader\nRobert Dilley 2022\nNot for public consumption\n\n"); + // Get offsets of the Game's ELF and calculate CRC32. + dl_iterate_phdr(callback, NULL); + // Get CPU ID + getCPUID(); // Implement SIGSEGV handler struct sigaction act; @@ -118,9 +144,9 @@ void __attribute__((constructor)) hook_init() act.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &act, NULL); - initConfig(); + initConfig(elf_crc); - if (initPatch() != 0) + if(initPatch() != 0) exit(1); if (initEeprom() != 0) @@ -206,18 +232,30 @@ int open64(const char *pathname, int flags) return open(pathname, flags); } - - FILE *fopen(const char *restrict pathname, const char *restrict mode) { FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen"); - // printf("fopen %s\n", pathname); if (strcmp(pathname, "/root/lindbergrc") == 0) { return _fopen("lindbergrc", mode); } + if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) + { + return _fopen("logo.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.tga") == 0) + { + return _fopen("LucidaConsole_12.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.abc") == 0) + { + return _fopen("LucidaConsole_12.abc", mode); + } + if (strcmp(pathname, "/proc/cpuinfo") == 0) { fileRead[CPUINFO] = 0; @@ -242,6 +280,25 @@ FILE *fopen64(const char *pathname, const char *mode) return fileHooks[OSRELEASE]; } + if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0) + { + return _fopen64("logo_red.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) + { + return _fopen64("logo.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0) + { + return _fopen64("SEGA_KakuGothic-DB-Roman_12.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0) + { + return _fopen64("SEGA_KakuGothic-DB-Roman_12.abc", mode); + } return _fopen64(pathname, mode); } @@ -465,7 +522,7 @@ float powf(float base, float exponent) return (float)pow((double)base, (double)exponent); } -/** This might be required for some games +/* int sem_wait(sem_t *sem) { int (*original_sem_wait)(sem_t * sem) = dlsym(RTLD_NEXT, "sem_wait"); @@ -476,6 +533,10 @@ int sem_wait(sem_t *sem) /** * Hook function used by Harley Davidson to change IPs to localhost * Currently does nothing. + * @param sockfd + * @param addr + * @param addrlen + * @return */ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { @@ -491,6 +552,45 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) return _connect(sockfd, addr, addrlen); } +/** + * Function to calculate CRC32 checksum in memory. +*/ +uint32_t get_crc32(const char *s,size_t n) +{ + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + return ~crc; +} + +/** + * Callback function to get the offset and size of the execution program in memory of the ELF we hook to. +*/ +static int callback(struct dl_phdr_info *info, size_t size, void *data) +{ + if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5)) + { + elf_crc = get_crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128); + } + return 1; +} + +void getCPUID() +{ + unsigned eax; + eax = 0; + __get_cpuid(0, &eax, &cpu_vendor.ebx, &cpu_vendor.ecx, &cpu_vendor.edx); + printf("CPU Vendor: %.4s%.4s%.4s\n", (const char*)&cpu_vendor.ebx,(const char*)&cpu_vendor.edx,(const char*)&cpu_vendor.ecx); +} + /** * Stop the game changing the DISPLAY environment variable */ diff --git a/src/lindbergh/hook.h b/src/lindbergh/hook.h index e69de29..36e0d2a 100644 --- a/src/lindbergh/hook.h +++ b/src/lindbergh/hook.h @@ -0,0 +1,9 @@ +uint32_t get_crc32(const char *s,size_t n); +void getCPUID(); +typedef struct +{ + unsigned ebx; + unsigned edx; + unsigned ecx; +}cpuvendor; + diff --git a/src/lindbergh/patch.c b/src/lindbergh/patch.c index 6d5beaa..05b6478 100644 --- a/src/lindbergh/patch.c +++ b/src/lindbergh/patch.c @@ -5,6 +5,9 @@ #include "patch.h" #include "config.h" +#include "hook.h" + +extern cpuvendor cpu_vendor; static void setVariable(uint32_t address, uint32_t value) { @@ -14,7 +17,7 @@ static void setVariable(uint32_t address, uint32_t value) void *toModify = (void *)(address - (address % pagesize)); - int prot = mprotect(toModify, pagesize, PROT_WRITE); + int prot = mprotect(toModify, pagesize, PROT_EXEC | PROT_WRITE); if (prot != 0) { printf("Error: Cannot unprotect memory region to change variable (%d)\n", prot); @@ -70,75 +73,116 @@ int initPatch() switch (game) { - case RTUNED: - { - detourFunction(0x08366846, amDongleInit); - detourFunction(0x08365301, amDongleIsAvailable); - detourFunction(0x08365cf7, amDongleUpdate); - } - break; - - case SRTV: - { - detourFunction(0x084d5b40, amDongleInit); - detourFunction(0x084d45f9, amDongleIsAvailable); - detourFunction(0x084d4fef, amDongleUpdate); - } - break; - - case ABC: - { - detourFunction(0x081e3424, amDongleInit); - detourFunction(0x081e3772, amDongleIsAvailable); - detourFunction(0x081e369e, amDongleUpdate); - } - break; - case OUTRUN: - { - setVariable(0x0893a24c, 2); // amBackupDebugLevel - setVariable(0x0893a260, 2); // amCreditDebugLevel - setVariable(0x0893a4b8, 2); // amDipswDebugLevel - setVariable(0x0893a4bc, 2); // amDongleDebugLevel - setVariable(0x0893a4c0, 2); // amEepromDebugLevel - setVariable(0x0893a4c4, 2); // amHwmonitorDebugLevel - setVariable(0x0893a4c8, 2); // amJvsDebugLevel - setVariable(0x0893a4cc, 2); // amLibDebugLevel - setVariable(0x0893a4d0, 2); // amMiscDebugLevel - setVariable(0x0893a4d4, 2); // amOsinfoDebugLevel - setVariable(0x0893a4d8, 2); // amSysDataDebugLevel - setVariable(0x0893a4e0, 2); // bcLibDebugLevel - detourFunction(0x08190e80, amDongleInit); - detourFunction(0x08191201, amDongleIsAvailable); - detourFunction(0x08191125, amDongleUpdate); - } - break; + case RTUNED: + { + detourFunction(0x08366846, amDongleInit); + detourFunction(0x08365301, amDongleIsAvailable); + detourFunction(0x08365cf7, amDongleUpdate); + } + break; - case THE_HOUSE_OF_THE_DEAD_4: - { - setVariable(0x0a737c60, 2); // amBackupDebugLevel - setVariable(0x0a737c64, 2); // amChunkDataDebugLevel - setVariable(0x0a737c80, 2); // amCreditDebugLevel - setVariable(0x0a737ed8, 2); // amDipswDebugLevel - setVariable(0x0a737edc, 2); // amDiskDebugLevel - setVariable(0x0a737ee0, 2); // amDongleDebugLevel - setVariable(0x0a737ee4, 2); // amEepromDebugLevel - setVariable(0x0a737ee8, 2); // amHmDebugLevel - setVariable(0x0a737ef0, 2); // amJvsDebugLevel - setVariable(0x0a737f14, 2); // amLibDebugLevel - setVariable(0x0a737f18, 2); // amMiscDebugLevel - setVariable(0x0a737f1c, 2); // amSysDataDebugLevel - setVariable(0x0a737f20, 2); // bcLibDebugLevel - setVariable(0x0a737f24, 0x0FFFFFFF); // s_logMask - detourFunction(0x08320178, amDongleInit); - detourFunction(0x08320459, amDongleIsAvailable); - detourFunction(0x083203c0, amDongleUpdate); - } - break; + case SRTV: + { + detourFunction(0x084d5b40, amDongleInit); + detourFunction(0x084d45f9, amDongleIsAvailable); + detourFunction(0x084d4fef, amDongleUpdate); + } + break; + case ABC_2006: + { + setVariable(0x0a0a37e4, 2); // amBackupDebugLevel + setVariable(0x0a0a3800, 2); // amCreditDebugLevel + setVariable(0x0a0a3a58, 2); // amDipswDebugLevel + setVariable(0x0a0a3a5c, 2); // amDongleDebugLevel + setVariable(0x0a0a3a60, 2); // amEepromDebugLevel + setVariable(0x0a0a3a64, 2); // amHwmonitorDebugLevel + setVariable(0x0a0a3a68, 2); // amJvsDebugLevel + setVariable(0x0a0a3a6c, 2); // amLibDebugLevel + setVariable(0x0a0a3a70, 2); // amMiscDebugLevel + setVariable(0x0a0a3a74, 2); // amOsinfoDebugLevel + setVariable(0x0a0a3a78, 2); // amSysDataDebugLevel + setVariable(0x0a0a3a80, 2); // bcLibDebugLevel + detourFunction(0x081e4980, amDongleInit); + detourFunction(0x081e4cce, amDongleIsAvailable); + detourFunction(0x081e4bfa, amDongleUpdate); + } + break; + case ABC_2007: + { + setVariable(0x0a0a0d24, 2); // amBackupDebugLevel + setVariable(0x0a0a0d40, 2); // amCreditDebugLevel + setVariable(0x0a0a0f98, 2); // amDipswDebugLevel + setVariable(0x0a0a0f9c, 2); // amDongleDebugLevel + setVariable(0x0a0a0fa0, 2); // amEepromDebugLevel + setVariable(0x0a0a0fa4, 2); // amHwmonitorDebugLevel + setVariable(0x0a0a0fa8, 2); // amJvsDebugLevel + setVariable(0x0a0a0fac, 2); // amLibDebugLevel + setVariable(0x0a0a0fb0, 2); // amMiscDebugLevel + setVariable(0x0a0a0fb4, 2); // amOsinfoDebugLevel + setVariable(0x0a0a0fb8, 2); // amSysDataDebugLevel + setVariable(0x0a0a0fc0, 2); // bcLibDebugLevel + detourFunction(0x081e3424, amDongleInit); + detourFunction(0x081e3772, amDongleIsAvailable); + detourFunction(0x081e369e, amDongleUpdate); + } + break; + case OUTRUN: + { + setVariable(0x0893a24c, 2); // amBackupDebugLevel + setVariable(0x0893a260, 2); // amCreditDebugLevel + setVariable(0x0893a4b8, 2); // amDipswDebugLevel + setVariable(0x0893a4bc, 2); // amDongleDebugLevel + setVariable(0x0893a4c0, 2); // amEepromDebugLevel + setVariable(0x0893a4c4, 2); // amHwmonitorDebugLevel + setVariable(0x0893a4c8, 2); // amJvsDebugLevel + setVariable(0x0893a4cc, 2); // amLibDebugLevel + setVariable(0x0893a4d0, 2); // amMiscDebugLevel + setVariable(0x0893a4d4, 2); // amOsinfoDebugLevel + setVariable(0x0893a4d8, 2); // amSysDataDebugLevel + setVariable(0x0893a4e0, 2); // bcLibDebugLevel + detourFunction(0x08190e80, amDongleInit); + detourFunction(0x08191201, amDongleIsAvailable); + detourFunction(0x08191125, amDongleUpdate); + } + break; - default: - // Don't do any patches for random games + case THE_HOUSE_OF_THE_DEAD_4: + { + setVariable(0x0a737c60, 2); // amBackupDebugLevel + setVariable(0x0a737c64, 2); // amChunkDataDebugLevel + setVariable(0x0a737c80, 2); // amCreditDebugLevel + setVariable(0x0a737ed8, 2); // amDipswDebugLevel + setVariable(0x0a737edc, 2); // amDiskDebugLevel + setVariable(0x0a737ee0, 2); // amDongleDebugLevel + setVariable(0x0a737ee4, 2); // amEepromDebugLevel + setVariable(0x0a737ee8, 2); // amHmDebugLevel + setVariable(0x0a737ef0, 2); // amJvsDebugLevel + setVariable(0x0a737f14, 2); // amLibDebugLevel + setVariable(0x0a737f18, 2); // amMiscDebugLevel + setVariable(0x0a737f1c, 2); // amSysDataDebugLevel + setVariable(0x0a737f20, 2); // bcLibDebugLevel + setVariable(0x0a737f24, 0x0FFFFFFF); // s_logMask + detourFunction(0x08320178, amDongleInit); + detourFunction(0x08320459, amDongleIsAvailable); + detourFunction(0x083203c0, amDongleUpdate); + setVariable(0x0837d6aa, cpu_vendor.ebx); + setVariable(0x0837d6ba, cpu_vendor.edx); + setVariable(0x0837d6c5, cpu_vendor.ecx); + } + break; + case THE_HOUSE_OF_THE_DEAD_4_TEST: + { + detourFunction(0x080677a0, amDongleInit); + detourFunction(0x08067a81, amDongleIsAvailable); + detourFunction(0x080679e8, amDongleUpdate); + setVariable(0x0807217a, cpu_vendor.ebx); + setVariable(0x0807218a, cpu_vendor.edx); + setVariable(0x08072195, cpu_vendor.ecx); + } + break; + default: + // Don't do any patches for random games break; } - return 0; -} +} \ No newline at end of file