diff --git a/platform/es3sec.c b/platform/es3sec.c index c1b116e..be29cd2 100644 --- a/platform/es3sec.c +++ b/platform/es3sec.c @@ -50,6 +50,35 @@ static HRESULT es3sec_hub_get_string_descriptor(struct irp *irp, PUSB_DESCRIPTOR static CONFIGRET my_CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags); static CONFIGRET (*next_CM_Get_Child)(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags); +static CONFIGRET my_CM_Get_Parent( + PDEVINST pdnDevInst, + DEVINST dnDevInst, + ULONG ulFlags +); + +static CONFIGRET (*next_CM_Get_Parent)( + PDEVINST pdnDevInst, + DEVINST dnDevInst, + ULONG ulFlags +); + +static CONFIGRET my_CM_Get_DevNode_Registry_PropertyA( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags +); +static CONFIGRET (*next_CM_Get_DevNode_Registry_PropertyA)( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags +); + static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( DEVINST dnDevInst, ULONG ulProperty, @@ -67,17 +96,73 @@ static CONFIGRET (*next_CM_Get_DevNode_Registry_PropertyW)( ULONG ulFlags ); +static CONFIGRET my_CM_Get_DevNode_Status( + PULONG pulStatus, + PULONG pulProblemNumber, + DEVINST dnDevInst, + ULONG ulFlags +); + +static CONFIGRET (*next_CM_Get_DevNode_Status)( + PULONG pulStatus, + PULONG pulProblemNumber, + DEVINST dnDevInst, + ULONG ulFlags +); + +static CONFIGRET my_CM_Get_Device_IDA( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +); + +static CONFIGRET (*next_CM_Get_Device_IDA)( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +); + +static CONFIGRET my_CM_Get_Device_ID_Size( + PULONG pulLen, + DEVINST dnDevInst, + ULONG ulFlags +); + +static CONFIGRET (*next_CM_Get_Device_ID_Size)( + PULONG pulLen, + DEVINST dnDevInst, + ULONG ulFlags +); + + static const struct hook_symbol cm_syms[] = { { + .name = "CM_Get_DevNode_Registry_PropertyA", + .patch = my_CM_Get_DevNode_Registry_PropertyA, + .link = (void **) &next_CM_Get_DevNode_Registry_PropertyA + }, { .name = "CM_Get_DevNode_Registry_PropertyW", .patch = my_CM_Get_DevNode_Registry_PropertyW, .link = (void **) &next_CM_Get_DevNode_Registry_PropertyW - }, - { + }, { .name = "CM_Get_Child", .patch = my_CM_Get_Child, .link = (void **) &next_CM_Get_Child - }, + }, { + .name = "CM_Get_Parent", + .patch = my_CM_Get_Parent, + .link = (void **) &next_CM_Get_Parent + }, { + .name = "CM_Get_DevNode_Status", + .patch = my_CM_Get_DevNode_Status, + .link = (void **) &next_CM_Get_DevNode_Status + }, { + .name = "CM_Get_Device_IDA", + .patch = my_CM_Get_Device_IDA, + .link = (void **) &next_CM_Get_Device_IDA + } }; HRESULT es3sec_hook_init( @@ -489,6 +574,19 @@ static HRESULT es3sec_hub_connection_driver_key_name(struct irp *irp) return hr; } +static CONFIGRET my_CM_Get_DevNode_Registry_PropertyA( + DEVINST dnDevInst, + ULONG ulProperty, + PULONG pulRegDataType, + PVOID Buffer, + PULONG pulLength, + ULONG ulFlags) +{ + dprintf("ES3 Dongle: my_CM_Get_DevNode_Registry_PropertyA\n"); + return next_CM_Get_DevNode_Registry_PropertyA(dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags); + // return my_CM_Get_DevNode_Registry_PropertyW(dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags); +} + static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( DEVINST dnDevInst, ULONG ulProperty, @@ -497,6 +595,8 @@ static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( PULONG pulLength, ULONG ulFlags) { + dprintf("ES3 Dongle: my_CM_Get_DevNode_Registry_PropertyW\n"); + CONFIGRET cr = next_CM_Get_DevNode_Registry_PropertyW(dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags); if (dnDevInst != HUB_DEVINST) { @@ -525,6 +625,8 @@ static CONFIGRET my_CM_Get_DevNode_Registry_PropertyW( static CONFIGRET my_CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) { + dprintf("ES3 Dongle: my_CM_Get_Child\n"); + if (dnDevInst != root_dev_inst) { return next_CM_Get_Child(pdnDevInst, dnDevInst, ulFlags); @@ -533,3 +635,74 @@ static CONFIGRET my_CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG u *pdnDevInst = HUB_DEVINST; return CR_SUCCESS; } + +static CONFIGRET my_CM_Get_Parent( + PDEVINST pdnDevInst, + DEVINST dnDevInst, + ULONG ulFlags +) +{ + dprintf("ES3 Dongle: my_CM_Get_Parent\n"); + + if (dnDevInst != HUB_DEVINST) + { + return next_CM_Get_Parent(pdnDevInst, dnDevInst, ulFlags); + } + + *pdnDevInst = root_dev_inst; + return CR_SUCCESS; +} + +static CONFIGRET my_CM_Get_DevNode_Status( + PULONG pulStatus, + PULONG pulProblemNumber, + DEVINST dnDevInst, + ULONG ulFlags +) +{ + dprintf("ES3 Dongle: my_CM_Get_DevNode_Status\n"); + + if (dnDevInst != HUB_DEVINST) + { + return next_CM_Get_DevNode_Status(pulStatus, pulProblemNumber, dnDevInst, ulFlags); + } + + *pulStatus = DN_DRIVER_LOADED; + *pulProblemNumber = 0; + return CR_SUCCESS; +} + +static CONFIGRET my_CM_Get_Device_IDA( + DEVINST dnDevInst, + PSTR Buffer, + ULONG BufferLen, + ULONG ulFlags +) +{ + dprintf("ES3 Dongle: my_CM_Get_Device_IDA\n"); + + if (dnDevInst != HUB_DEVINST) + { + return next_CM_Get_Device_IDA(dnDevInst, Buffer, BufferLen, ulFlags); + } + + strcpy_s(Buffer, BufferLen, "USB\\ROOT_HUB"); + return CR_SUCCESS; +} + +static CONFIGRET my_CM_Get_Device_ID_Size( + PULONG pulLen, + DEVINST dnDevInst, + ULONG ulFlags +) +{ + dprintf("ES3 Dongle: my_CM_Get_Device_ID_Size\n"); + + if (dnDevInst != HUB_DEVINST) + { + return next_CM_Get_Device_ID_Size(pulLen, dnDevInst, ulFlags); + } + + *pulLen = 11; + return CR_SUCCESS; +} diff --git a/taikohook/amfw.c b/taikohook/amfw.c index fa9c601..c59b213 100644 --- a/taikohook/amfw.c +++ b/taikohook/amfw.c @@ -1,9 +1,15 @@ #include +#include + #include "taikohook/config.h" #include "hook/table.h" +#include "hook/iohook.h" +#include "hooklib/dll.h" #include "hooklib/path.h" +#include "hooklib/setupapi.h" +#include "hooklib/serial.h" #include "util/dprintf.h" @@ -15,12 +21,41 @@ * that AMFW uses and let it talk to the game for us. */ +static const wchar_t *target_modules[] = { + L"AMFrameWork.dll", + L"nbamUsbfinder.dll", +}; + +static const size_t target_modules_len = _countof(target_modules); + +static void dll_hook_insert_hooks(HMODULE target); + +static HMODULE WINAPI hook_LoadLibraryA(const char *name); +static HMODULE (WINAPI *next_LoadLibraryA)(const char *name); + +static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name); +static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name); + +static const struct hook_symbol kernel32_syms[] = { + { + .name = "LoadLibraryA", + .patch = hook_LoadLibraryA, + .link = (void **) &next_LoadLibraryA, + }, { + .name = "LoadLibraryW", + .patch = hook_LoadLibraryW, + .link = (void **) &next_LoadLibraryW, + } +}; + HRESULT amfw_hook_init(wchar_t serial[13]) { HANDLE hMod; dprintf("AMFW: Init\n"); + dll_hook_insert_hooks(NULL); + hMod = GetModuleHandle("AMFrameWork.dll"); if (hMod == NULL) { @@ -31,6 +66,104 @@ HRESULT amfw_hook_init(wchar_t serial[13]) dprintf("AMFW: Found AMFrameWork Handle\n"); path_hook_insert_hooks(hMod); + dll_hook_insert_hooks(hMod); + setupapi_hook_insert_hooks(hMod); + + serial_hook_apply_hooks(hMod); + iohook_apply_hooks(hMod); return S_OK; } + +static void dll_hook_insert_hooks(HMODULE target) { + hook_table_apply( + target, + "kernel32.dll", + kernel32_syms, + _countof(kernel32_syms)); +} + +static HMODULE WINAPI hook_LoadLibraryA(const char *name) +{ + HMODULE result; + wchar_t *name_w; + size_t name_c; + + if (name == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + + return NULL; + } + + mbstowcs_s(&name_c, NULL, 0, name, 0); + name_w = malloc(name_c * sizeof(wchar_t)); + + if (name_w == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + + return NULL; + } + + mbstowcs_s(NULL, name_w, name_c, name, name_c - 1); + result = hook_LoadLibraryW(name_w); + free(name_w); + + return result; +} + + +static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name) +{ + const wchar_t *name_end; + const wchar_t *target_module; + bool already_loaded; + HMODULE result; + size_t name_len; + size_t target_module_len; + + if (name == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + + return NULL; + } + + // Check if the module is already loaded + already_loaded = GetModuleHandleW(name) != NULL; + + // Must call the next handler so the DLL reference count is incremented + result = next_LoadLibraryW(name); + + if (!already_loaded && result != NULL) { + name_len = wcslen(name); + + for (size_t i = 0; i < target_modules_len; i++) { + target_module = target_modules[i]; + target_module_len = wcslen(target_module); + + // Check if the newly loaded library is at least the length of + // the name of the target module + if (name_len < target_module_len) { + continue; + } + + name_end = &name[name_len - target_module_len]; + + // Check if the name of the newly loaded library is one of the + // modules the path hooks should be injected into + if (_wcsicmp(name_end, target_module) != 0) { + continue; + } + + dprintf("Taiko: Hooked %S\n", target_module); + + dll_hook_insert_hooks(result); + // path_hook_insert_hooks(result); + setupapi_hook_insert_hooks(result); + + serial_hook_apply_hooks(result); + iohook_apply_hooks(result); + } + } + + return result; +}