From 44cdb0552f1b3ac0faadf787814b76704247b88c Mon Sep 17 00:00:00 2001 From: geni Date: Sat, 5 Jun 2021 13:14:30 +0300 Subject: [PATCH] Update Windows patches to 0.4.29, rewrite a bunch of code Closes #13 PS: fuck msvc --- .clang-format | 11 ++++ .gitignore | 10 +-- README.adoc | 9 ++- azure-pipelines.yml | 35 ++-------- build_debug.bat | 19 ++++++ build_release.bat | 19 ++++++ patcher.vcxproj | 72 -------------------- source/build.c | 17 +++++ source/checks.c | 26 ++++++++ source/language_layer.h | 16 +++++ source/linux/checks.inc | 1 + source/linux/patches.inc | 3 + source/main.c | 104 +++++++++++++++++++++++++++++ source/options.h | 9 +++ source/patches.c | 26 ++++++++ source/patches.h | 6 ++ source/pattern.h | 16 +++++ source/strings.c | 46 +++++++++++++ source/strings.h | 15 +++++ source/win32/checks.inc | 1 + source/win32/patches.inc | 5 ++ src/checks.c | 16 ----- src/checks.h | 11 ---- src/main.c | 138 --------------------------------------- src/patches.c | 33 ---------- src/patches.h | 16 ----- 26 files changed, 350 insertions(+), 330 deletions(-) create mode 100644 build_debug.bat create mode 100644 build_release.bat delete mode 100644 patcher.vcxproj create mode 100644 source/build.c create mode 100644 source/checks.c create mode 100644 source/language_layer.h create mode 100644 source/linux/checks.inc create mode 100644 source/linux/patches.inc create mode 100644 source/main.c create mode 100644 source/options.h create mode 100644 source/patches.c create mode 100644 source/patches.h create mode 100644 source/pattern.h create mode 100644 source/strings.c create mode 100644 source/strings.h create mode 100644 source/win32/checks.inc create mode 100644 source/win32/patches.inc delete mode 100644 src/checks.c delete mode 100644 src/checks.h delete mode 100644 src/main.c delete mode 100644 src/patches.c delete mode 100644 src/patches.h diff --git a/.clang-format b/.clang-format index 6a71758..a4ae9ed 100644 --- a/.clang-format +++ b/.clang-format @@ -5,5 +5,16 @@ TabWidth: 4 UseTab: Always BinPackParameters: true AllowAllParametersOfDeclarationOnNextLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortBlocksOnASingleLine: true CommentPragmas: '.\/[\*(\/\/)]+(.+\n.+)+\*\/' ColumnLimit: 0 +StatementMacros: ["PATCH", "CHECK"] +AlignConsecutiveDeclarations: true +AlignConsecutiveAssignments: true +AlignConsecutiveMacros: true +AllowShortFunctionsOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AlignOperands: true +SpaceAfterCStyleCast: true +SortIncludes: false diff --git a/.gitignore b/.gitignore index 7e302f5..d163863 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1 @@ -.vs/* -*.exe -patcher -*.filters -*.user -*.obj -patcher.vcxproj -patcher.log -patcher.sln +build/ \ No newline at end of file diff --git a/README.adoc b/README.adoc index 1d09705..7b1847b 100644 --- a/README.adoc +++ b/README.adoc @@ -10,13 +10,12 @@ Currently has patches that allow you to: * See deleted messages * Send messages in channels with a cooldown enabled -Adding completely new features is not in the scope of this project. +Adding features that require more than changing a few bytes is not in the scope of this project. == Supported platforms -Windows is the only one I make sure always works, as it's the platform I usually use. -I will occasionally test the Linux patches, however I can't assure you that they'll always work. -macOS is "supported", as in I've tried to make it work. I don't own a Mac, nor do I have a Hackintosh VM to test on. +Windows and Linux, though the latter won't get updated as quickly. == Supported versions -0.4.28 on Windows, 0.4.27 on all other platforms, although you can go back a few commits if you want to use older versions. +Windows: `0.4.29` +Linux: `0.4.27` This doesn't use pattern matching, so I have to manually update every time a new Ripcord version is released. It's usually updated within 12 hours of a new release, but I can't guarantee anything. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0766043..3fee3ee 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,12 +15,9 @@ jobs: vmImage: ubuntu-latest steps: - - script: gcc -std=c99 -pedantic -Wextra -O3 -o patcher src/main.c src/patches.c src/checks.c + - script: gcc -std=c99 -pedantic -Wextra -O3 -DBUILD_LINUX=1 -o $BUILD_ARTIFACTSTAGINGDIRECTORY/patcher-linux-x64 src/build.c displayName: 'Build' - - bash: mv $SYSTEM_DEFAULTWORKINGDIRECTORY/patcher $BUILD_ARTIFACTSTAGINGDIRECTORY/patcher-linux-x64 - displayName: Move binary to artifact directory - - task: PublishBuildArtifacts@1 displayName: Upload binary to artifacts inputs: @@ -32,31 +29,10 @@ jobs: vmImage: windows-latest steps: - - task: MSBuild@1 - inputs: - solution: $(System.DefaultWorkingDirectory)/patcher.vcxproj - platform: x64 - configuration: Release - - - bash: mv $SYSTEM_DEFAULTWORKINGDIRECTORY/x64/Release/patcher.exe $BUILD_ARTIFACTSTAGINGDIRECTORY/patcher-windows-x64.exe - displayName: Move binary to artifact directory - - - task: PublishBuildArtifacts@1 - displayName: Upload binary to artifacts - inputs: - artifactName: patcher - pathToPublish: $(Build.ArtifactStagingDirectory) - - - job: macOS - pool: - vmImage: macos-latest - - steps: - - script: clang -std=c99 -pedantic -Wextra -O3 -o patcher src/main.c src/patches.c src/checks.c - displayName: 'Build' - - - bash: mv $SYSTEM_DEFAULTWORKINGDIRECTORY/patcher $BUILD_ARTIFACTSTAGINGDIRECTORY/patcher-macOS - displayName: Move binary to artifact directory + - script: | + call build_release.bat + move %SYSTEM_DEFAULTWORKINGDIRECTORY%\\build\\patcher.exe %BUILD_ARTIFACTSTAGINGDIRECTORY%\\patcher-windows-x64.exe + displayName: Build - task: PublishBuildArtifacts@1 displayName: Upload binary to artifacts @@ -72,7 +48,6 @@ jobs: dependsOn: - Windows - Linux - - macOS steps: - task: DownloadBuildArtifacts@0 diff --git a/build_debug.bat b/build_debug.bat new file mode 100644 index 0000000..76e2060 --- /dev/null +++ b/build_debug.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 + +set application_name=patcher +set compiler=cl.exe + +set build_options= /DBUILD_WIN32=1 /D_DEBUG /D_CRT_SECURE_NO_WARNINGS +set compile_flags= -nologo /W4 /permissive- /std:c17 /FC /TC /FS /Zi /I ../source/ +set link_flags= -opt:ref -incremental:no /Debug:full + +if not exist build mkdir build +pushd build +%compiler% %build_options% %compile_flags% ../source/build.c /link %link_flags% /out:%application_name%.exe +popd + +endlocal diff --git a/build_release.bat b/build_release.bat new file mode 100644 index 0000000..fa00d2a --- /dev/null +++ b/build_release.bat @@ -0,0 +1,19 @@ +@echo off + +setlocal + +call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 + +set application_name=patcher +set compiler=cl.exe + +set build_options= /DBUILD_WIN32=1 /D_CRT_SECURE_NO_WARNINGS +set compile_flags= -nologo /W4 /permissive- /std:c17 /FC /TC /O2 /I ../source/ +set link_flags= -opt:ref -incremental:no /Debug:none + +if not exist build mkdir build +pushd build +%compiler% %build_options% %compile_flags% ../source/build.c /link %link_flags% /out:%application_name%.exe +popd + +endlocal diff --git a/patcher.vcxproj b/patcher.vcxproj deleted file mode 100644 index 68107da..0000000 --- a/patcher.vcxproj +++ /dev/null @@ -1,72 +0,0 @@ - - - - Debug - x64 - - - Release - x64 - - - Debug - Win32 - - - Release - Win32 - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - CompileAsC - NotUsing - Disabled - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MaxSpeed - NotUsing - - - Console - true - false - - - - - Application - x64 - v142 - true - Unicode - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/build.c b/source/build.c new file mode 100644 index 0000000..5227d1f --- /dev/null +++ b/source/build.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +#include "options.h" +#include "language_layer.h" + +#include "strings.h" +#include "pattern.h" +#include "patches.h" + +#include "strings.c" +#include "patches.c" +#include "checks.c" + +#include "main.c" diff --git a/source/checks.c b/source/checks.c new file mode 100644 index 0000000..91bea6b --- /dev/null +++ b/source/checks.c @@ -0,0 +1,26 @@ +typedef Patch Check; + +#if BUILD_WIN32 +#define CHECKS_INCLUDE_PATH "win32/checks.inc" +#elif BUILD_LINUX +#define CHECKS_INCLUDE_PATH "linux/checks.inc" +#endif + +#define CHECK(check_name, check_offset, ...) \ + global const Check check_name = { \ + .name = S8LitComp(#check_name), \ + .offset = check_offset, \ + .pattern = PatternFromStringLitComp(__VA_ARGS__), \ + }; +#include CHECKS_INCLUDE_PATH +#undef CHECK + +#define CHECK(checkname, ...) &checkname, +global const Check* checks[] = { +#include CHECKS_INCLUDE_PATH +}; +#undef CHECK + +global const u32 checks_count = ArraySize(checks); + +#undef CHECKS_INCLUDE_PATH diff --git a/source/language_layer.h b/source/language_layer.h new file mode 100644 index 0000000..633f890 --- /dev/null +++ b/source/language_layer.h @@ -0,0 +1,16 @@ +#define global static +#define internal static +#define local_persist static +#define ArraySize(a) (sizeof(a) / sizeof((a)[0])) + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef i32 b32; diff --git a/source/linux/checks.inc b/source/linux/checks.inc new file mode 100644 index 0000000..adcdee2 --- /dev/null +++ b/source/linux/checks.inc @@ -0,0 +1 @@ +CHECK(version_check, 0x4C92AD, "0.4.27") diff --git a/source/linux/patches.inc b/source/linux/patches.inc new file mode 100644 index 0000000..b7850bc --- /dev/null +++ b/source/linux/patches.inc @@ -0,0 +1,3 @@ +PATCH(deleted_message_details, 0x163FA0, {0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3}) +PATCH(deleted_message_append, 0x209DE3, {0xE9, 0x83, 0x00, 0x00}) +PATCH(cooldown, 0x169CD0, {0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3}) diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..2efa1a0 --- /dev/null +++ b/source/main.c @@ -0,0 +1,104 @@ +i32 main(i32 argc, char** argv) { + // TODO(geni): Rewrite this whole thing + // TODO(geni): Memory-mapped files + + if (argc == 2) { + if (CStringCompareToS8(argv[1], S8Lit("-h"))) { + String8 base_name = S8PathToBaseName(S8FromCString(argv[0])); + printf("Usage: %.*s [-h] [-l] [original (" DEFAULT_FILENAME ") [patched (" DEFAULT_PATCH_FILENAME ") [disabled patches]]]", S8Expand(base_name)); + } else if (CStringCompareToS8(argv[1], S8Lit("-l"))) { + puts("Available patches:"); + for (u32 i = 0; i < patches_count; ++i) { + printf("Patch \"%.*s\"\n", S8Expand(patches[i]->name)); + } + } + + return 0; + } + + // NOTE(geni): User wants to disable specific patches + if (argc > 3) { + for (i32 i = 3; i < argc; ++i) { + for (u32 p = 0; p < patches_count; ++p) { + if (!patches[p]) { + continue; + } + + if (S8CompareToCString(patches[p]->name, argv[i])) { + patches[p] = NULL; + } + } + } + } + + FILE* fp = NULL; + if (argc == 1) { + fputs("No arguments passed, attempting to use " DEFAULT_FILENAME " as original binary...\n", stderr); + fp = fopen(DEFAULT_FILENAME, "rb"); + } else { + fp = fopen(argv[1], "rb"); + } + + if (!fp) { + fputs("Failed to open original binary!\n", stderr); + return 1; + } + + fseek(fp, 0, SEEK_END); + const u64 size = ftell(fp); + rewind(fp); + + u8* buf = malloc(size); + if (!buf) { + fprintf(stderr, "Failed to allocate buffer (size %zu), not enough memory?", size); + fclose(fp); + return 1; + } + fread(buf, size, sizeof(u8), fp); + fclose(fp); + + b32 failed_checks = 0; + for (u32 i = 0; i < checks_count; ++i) { + const Check* c = checks[i]; + + if (memcmp(buf + c->offset, PatternExpand(c->pattern)) != 0) { + fprintf(stderr, "Check \"%.*s\" failed!\n", S8Expand(c->name)); + failed_checks = 1; + } + } + if (failed_checks) { + return 1; + } + + for (u32 i = 0; i < patches_count; ++i) { + const Patch* p = patches[i]; + + // NOTE(geni): Patch is (hopefully) disabled + if (!p) { + continue; + } + + memcpy(buf + p->offset, PatternExpand(p->pattern)); + printf("Patch \"%.*s\" done\n", S8Expand(p->name)); + } + + if (argc < 2) { + fputs("No patched filename passed, attempting to use " DEFAULT_PATCH_FILENAME " as patched binary...\n", stderr); + fp = fopen(DEFAULT_PATCH_FILENAME, "wb"); + } else { + fp = fopen(argv[2], "wb"); + } + + if (!fp) { + fputs("Failed to create patched binary!\n", stderr); + return 1; + } + const u64 written = fwrite(buf, sizeof(buf[0]), size, fp); + if (written != size) { + fputs("Number of bytes written differs from original size\n", stderr); + return 1; + } + + fclose(fp); + free(buf); +} diff --git a/source/options.h b/source/options.h new file mode 100644 index 0000000..5f7255d --- /dev/null +++ b/source/options.h @@ -0,0 +1,9 @@ +#if BUILD_WIN32 +#define DEFAULT_FILENAME "Ripcord.exe" +#define DEFAULT_PATCH_FILENAME "RipcordPatched.exe" +#elif BUILD_LINUX +#define DEFAULT_FILENAME "Ripcord" +#define DEFAULT_PATCH_FILENAME "RipcordPatched" +#else +#error Not supported +#endif diff --git a/source/patches.c b/source/patches.c new file mode 100644 index 0000000..9eebc30 --- /dev/null +++ b/source/patches.c @@ -0,0 +1,26 @@ +#if BUILD_WIN32 +#define PATCHES_INCLUDE_PATH "win32/patches.inc" +#elif BUILD_LINUX +#define PATCHES_INCLUDE_PATH "linux/patches.inc" +#endif + +#define PATCH(patch_name, patch_offset, ...) \ + global const u8 patch_name##_pattern[] = __VA_ARGS__; \ + \ + global const Patch patch_name = { \ + .name = S8LitComp(#patch_name), \ + .offset = patch_offset, \ + .pattern = PatternComp(patch_name##_pattern), \ + }; +#include PATCHES_INCLUDE_PATH +#undef PATCH + +#define PATCH(patchname, ...) &patchname, +global const Patch* patches[] = { +#include PATCHES_INCLUDE_PATH +}; +#undef PATCH + +global const u32 patches_count = ArraySize(patches); + +#undef PATCHES_INCLUDE_PATH diff --git a/source/patches.h b/source/patches.h new file mode 100644 index 0000000..b923244 --- /dev/null +++ b/source/patches.h @@ -0,0 +1,6 @@ +typedef struct { + String8 name; + u32 offset; + + Pattern pattern; +} Patch; diff --git a/source/pattern.h b/source/pattern.h new file mode 100644 index 0000000..0e691b9 --- /dev/null +++ b/source/pattern.h @@ -0,0 +1,16 @@ +typedef struct { + const u8* pattern; + u32 size; +} Pattern; + +// NOTE(geni): What are the Comp macros for? MSVC. They're for MSVC. Try replacing PatternComp with Pattern in patches/checks.c and see for yourself. +// (disclaimer: I don't know if it's complying with the standard or just stupid, but clang handles it fine) +#define Pattern(p) (Pattern) PatternComp(p) +#define PatternComp(p) \ + { .pattern = (const u8*) (p), .size = ArraySize(p) } + +#define PatternFromStringLit(p) (Pattern) PatternFromStringLitComp(p) +#define PatternFromStringLitComp(p) \ + { .pattern = (const u8*) (p), .size = ArraySize(p) - 1 } + +#define PatternExpand(p) (p).pattern, (p).size diff --git a/source/strings.c b/source/strings.c new file mode 100644 index 0000000..098986e --- /dev/null +++ b/source/strings.c @@ -0,0 +1,46 @@ +internal String8 S8FromCString(char* str) { + return (String8){ + .s = (u8*) str, + .size = strlen(str), + }; +} + +internal b32 S8Compare(String8 a, String8 b) { + if (a.size != b.size) { + return 0; + } + + for (u32 i = 0; i < a.size; ++i) { + if (a.s[i] != b.s[i]) { + return 0; + } + } + + return 1; +} +internal b32 S8CompareToCString(String8 a, const char* b) { + return S8Compare(a, S8FromCString(b)); +} +internal b32 CStringCompareToS8(const char* a, String8 b) { + return S8Compare(S8FromCString(a), b); +} + +internal String8 S8SubstringAfterLastOccurenceOf(String8 str, char c) { + for (u8* i = str.s + str.size; i >= str.s; --i) { + if (*i == c) { + return (String8){ + .s = i + 1, + .size = i + 1 - str.s, + }; + } + } + + return str; +} +internal String8 S8PathToBaseName(String8 path) { + String8 result = S8SubstringAfterLastOccurenceOf(path, '/'); + if (result.s == path.s) { + result = S8SubstringAfterLastOccurenceOf(path, '\\'); + } + return result; +} diff --git a/source/strings.h b/source/strings.h new file mode 100644 index 0000000..b207544 --- /dev/null +++ b/source/strings.h @@ -0,0 +1,15 @@ +typedef struct { + union { + u8* s; + char* cs; + }; + u64 size; +} String8; + +// NOTE(geni): What are the Comp macros for? MSVC. They're for MSVC. Try replacing S8LitComp with S8Lit in patches/checks.c and see for yourself. +// (disclaimer: I don't know if it's complying with the standard or just stupid, but clang handles it fine) +#define S8Lit(str) (String8) S8LitComp(str) +#define S8LitComp(str) \ + { .s = (u8*) str, .size = (i32) ArraySize(str) - 1 } + +#define S8Expand(str) (i32)((str).size), ((str).s) diff --git a/source/win32/checks.inc b/source/win32/checks.inc new file mode 100644 index 0000000..545d7cd --- /dev/null +++ b/source/win32/checks.inc @@ -0,0 +1 @@ +CHECK(version_check, 0x3B9970, "0.4.29") diff --git a/source/win32/patches.inc b/source/win32/patches.inc new file mode 100644 index 0000000..0f89e98 --- /dev/null +++ b/source/win32/patches.inc @@ -0,0 +1,5 @@ +PATCH(deleted_message_space, 0x3E15F1, {0x20}) +PATCH(deleted_message_space_length, 0x179B4B, {0x08}) +PATCH(deleted_message_append, 0x179B79, {0xEB, 0x4C}) +PATCH(deleted_message_details, 0xEA8AC, {0xEB}) +PATCH(cooldown, 0x1532BB, {0xEB, 0x46}) diff --git a/src/checks.c b/src/checks.c deleted file mode 100644 index 2e62c40..0000000 --- a/src/checks.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "checks.h" - -#define CHECK(checkname, _address, ...) \ - static byte check_sig_##checkname[] = __VA_ARGS__; \ - static const check checkname = {#checkname, _address, sizeof check_sig_##checkname / sizeof check_sig_##checkname[0], check_sig_##checkname} - -#ifdef _WIN32 -CHECK(version_check, 0x3B7D50, "0.4.28"); -#elif __linux__ -CHECK(version_check, 0x4C92AD, "0.4.27"); -#elif __APPLE__ -CHECK(version_check, 0x47FFE2, "0.4.27"); -#endif - -const check* checks[] = {&version_check}; -const byte num_checks = sizeof checks / sizeof checks[0]; \ No newline at end of file diff --git a/src/checks.h b/src/checks.h deleted file mode 100644 index aeb2a02..0000000 --- a/src/checks.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef CHECKS_H -#define CHECKS_H - -#include "patches.h" - -typedef patch check; - -extern const check* checks[]; -extern const byte num_checks; - -#endif diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 274c658..0000000 --- a/src/main.c +++ /dev/null @@ -1,138 +0,0 @@ -#ifdef _WIN32 -#define DEFAULT_FILENAME "Ripcord.exe" -#define DEFAULT_PATCH_FILENAME "RipcordPatched.exe" -#define _CRT_SECURE_NO_WARNINGS 1 -#elif __linux__ || __APPLE__ -#define DEFAULT_FILENAME "Ripcord" -#define DEFAULT_PATCH_FILENAME "RipcordPatched" -#endif - -#define MATCH(a, b) strcmp(a, b) == 0 - -#include -#include -#include -#include -#include "checks.h" -#include "patches.h" - -/* I hope no (supported) OS ever uses anything different.. */ -const char* portable_ish_basename(const char* path) { - char* base = strrchr(path, '/'); - if (!base) { - base = strrchr(path, '\\'); - } - return base ? base + 1 : path; -} - -void usage(const char* path) { - printf("Usage: %s [-h] [-l] [original (" DEFAULT_FILENAME ") [patched (" DEFAULT_PATCH_FILENAME ") [disabled patches]]]", portable_ish_basename(path)); -} - -void list() { - for (unsigned i = 0; i < num_patches; ++i) { - printf("Patch \"%s\"\n", patches[i]->name); - } -} - -int main(int argc, char** argv) { - if (argc == 2) { - if (MATCH(argv[1], "-h")) { - usage(argv[0]); - } else if (MATCH(argv[1], "-l")) { - list(); - } - - return 0; - } - - /* User wants to disable specific patches */ - if (argc > 3) { - for (unsigned i = 3; i < argc; ++i) { - for (unsigned p = 0; p < num_patches; ++p) { - /* Patch may already be disabled (or NULL for some other reason) */ - if (!patches[p]) { - continue; - } - - if (MATCH(patches[p]->name, argv[i])) { - patches[p] = NULL; - } - } - } - } - - FILE* fp = NULL; - if (argc == 1) { - fputs("No arguments passed, attempting to use " DEFAULT_FILENAME " as original binary...\n", stderr); - fp = fopen(DEFAULT_FILENAME, "rb"); - } else { - fp = fopen(argv[1], "rb"); - } - - if (!fp) { - fputs("Failed to open original binary!\n", stderr); - return 1; - } - - fseek(fp, 0, SEEK_END); - const size_t size = ftell(fp); - rewind(fp); - - byte* buf = malloc(sizeof(byte) * size); - if (!buf) { - fprintf(stderr, - "Failed to allocate buffer (size %zu), not enough memory?", - sizeof(byte) * size); - fclose(fp); - return 1; - } - fread(buf, size, sizeof(byte), fp); - fclose(fp); - - for (unsigned i = 0; i < num_checks; ++i) { - const check* c = checks[i]; - - if (memcmp(buf + c->address, c->sig, c->sig_size) != 0) { - fprintf(stderr, "Check \"%s\" failed!\n", c->name); - - /* Don't return if there are any more checks left to do, it's better to let all of them run */ - if (i == num_checks - 1) { - return 1; - } - - break; - } - } - - for (unsigned i = 0; i < num_patches; ++i) { - const patch* p = patches[i]; - - /* Patch is (probably) disabled */ - if (!p) { - continue; - } - - memcpy(buf + p->address, p->sig, p->sig_size); - printf("Patch \"%s\" done\n", p->name); - } - - if (argc < 2) { - fputs("No patched filename passed, attempting to use " DEFAULT_PATCH_FILENAME " as patched binary...\n", stderr); - fp = fopen(DEFAULT_PATCH_FILENAME, "wb"); - } else { - fp = fopen(argv[2], "wb"); - } - - if (!fp) { - fputs("Failed to create patched binary!\n", stderr); - return 1; - } - const size_t written = fwrite(buf, sizeof(byte), size, fp); - if (written != size) { - fputs("Number of bytes written differs from original size", stderr); - return 1; - } - fclose(fp); - free(buf); -} diff --git a/src/patches.c b/src/patches.c deleted file mode 100644 index 7025587..0000000 --- a/src/patches.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "patches.h" - -#define PATCH(patchname, _address, ...) \ - static byte patch_sig_##patchname[] = __VA_ARGS__; \ - static const patch patchname = {#patchname, _address, sizeof patch_sig_##patchname / sizeof patch_sig_##patchname[0], patch_sig_##patchname} - -#ifdef _WIN32 -PATCH(deleted_message_space, 0x3DF7E1, {0x20}); -PATCH(deleted_message_space_length, 0x177D4B, {0x08}); -PATCH(deleted_message_append, 0x177D79, {0xEB, 0x4C}); -PATCH(deleted_message_details, 0xE985C, {0xEB}); -PATCH(cooldown, 0x1514AF, {0xEB, 0x46}); - -const patch* patches[] = { - &deleted_message_space_length, &deleted_message_details, - &deleted_message_append, &deleted_message_space, &cooldown}; -#elif __linux__ -PATCH(deleted_message_details, 0x163FA0, - {0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3}); -PATCH(deleted_message_append, 0x209DE3, {0xE9, 0x83, 0x00, 0x00}); -PATCH(cooldown, 0x169CD0, {0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3}); - -const patch* patches[] = {&deleted_message_details, &deleted_message_append, &cooldown}; -#elif __APPLE__ -PATCH(deleted_message_details, 0xA2338, - {0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3}); -PATCH(deleted_message_append, 0x188C4, {0xE9, 0x83, 0x00, 0x00}); -PATCH(cooldown, 0x11EE8C, {0xB0, 0x01, 0x90}); - -const patch* patches[] = {&deleted_message_details, &deleted_message_append, &cooldown}; -#endif - -const byte num_patches = sizeof patches / sizeof patches[0]; \ No newline at end of file diff --git a/src/patches.h b/src/patches.h deleted file mode 100644 index 75a4c6f..0000000 --- a/src/patches.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PATCHES_H -#define PATCHES_H - -typedef unsigned char byte; - -typedef struct { - const char* name; - const unsigned address; - const unsigned sig_size; - const byte* sig; -} patch; - -extern const patch* patches[]; -extern const byte num_patches; - -#endif