Skip to content

Commit

Permalink
Add Dynamic Patch from config file
Browse files Browse the repository at this point in the history
Signed-off-by: Acrisio Filho <[email protected]>
  • Loading branch information
Acrisio-Filho authored and jchv committed Feb 17, 2024
1 parent 8c51084 commit f5f7368
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 55 deletions.
23 changes: 3 additions & 20 deletions rugburn.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -149,7 +150,7 @@
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>exportvs.def</ModuleDefinitionFile>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<AdditionalDependencies>kernel32.lib;user32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shlwapi.lib;libvcruntime.lib;libcmt.lib;libucrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand Down Expand Up @@ -180,6 +181,7 @@
<ClCompile Include="src\common.c" />
<ClCompile Include="src\config.c" />
<ClCompile Include="src\dll\rugburn\main.c" />
<ClCompile Include="src\hex.c" />
<ClCompile Include="src\hooks\hooks.c" />
<ClCompile Include="src\hooks\kernel32\inject.c" />
<ClCompile Include="src\hooks\user32\window.c" />
Expand All @@ -193,25 +195,6 @@
<ClCompile Include="src\hooks\msvcr100\msvcr100.c" />
<ClCompile Include="src\patch_usa_852.c" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\bootstrap.h" />
<ClInclude Include="src\common-fnptr.h" />
<ClInclude Include="src\common.h" />
<ClInclude Include="src\config.h" />
<ClInclude Include="src\hooks\hooks.h" />
<ClInclude Include="src\hooks\kernel32\inject.h" />
<ClInclude Include="src\hooks\user32\window.h" />
<ClInclude Include="src\hooks\wininet\netredir.h" />
<ClInclude Include="src\hooks\ws2_32\redir.h" />
<ClInclude Include="src\ijlfwd.h" />
<ClInclude Include="src\inject.h" />
<ClInclude Include="src\json.h" />
<ClInclude Include="src\patch.h" />
<ClInclude Include="src\regex.h" />
<ClInclude Include="src\third_party\lend\ld32.h" />
<ClCompile Include="src\hooks\msvcr100\msvcr100.h" />
<ClCompile Include="src\patch_usa_852.h" />
</ItemGroup>
<ItemGroup>
<None Include="exportvs.def" />
<None Include="LICENSE.md" />
Expand Down
20 changes: 1 addition & 19 deletions rugburn.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,7 @@
<ClCompile Include="src\config.c" />
<ClCompile Include="src\hooks\msvcr100\msvcr100.c" />
<ClCompile Include="src\patch_usa_852.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\bootstrap.h" />
<ClInclude Include="src\common-fnptr.h" />
<ClInclude Include="src\common.h" />
<ClInclude Include="src\hooks\hooks.h" />
<ClInclude Include="src\hooks\kernel32\inject.h" />
<ClInclude Include="src\hooks\user32\window.h" />
<ClInclude Include="src\hooks\wininet\netredir.h" />
<ClInclude Include="src\hooks\ws2_32\redir.h" />
<ClInclude Include="src\ijlfwd.h" />
<ClInclude Include="src\inject.h" />
<ClInclude Include="src\patch.h" />
<ClInclude Include="src\third_party\lend\ld32.h" />
<ClInclude Include="src\json.h" />
<ClInclude Include="src\regex.h" />
<ClInclude Include="src\config.h" />
<ClCompile Include="src\hooks\msvcr100\msvcr100.h" />
<ClCompile Include="src\patch_usa_852.h" />
<ClCompile Include="src\hex.c" />
</ItemGroup>
<ItemGroup>
<None Include="exportvs.def" />
Expand Down
5 changes: 4 additions & 1 deletion src/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
PFNLOADLIBRARYAPROC pLoadLibraryA = NULL;
PFNGETPROCADDRESSPROC pGetProcAddress = NULL;

