summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrebeccadoth <rebeccadoth@disroot.org>2026-11-10 19:17:23 +0100
committerrebeccadoth <rebeccadoth@disroot.org>2026-11-10 19:17:23 +0100
commit7af6395a130685954cd9903bc02084640ae05e27 (patch)
tree258feb356f5aeb1eaba527488336fccf17d80933
initial commitHEADmaster
-rw-r--r--.gitignore4
-rw-r--r--CMakeLists.txt11
-rw-r--r--build.ps111
-rw-r--r--dllproxy.c180
-rw-r--r--exports.def9
-rw-r--r--proxy.S24
6 files changed, 239 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed4a5dc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+build/
+asdbuild/
+*.lnk
+Makefile \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..7fe6bf7
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.10)
+project(pd2-bw LANGUAGES C ASM_NASM)
+
+set(CMAKE_C_STANDARD "11")
+
+set(CMAKE_C_FLAGS "/Wall")
+
+set_source_files_properties(proxy.S PROPERTIES LANGUAGE ASM_NASM)
+
+add_library(DINPUT8 SHARED proxy.S dllproxy.c exports.def)
+#add_executable(test dllproxy.c proxy.S)
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..1b107ff
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,11 @@
+if (Test-Path -Path "build\") {
+ cd build
+ cmake --build .
+ cd ..
+} else {
+ mkdir build
+ cd build
+ cmake -G "Visual Studio 17 2022" -A Win32 ..
+ cd ..
+ .\build.ps1
+} \ No newline at end of file
diff --git a/dllproxy.c b/dllproxy.c
new file mode 100644
index 0000000..808c168
--- /dev/null
+++ b/dllproxy.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+//#pragma warning( push )
+//#pragma warning( disable : 4668)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <psapi.h>
+//#pragma warning( pop )
+
+static void* faddrs[6];
+char fnames[] = "DirectInput8Create\0" "DllCanUnloadNow\0" "DllGetClassObject\0" \
+"DllRegisterServer\0" "DllUnregisterServer\0" "GetdfDIJoystick\0" "\3";
+
+/*[[nodiscard]]*/ size_t next_name(char *names[])
+{
+ size_t len = 0;
+ while(names != NULL) {
+ if(**names == '\0') { (*names)++; break; }
+ else if(**names == '\3') break;
+ (*names)++; len++;
+ }
+
+ return len;
+}
+
+HMODULE init_faddrs(void)
+{
+ HMODULE h = LoadLibrary("C:\\Windows\\SysWOW64\\dinput8.dll"); // perhaps i should ship my own original dinput8.dll and proxy from a renamed copy but uhhhh no
+ if (h == NULL) goto init_end;
+
+ char* fname = fnames;
+ size_t i = 0;
+ do {
+ faddrs[i] = (void*)GetProcAddress(h, fname);
+ i++;
+ } while(next_name(&fname));
+
+
+init_end:
+ return h;
+}
+
+HMODULE hodll = NULL;
+
+
+/*void* sigscan(const char* pattern, const char* mask)
+{
+ HMODULE module = GetModuleHandle(NULL);
+ if(module == NULL) return NULL;
+
+ MODULEINFO minfo;
+ if(GetModuleInformation(GetCurrentProcess(), module, &minfo, sizeof(minfo)) == 0) return NULL;
+
+ size_t len = strlen(mask);
+ unsigned char* addr = (unsigned char*)minfo.lpBaseOfDll;
+ for(DWORD i = 0; i < minfo.SizeOfImage - (len-1); i++)
+ {
+ for(size_t j = 0; j < len; j++)
+ {
+ if(addr[i + j] == (unsigned char)(pattern[j]) && (unsigned char)(mask[j]) != '?')
+ {
+ if(j == (len-1))
+ return (void*)(addr + i);
+ }
+ else
+ break;
+
+ }
+ }
+
+ return NULL;
+}*/
+
+/*
+void* GetStackBaseFromTEB(void)
+{
+#if defined(_WIN64)
+ return (void*)__readgsqword(0x08);
+#elif defined(_WIN32)
+ return (void*)__readfsdword(0x04);
+#endif
+}
+*/
+
+void* GetEntryPointOfHostProcess(void)
+{
+ HMODULE module = GetModuleHandle(NULL);
+ if(module == NULL) return NULL;
+
+ MODULEINFO minfo;
+ if(GetModuleInformation(GetCurrentProcess(), module, &minfo, sizeof(minfo)) == 0) return NULL;
+ return minfo.EntryPoint;
+}
+
+void* PD2_EBP = NULL;
+uint8_t writeback[5] = { 0 };
+void* retaddr = NULL;
+
+#pragma pack(push, 4)
+typedef struct _Patch {
+ uint8_t* writeback;
+ uint8_t NOPs; // to keep alignment, unsure if actually needed but would be nice if the debugger suddenly didn't re-disassemble everything incorrectly after the patch
+ void* addr;
+ void (*func)(void);
+} Patch;
+#pragma pack(pop)
+
+void PatchCALL(Patch* patch, BOOL UnVProtect)
+{
+ if(UnVProtect) {
+ DWORD _;
+ if(VirtualProtect(patch->addr, 5 + patch->NOPs, PAGE_EXECUTE_READWRITE, &_) == 0) {
+ char err[64] = { '\0' };
+ snprintf(err, 64, "%lu", GetLastError());
+ MessageBox(GetCurrentProcess(), err, NULL, MB_OK);
+ return;
+ }
+ }
+}
+
+void PatchGame(void* addr, void (*func)(void))
+{
+ DWORD _;
+ if(VirtualProtect(addr, 5, PAGE_EXECUTE_READWRITE, &_) == 0)
+ {
+ char err[64] = { '\0' };
+ snprintf(err, 64, "%lu", GetLastError());
+ MessageBox(GetCurrentProcess(), err, NULL, MB_OK);
+ return;
+ }
+ uint8_t oinst[5] = { 0 };
+ memcpy_s(oinst, sizeof(*oinst) * 5, addr, 5);
+ uint8_t patched[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
+ ((int32_t*)(patched + 1))[0] = (uintptr_t)func - ((uintptr_t)addr + 1 + sizeof(uintptr_t)); // math assumes patching over a jmp or call, not that it really matters
+ memcpy_s(addr, 5, patched, 5);
+ memcpy_s(writeback, 5, oinst, 5); // magic global that hopefully works
+}
+
+void __declspec(naked) GetEBPWithinGame(void)
+{
+ __asm {
+ pushad
+ }
+ __asm {
+ mov PD2_EBP, ebp
+ }
+ memcpy_s(retaddr, 5, writeback, 5);
+ __asm {
+ popad
+ push retaddr
+ ret
+ }
+}
+
+BOOL WINAPI DllMain(/*[[maybe_unused]]*/ HINSTANCE h_dll, DWORD fwdReason, LPVOID lpvReserved)
+{
+ switch(fwdReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ hodll = init_faddrs();
+ if(hodll == NULL) return FALSE;
+ retaddr = GetEntryPointOfHostProcess();
+ PatchGame(retaddr, &GetEBPWithinGame);
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // [[fallthrough]];
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ if(lpvReserved != NULL) break;
+ if(hodll != NULL) FreeLibrary(hodll);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/exports.def b/exports.def
new file mode 100644
index 0000000..23e7f1b
--- /dev/null
+++ b/exports.def
@@ -0,0 +1,9 @@
+LIBRARY "DINPUT8.dll"
+
+EXPORTS
+DirectInput8Create PRIVATE
+DllCanUnloadNow PRIVATE
+DllGetClassObject PRIVATE
+DllRegisterServer PRIVATE
+DllUnregisterServer PRIVATE
+GetdfDIJoystick PRIVATE \ No newline at end of file
diff --git a/proxy.S b/proxy.S
new file mode 100644
index 0000000..72010ae
--- /dev/null
+++ b/proxy.S
@@ -0,0 +1,24 @@
+[bits 32]
+
+extern _faddrs
+
+global _DirectInput8Create
+global _DllCanUnloadNow
+global _DllGetClassObject
+global _DllRegisterServer
+global _DllUnregisterServer
+global _GetdfDIJoystick
+
+section .text
+_DirectInput8Create:
+ jmp _faddrs[0 * 4]
+_DllCanUnloadNow:
+ jmp _faddrs[1 * 4]
+_DllGetClassObject:
+ jmp _faddrs[2 * 4]
+_DllRegisterServer:
+ jmp _faddrs[3 * 4]
+_DllUnregisterServer:
+ jmp _faddrs[4 * 4]
+_GetdfDIJoystick:
+ jmp _faddrs[5 * 4] \ No newline at end of file