#ifndef _MSC_VER
typedef struct _EXCEPTION_REGISTRATION_RECORD {
struct _EXCEPTION_REGISTRATION_RECORD *Next;
EXCEPTION_DISPOSITION *Handler;
Expand All @@ -22,6 +23,7 @@ typedef struct _NT_TIB {
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB, *PNT_TIB;
#endif

typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
Expand Down Expand Up @@ -83,6 +85,7 @@ typedef struct _TEB {
#else // x86
PTEB tebPtr = (PTEB)__readfsdword(OFFSETOF(NT_TIB, Self));
#endif
return tebPtr;
}
#endif

Expand Down Expand Up @@ -134,7 +137,7 @@ VOID BootstrapPEB() {
pAddressOfOrdinals = (LPWORD)(pExportDir->AddressOfNameOrdinals + pImageBase);
pAddressOfNames = (LPDWORD)(pExportDir->AddressOfNames + pImageBase);

for (i = 0; i < iNumberOfNames; i++) {
for (i = 0; i < (int)iNumberOfNames; i++) {
PCHAR pName = (PCHAR)(pAddressOfNames[i] + pImageBase);

// Exit early iff we have the ordinals we're looking for.
Expand Down
2 changes: 1 addition & 1 deletion src/common-fnptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ typedef HLOCAL (STDCALL *PFNLOCALFREEPROC)(HLOCAL);
typedef HMODULE (STDCALL *PFNGETMODULEHANDLEAPROC)(LPCSTR);
typedef DWORD (STDCALL *PFNGETMODULEFILENAMEAPROC)(HMODULE, LPCH, DWORD);
typedef DWORD (STDCALL *PFNGETFILEATTRIBUTESAPROC)(LPCSTR);
typedef DECLSPEC_NORETURN VOID (STDCALL *PFNEXITPROCESSPROC)(UINT);
typedef VOID (STDCALL *PFNEXITPROCESSPROC)(UINT);
typedef DWORD (STDCALL *PFNGETFILESIZEPROC)(HANDLE, LPDWORD);
typedef BOOL (STDCALL *PFNREADFILEPROC)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
typedef BOOL (STDCALL *PFNWRITEFILEPROC)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
Expand Down
2 changes: 2 additions & 0 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ VOID InitCommon() {
}

// C standard library functions
#ifndef _MSC_VER
int strcmp(LPCSTR dest, LPCSTR src) {
int cmp;
do {
Expand Down Expand Up @@ -113,6 +114,7 @@ PVOID memset(PVOID p, INT c, UINT size) {
}
return p;
}
#endif

// String formatting
int VSPrintfZ(LPSTR dest, LPCSTR fmt, va_list args) {
Expand Down
32 changes: 31 additions & 1 deletion src/config.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "config.h"
#include "json.h"
#include "hex.h"
#include "patch.h"

LPCSTR RugburnConfigFilename = "rugburn.json";
RUGBURNCONFIG Config;
Expand Down Expand Up @@ -49,12 +51,26 @@ void ReadJsonPortRewriteRuleArray(LPSTR *json) {
Config.NumPortRewriteRules++;
}

void ReadJsonPatchAddressMap(LPSTR *json, LPCSTR key) {
LPCSTR value = JsonReadString(json);

if (Config.NumPatchAddress == MAXPATCHADDRESS) {
FatalError("Reached maximum number of Patch address!");
}

Config.PatchAddress[Config.NumPatchAddress].addr = ReadDword(key);
TranslateHexInText(value, Config.PatchAddress[Config.NumPatchAddress].patch, sizeof(Config.PatchAddress[Config.NumPatchAddress].patch), &Config.PatchAddress[Config.NumPatchAddress].patch_len);
Config.NumPatchAddress++;
}

void ReadJsonConfigMap(LPSTR *json, LPCSTR key) {
if (!strcmp(key, "UrlRewrites")) {
JsonReadMap(json, ReadJsonUrlRewriteRuleMap);
} else if (!strcmp(key, "PortRewrites")) {
JsonReadArray(json, ReadJsonPortRewriteRuleArray);
} else {
} else if (!strcmp(key, "PatchAddress")) {
JsonReadMap(json, ReadJsonPatchAddressMap);
} else {
FatalError("Unexpected JSON config key '%s'", key);
}
}
Expand Down Expand Up @@ -123,3 +139,17 @@ BOOL RewriteAddr(LPSOCKADDR_IN addr) {

return FALSE;
}

void PatchAddress() {
int i;

for (i = 0; i < Config.NumPatchAddress; i++) {

if (Config.PatchAddress[i].addr != 0 && Config.PatchAddress[i].patch_len > 0 && Config.PatchAddress[i].patch[0] != '\0') {

Patch((LPVOID)Config.PatchAddress[i].addr, Config.PatchAddress[i].patch, Config.PatchAddress[i].patch_len);

Log("PatchAddress: 0x%08lX, Len: %d, Value: %s\r\n", Config.PatchAddress[i].addr, Config.PatchAddress[i].patch_len, Config.PatchAddress[i].patch);
}
}
}
11 changes: 11 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#define MAXURLREWRITES 64
#define MAXPORTREWRITES 16
#define MAXPATCHADDRESS 64

typedef struct _URLREWRITERULE {
REGEX *from;
Expand All @@ -18,18 +19,28 @@ typedef struct _PORTREWRITERULE {
LPCSTR toaddr;
} PORTREWRITERULE, *LPPORTREWRITERULE;

typedef struct _PATCHADDRESS {
DWORD addr;
CHAR patch[1024];
int patch_len;
} PATCHADDRESS, *LPPATCHADDRESS;

typedef struct _RUGBURNCONFIG {
URLREWRITERULE UrlRewriteRules[MAXURLREWRITES];
int NumUrlRewriteRules;

PORTREWRITERULE PortRewriteRules[MAXPORTREWRITES];
int NumPortRewriteRules;

PATCHADDRESS PatchAddress[MAXPATCHADDRESS];
int NumPatchAddress;
} RUGBURNCONFIG, *LPRUGBURNCONFIG;

extern RUGBURNCONFIG Config;

void LoadJsonRugburnConfig();
LPCSTR RewriteURL(LPCSTR url);
BOOL RewriteAddr(LPSOCKADDR_IN addr);
void PatchAddress();

#endif
34 changes: 21 additions & 13 deletions src/dll/rugburn/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static VOID InitEnvironment() {
/**
* Implements the GameGuard patches for Pangya US 852.00.
*/
static VOID STDCALL PatchGG_US852(PVOID unused) {
static DWORD STDCALL PatchGG_US852(PVOID unused) {
while(1) {
// TODO(john): Remove hardcoded addresses.
if (*(DWORD*)0x00A495E0 == 0x8F143D83) {
Expand Down Expand Up @@ -82,7 +82,7 @@ static VOID STDCALL PatchGG_US852(PVOID unused) {

Patch((LPVOID)0x00655630, jmp_to_patch_ranking, sizeof(jmp_to_patch_ranking));
Log("Patched Ranking System disabled (US 852)\r\n");
return;
return TRUE;
}
if (*(DWORD*)0x00A49580 == 0x8F143D83) {
Patch((LPVOID)0x00A49580, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Expand All @@ -92,16 +92,17 @@ static VOID STDCALL PatchGG_US852(PVOID unused) {
Patch((LPVOID)0x00A496E0, "\xC3", 1);
Patch((LPVOID)0x00A49840, "\xC3", 1);
Log("Patched GG check routines (US 824)\r\n");
return;
return TRUE;
}
Delay(5);
}
return FALSE;
}

/**
* Implements the GameGuard patches for Pangya JP 972.00.
*/
static VOID STDCALL PatchGG_JP972(PVOID unused) {
static DWORD STDCALL PatchGG_JP972(PVOID unused) {
while(1) {
// TODO(john): Remove hardcoded addresses.
if (*(DWORD*)0x00A5CD10 == 0x1BA43D83) {
Expand All @@ -112,7 +113,7 @@ static VOID STDCALL PatchGG_JP972(PVOID unused) {
Patch((LPVOID)0x00A5CE10, "\xC3", 1);
Patch((LPVOID)0x00A5CE40, "\xC3", 1);
Log("Patched GG check routines (JP 972)\r\n");
return;
return TRUE;
}
if (*(DWORD*)0x00A5CF80 == 0x1BA43D83) {
Patch((LPVOID)0x00A5CF80, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Expand All @@ -122,7 +123,7 @@ static VOID STDCALL PatchGG_JP972(PVOID unused) {
Patch((LPVOID)0x00A5CE80, "\xC3", 1);
Patch((LPVOID)0x00A5CEB0, "\xC3", 1);
Log("Patched GG check routines (JP 974)\r\n");
return;
return TRUE;
}
if (*(DWORD*)0x00A5CF80 == 0x1C143D83) {
Patch((LPVOID)0x00A5CF80, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Expand All @@ -132,10 +133,22 @@ static VOID STDCALL PatchGG_JP972(PVOID unused) {
Patch((LPVOID)0x00A5CE80, "\xC3", 1);
Patch((LPVOID)0x00A5CEB0, "\xC3", 1);
Log("Patched GG check routines (JP 983)\r\n");
return;
return TRUE;
}
Delay(5);
}
return FALSE;
}

static VOID STDCALL PatchDynamicAndGG(LPTHREAD_START_ROUTINE patchThread) {

if (!patchThread) {
Warning("It looks like no patch exists for this version of PangYa™.\nThe game will likely exit a couple minutes after detecting GameGuard is not present.");
PatchAddress();
}else {
if (patchThread(NULL) == TRUE)
PatchAddress();
}
}

/**
Expand All @@ -161,13 +174,8 @@ static VOID InitGGPatch() {
break;
}

if (!patchThread) {
Warning("It looks like no patch exists for this version of PangYa™.\nThe game will likely exit a couple minutes after detecting GameGuard is not present.");
return;
}

pCreateThread = GetProc(hKernel32Module, "CreateThread");
pCreateThread(0, 0, patchThread, 0, 0, 0);
pCreateThread(0, 0, (LPTHREAD_START_ROUTINE)PatchDynamicAndGG, patchThread, 0, 0);
}

// Standalone forwarding DLL entrypoint
Expand Down
Loading

0 comments on commit f5f7368

Please sign in to comment.