From 98d2ea139095c84ec84ce13836dc70ccad6a43d9 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Wed, 13 Sep 2023 11:25:29 -0400 Subject: [PATCH 1/6] vfs: add hook for C:\Users\AppUser --- platform/vfs.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/platform/vfs.c b/platform/vfs.c index 7bd2953..befc87d 100644 --- a/platform/vfs.c +++ b/platform/vfs.c @@ -20,6 +20,10 @@ static HRESULT vfs_path_hook_nthome( const wchar_t *src, wchar_t *dest, size_t *count); +static HRESULT vfs_path_hook_w10home( + const wchar_t *src, + wchar_t *dest, + size_t *count); static HRESULT vfs_path_hook_option( const wchar_t *src, wchar_t *dest, @@ -31,6 +35,9 @@ static wchar_t vfs_nthome_real[MAX_PATH]; static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser"; static const size_t vfs_nthome_len = _countof(vfs_nthome) - 1; +static const wchar_t vfs_w10home[] = L"C:\\Users\\AppUser"; +static const size_t vfs_w10home_len = _countof(vfs_w10home) - 1; + static const wchar_t vfs_option[] = L"C:\\Mount\\Option"; static const size_t vfs_option_len = _countof(vfs_option) - 1; @@ -144,6 +151,12 @@ HRESULT vfs_hook_init(const struct vfs_config *config) return hr; } + hr = path_hook_push(vfs_path_hook_w10home); + + if (FAILED(hr)) { + return hr; + } + if (vfs_config.option[0] != L'\0') { hr = path_hook_push(vfs_path_hook_option); @@ -357,6 +370,53 @@ static HRESULT vfs_path_hook_nthome( return S_OK; } +static HRESULT vfs_path_hook_w10home( + const wchar_t *src, + wchar_t *dest, + size_t *count) +{ + size_t required; + size_t redir_len; + size_t shift; + + assert(src != NULL); + assert(count != NULL); + + /* Case-insensitive check to see if src starts with vfs_w10home */ + + if (path_compare_w(src, vfs_w10home, vfs_w10home_len) != 0) { + return S_FALSE; + } + + /* Check if the character after vfs_w10home is a separator or the end of + the string */ + + if (!path_is_separator_w(src[vfs_w10home_len]) && + src[vfs_w10home_len] != L'\0') + { + return S_FALSE; + } + + /* Cut off the matched \, add the replaced prefix, count NUL */ + + shift = path_is_separator_w(src[vfs_w10home_len]) ? 1 : 0; + redir_len = wcslen(vfs_nthome_real); + required = wcslen(src) - vfs_w10home_len - shift + redir_len + 1; + + if (dest != NULL) { + if (required > *count) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + wcscpy_s(dest, *count, vfs_nthome_real); + wcscpy_s(dest + redir_len, *count - redir_len, src + vfs_w10home_len + shift); + } + + *count = required; + + return S_OK; +} + static HRESULT vfs_path_hook_option( const wchar_t *src, wchar_t *dest, From 3d7d9fcaa5fa145db5a14532426e1f9e0e664a55 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Wed, 13 Sep 2023 17:54:40 -0400 Subject: [PATCH 2/6] hooklib: add createprocess hook skeleton --- hooklib/createprocess.c | 176 ++++++++++++++++++++++++++++++++++++++++ hooklib/createprocess.h | 14 ++++ 2 files changed, 190 insertions(+) create mode 100644 hooklib/createprocess.c create mode 100644 hooklib/createprocess.h diff --git a/hooklib/createprocess.c b/hooklib/createprocess.c new file mode 100644 index 0000000..1b1ebad --- /dev/null +++ b/hooklib/createprocess.c @@ -0,0 +1,176 @@ +#include + +#include +#include +#include +#include + +#include "hook/table.h" + +static BOOL WINAPI my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); +BOOL my_CreateProcessW( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); + +static BOOL (WINAPI *next_CreateProcessA)( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); + +static BOOL (WINAPI *next_CreateProcessW)( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); + +static const struct hook_symbol win32_hooks[] = { + { + .name = "CreateProcessA", + .patch = my_CreateProcessA, + .link = (void **) &next_CreateProcessA + }, + { + .name = "CreateProcessW", + .patch = my_CreateProcessW, + .link = (void **) &next_CreateProcessW + }, +}; + +static bool did_init = false; + +static struct process_hook_sym_w *processe_syms_w; +static struct process_hook_sym_a *processe_syms_a; + +static size_t processe_nsyms_a = 0; +static size_t processe_nsyms_w = 0; + +void createprocess_push_hook_w(const wchar_t *name, const wchar_t *dll_name, const wchar_t *tail) { + createprocess_hook_init(); +} + +void createprocess_push_hook_a(const char *name, const char *dll_name, const char *tail) { + createprocess_hook_init(); +} + +void createprocess_hook_init() { + if (did_init) { + return; + } + did_init = true; + + hook_table_apply( + NULL, + "kernel32.dll", + win32_hooks, + _countof(win32_hooks)); + + dprintf("CreateProcess: Init\n"); +} + + +static BOOL WINAPI my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +) +{ + if (strncmp(".\\15312firm\\firmupdate_1113.exe", lpCommandLine, 31)) { + return next_CreateProcessA( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); + } + + dprintf("CreateProcess: Hooking child process %s\n", lpCommandLine); + char new_cmd[MAX_PATH] = "inject -d -k carolhook.dll "; + strcat_s(new_cmd, MAX_PATH, lpCommandLine); + + return next_CreateProcessA( + lpApplicationName, + new_cmd, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); +} + +BOOL my_CreateProcessW( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + return next_CreateProcessW( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); +} \ No newline at end of file diff --git a/hooklib/createprocess.h b/hooklib/createprocess.h new file mode 100644 index 0000000..fdbaa9b --- /dev/null +++ b/hooklib/createprocess.h @@ -0,0 +1,14 @@ +void createprocess_push_hook_w(); +void createprocess_push_hook_a(); + +struct process_hook_sym_w { + const wchar_t *name; + const wchar_t *dll_name; + const wchar_t *tail; +}; + +struct process_hook_sym_a { + const char *name; + const char *dll_name; + const char *tail; +}; \ No newline at end of file From 2dbb4aec8cacdfbddd8fc7b5a76c7c98d4bba416 Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Wed, 13 Sep 2023 19:54:22 -0400 Subject: [PATCH 3/6] hooklib: add createprocess to meson --- hooklib/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooklib/meson.build b/hooklib/meson.build index d112da6..4a381b4 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -9,6 +9,8 @@ hooklib_lib = static_library( sources : [ 'config.c', 'config.h', + 'createprocess.c', + 'createprocess.h', 'dll.c', 'dll.h', 'dns.c', From dca84e08d0973e9b77bdb81c327dd459359be577 Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Wed, 13 Sep 2023 19:57:10 -0400 Subject: [PATCH 4/6] hooklib: fix createprocess imports --- hooklib/createprocess.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hooklib/createprocess.c b/hooklib/createprocess.c index 1b1ebad..9e6ea7c 100644 --- a/hooklib/createprocess.c +++ b/hooklib/createprocess.c @@ -7,6 +7,9 @@ #include "hook/table.h" +#include "util/dprintf.h" + +void createprocess_hook_init(); static BOOL WINAPI my_CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, From 0d839770738b5ed589497643a23da4746565f2c8 Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Wed, 13 Sep 2023 20:23:40 -0400 Subject: [PATCH 5/6] hooklib: fill out my_CreateProcessA --- hooklib/createprocess.c | 142 ++++++++++++++++++++++++++++++---------- hooklib/createprocess.h | 16 +++-- 2 files changed, 119 insertions(+), 39 deletions(-) diff --git a/hooklib/createprocess.c b/hooklib/createprocess.c index 9e6ea7c..656487c 100644 --- a/hooklib/createprocess.c +++ b/hooklib/createprocess.c @@ -7,6 +7,8 @@ #include "hook/table.h" +#include "hooklib/createprocess.h" + #include "util/dprintf.h" void createprocess_hook_init(); @@ -76,18 +78,80 @@ static const struct hook_symbol win32_hooks[] = { static bool did_init = false; -static struct process_hook_sym_w *processe_syms_w; -static struct process_hook_sym_a *processe_syms_a; +static struct process_hook_sym_w *process_syms_w; +static struct process_hook_sym_a *process_syms_a; -static size_t processe_nsyms_a = 0; -static size_t processe_nsyms_w = 0; +static size_t process_nsyms_a = 0; +static size_t process_nsyms_w = 0; + +static CRITICAL_SECTION createproc_lock; + +HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail) { + struct process_hook_sym_w *new_mem; + struct process_hook_sym_w *new_proc; + HRESULT hr; + + assert(name != NULL); + assert(head != NULL); -void createprocess_push_hook_w(const wchar_t *name, const wchar_t *dll_name, const wchar_t *tail) { createprocess_hook_init(); + EnterCriticalSection(&createproc_lock); + + new_mem = realloc( + process_syms_w, + (process_nsyms_w + 1) * sizeof(struct process_hook_sym_w)); + + if (new_mem == NULL) { + + LeaveCriticalSection(&createproc_lock); + return E_OUTOFMEMORY; + } + + new_proc = &new_mem[process_nsyms_w]; + memset(new_proc, 0, sizeof(*new_proc)); + new_proc->name = name; + new_proc->head = head; + new_proc->tail = tail; + + process_syms_w = new_mem; + process_nsyms_w++; + + LeaveCriticalSection(&createproc_lock); + return S_OK; } -void createprocess_push_hook_a(const char *name, const char *dll_name, const char *tail) { +HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail) { + struct process_hook_sym_a *new_mem; + struct process_hook_sym_a *new_proc; + + assert(name != NULL); + assert(head != NULL); + createprocess_hook_init(); + + EnterCriticalSection(&createproc_lock); + + new_mem = realloc( + process_syms_a, + (process_nsyms_a + 1) * sizeof(struct process_hook_sym_a)); + + if (new_mem == NULL) { + + LeaveCriticalSection(&createproc_lock); + return E_OUTOFMEMORY; + } + + new_proc = &new_mem[process_nsyms_a]; + memset(new_proc, 0, sizeof(*new_proc)); + new_proc->name = name; + new_proc->head = head; + new_proc->tail = tail; + + process_syms_a = new_mem; + process_nsyms_a++; + + LeaveCriticalSection(&createproc_lock); + return S_OK; } void createprocess_hook_init() { @@ -101,7 +165,7 @@ void createprocess_hook_init() { "kernel32.dll", win32_hooks, _countof(win32_hooks)); - + InitializeCriticalSection(&createproc_lock); dprintf("CreateProcess: Init\n"); } @@ -119,37 +183,45 @@ static BOOL WINAPI my_CreateProcessA( LPPROCESS_INFORMATION lpProcessInformation ) { - if (strncmp(".\\15312firm\\firmupdate_1113.exe", lpCommandLine, 31)) { + for (int i = 0; i < process_nsyms_a; i++) { + if (strncmp(process_syms_a->name, lpCommandLine, strlen(process_syms_a->name))) { + continue; + } + + dprintf("CreateProcess: Hooking child process %s\n", lpCommandLine); + char new_cmd[MAX_PATH]; + strcat_s(new_cmd, MAX_PATH, process_syms_a->head); + strcat_s(new_cmd, MAX_PATH, lpCommandLine); + + if (process_syms_a->tail[0]) { + strcat_s(new_cmd, MAX_PATH, process_syms_a->tail); + } + return next_CreateProcessA( - lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation - ); + lpApplicationName, + new_cmd, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); } - - dprintf("CreateProcess: Hooking child process %s\n", lpCommandLine); - char new_cmd[MAX_PATH] = "inject -d -k carolhook.dll "; - strcat_s(new_cmd, MAX_PATH, lpCommandLine); - return next_CreateProcessA( - lpApplicationName, - new_cmd, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation - ); + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); } BOOL my_CreateProcessW( diff --git a/hooklib/createprocess.h b/hooklib/createprocess.h index fdbaa9b..aedd9b6 100644 --- a/hooklib/createprocess.h +++ b/hooklib/createprocess.h @@ -1,14 +1,22 @@ -void createprocess_push_hook_w(); -void createprocess_push_hook_a(); +#include + +HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail); +HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail); struct process_hook_sym_w { const wchar_t *name; - const wchar_t *dll_name; + size_t name_size; + const wchar_t *head; + size_t head_size; const wchar_t *tail; + size_t tail_size; }; struct process_hook_sym_a { const char *name; - const char *dll_name; + size_t name_size; + const char *head; + size_t head_size; const char *tail; + size_t tail_size; }; \ No newline at end of file From 157f52da4cbe2dd0875a8c4ef018a668d1e734cd Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Fri, 15 Sep 2023 01:35:33 -0400 Subject: [PATCH 6/6] platform: add epay hook --- hooklib/createprocess.c | 7 +- hooklib/createprocess.h | 2 + platform/config.c | 9 ++ platform/config.h | 2 + platform/epay.c | 335 ++++++++++++++++++++++++++++++++++++++++ platform/epay.h | 63 ++++++++ platform/meson.build | 2 + platform/platform.c | 7 + platform/platform.h | 2 + 9 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 platform/epay.c create mode 100644 platform/epay.h diff --git a/hooklib/createprocess.c b/hooklib/createprocess.c index 656487c..d411aaf 100644 --- a/hooklib/createprocess.c +++ b/hooklib/createprocess.c @@ -188,15 +188,16 @@ static BOOL WINAPI my_CreateProcessA( continue; } - dprintf("CreateProcess: Hooking child process %s\n", lpCommandLine); - char new_cmd[MAX_PATH]; + dprintf("CreateProcess: Hooking child process %s %s\n", lpApplicationName, lpCommandLine); + char new_cmd[MAX_PATH] = {0}; strcat_s(new_cmd, MAX_PATH, process_syms_a->head); strcat_s(new_cmd, MAX_PATH, lpCommandLine); - if (process_syms_a->tail[0]) { + if (process_syms_a->tail != NULL) { strcat_s(new_cmd, MAX_PATH, process_syms_a->tail); } + dprintf("CreateProcess: Replaced CreateProcessA %s\n", new_cmd); return next_CreateProcessA( lpApplicationName, new_cmd, diff --git a/hooklib/createprocess.h b/hooklib/createprocess.h index aedd9b6..93ed8f7 100644 --- a/hooklib/createprocess.h +++ b/hooklib/createprocess.h @@ -1,3 +1,5 @@ +#pragma once + #include HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail); diff --git a/platform/config.c b/platform/config.c index 1c6be62..93bc73e 100644 --- a/platform/config.c +++ b/platform/config.c @@ -13,6 +13,7 @@ #include "platform/clock.h" #include "platform/config.h" #include "platform/dns.h" +#include "platform/epay.h" #include "platform/hwmon.h" #include "platform/hwreset.h" #include "platform/misc.h" @@ -30,6 +31,7 @@ void platform_config_load(struct platform_config *cfg, const wchar_t *filename) amvideo_config_load(&cfg->amvideo, filename); clock_config_load(&cfg->clock, filename); dns_config_load(&cfg->dns, filename); + epay_config_load(&cfg->epay, filename); hwmon_config_load(&cfg->hwmon, filename); hwreset_config_load(&cfg->hwreset, filename); misc_config_load(&cfg->misc, filename); @@ -317,3 +319,10 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename) filename); } +void epay_config_load(struct epay_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + cfg->enable = GetPrivateProfileIntW(L"epay", L"enable", 1, filename); +} diff --git a/platform/config.h b/platform/config.h index 7ece41d..93df65a 100644 --- a/platform/config.h +++ b/platform/config.h @@ -9,6 +9,7 @@ #include "platform/amvideo.h" #include "platform/clock.h" #include "platform/dns.h" +#include "platform/epay.h" #include "platform/hwmon.h" #include "platform/hwreset.h" #include "platform/misc.h" @@ -25,6 +26,7 @@ void platform_config_load( void amvideo_config_load(struct amvideo_config *cfg, const wchar_t *filename); void clock_config_load(struct clock_config *cfg, const wchar_t *filename); void dns_config_load(struct dns_config *cfg, const wchar_t *filename); +void epay_config_load(struct epay_config *cfg, const wchar_t *filename); void hwmon_config_load(struct hwmon_config *cfg, const wchar_t *filename); void hwreset_config_load(struct hwreset_config *cfg, const wchar_t *filename); void misc_config_load(struct misc_config *cfg, const wchar_t *filename); diff --git a/platform/epay.c b/platform/epay.c new file mode 100644 index 0000000..0faf145 --- /dev/null +++ b/platform/epay.c @@ -0,0 +1,335 @@ +#include + +#include +#include +#include +#include + +#include "hook/table.h" + +#include "hooklib/reg.h" + +#include "platform/epay.h" + +#include "util/dprintf.h" + +static HRESULT misc_read_thinca_adapter(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_ca_loc(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_ca_client_loc(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_network_timeout(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_pattern0(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_network_timeout0(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_pattern1(void *bytes, uint32_t *nbytes); +static HRESULT misc_read_network_timeout1(void *bytes, uint32_t *nbytes); + +static uint64_t thinca_initialize(struct thinca_impl * self, uint64_t val); +static uint64_t thinca_dispose(struct thinca_impl * self); +static uint64_t thinca_set_resource(struct thinca_impl * self, char * res); +static uint64_t thinca_set_pay_log(struct thinca_impl * self, uint64_t val, char * log, uint64_t val2, const char * size_lim); +static uint64_t thinca_set_client_log(struct thinca_impl * self, uint64_t val, char * log); +static uint64_t thinca_set_client_cfg(struct thinca_impl * self, char * log, uint64_t val); +static uint64_t thinca_set_goods_code(struct thinca_impl * self, char * code); +static uint64_t thinca_set_evt_handler(struct thinca_impl * self, void* handler); +static uint64_t thinca_set_cert(struct thinca_impl * self, char * cert, uint64_t val); +static uint64_t thinca_set_serial(struct thinca_impl * self, char * cert); +static uint64_t thinca_check_deal(struct thinca_impl * self, void* deal); +static uint64_t thinca_cancel(struct thinca_impl * self); +static uint64_t thinca_select(struct thinca_impl * self); +static uint64_t thinca_unk(struct thinca_impl * self, uint64_t val); +static void thinca_unk8(struct thinca_impl * self); + +static uint64_t my_ThincaPaymentGetVersion(); +static uint64_t (*next_ThincaPaymentGetVersion)(); + +static struct thinca_main* my_ThincaPaymentGetInstance(uint64_t ver); +static struct thinca_main* (*next_ThincaPaymentGetInstance)(uint64_t ver); + +static struct thinca_main* thinca_stub; + +static const struct reg_hook_val epay_adapter_keys[] = { + { + .name = L"TfpsAimeRwAdapter", + .read = misc_read_thinca_adapter, + .type = REG_SZ, + } +}; + +static const struct reg_hook_val epay_tcap_keys[] = { + { + .name = L"CaLocation", + .read = misc_read_ca_loc, + .type = REG_SZ, + }, + { + .name = L"ThincaTcapClientPath", + .read = misc_read_ca_client_loc, + .type = REG_SZ, + }, + { + .name = L"ClientNetworkTimeout", + .read = misc_read_network_timeout, + .type = REG_DWORD, + } +}; + +static const struct reg_hook_val epay_tcap_url0_keys[] = { + { + .name = L"Pattern", + .read = misc_read_pattern0, + .type = REG_SZ, + }, + { + .name = L"ClientNetworkTimeout", + .read = misc_read_network_timeout0, + .type = REG_DWORD, + } +}; + +static const struct reg_hook_val epay_tcap_url1_keys[] = { + { + .name = L"Pattern", + .read = misc_read_pattern1, + .type = REG_SZ, + }, + { + .name = L"ClientNetworkTimeout", + .read = misc_read_network_timeout1, + .type = REG_DWORD, + } +}; + +static const struct hook_symbol epay_syms[] = { + { + .name = "ThincaPaymentGetVersion", + .patch = my_ThincaPaymentGetVersion, + .link = (void **) &next_ThincaPaymentGetVersion, + .ordinal = 1, + }, + { + .name = "__imp_ThincaPaymentGetInstance", + .patch = my_ThincaPaymentGetInstance, + .link = (void **) &next_ThincaPaymentGetInstance, + .ordinal = 2, + }, + { + .name = "ThincaPaymentGetInstance", + .patch = my_ThincaPaymentGetInstance, + .link = (void **) &next_ThincaPaymentGetInstance, + .ordinal = 2, + } +}; + +HRESULT epay_hook_init(const struct epay_config *cfg) { + HRESULT hr; + assert(cfg != NULL); + + if (!cfg->enable) { + return S_FALSE; + } + + hr = reg_hook_push_key( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\TFPaymentService\\ThincaRwAdapter", + epay_adapter_keys, + _countof(epay_adapter_keys)); + + if (FAILED(hr)) { + return hr; + } + + hr = reg_hook_push_key( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\TFPaymentService\\ThincaTcapClient", + epay_tcap_keys, + _countof(epay_tcap_keys)); + + if (FAILED(hr)) { + return hr; + } + + hr = reg_hook_push_key( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\TFPaymentService\\ThincaTcapClient\\URL0", + epay_tcap_url0_keys, + _countof(epay_tcap_url0_keys)); + + if (FAILED(hr)) { + return hr; + } + + hr = reg_hook_push_key( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\TFPaymentService\\ThincaTcapClient\\URL1", + epay_tcap_url1_keys, + _countof(epay_tcap_url1_keys)); + + hook_table_apply( + NULL, + "ThincaPayment.dll", + epay_syms, + _countof(epay_syms)); + + thinca_stub = (struct thinca_main *)malloc(sizeof(struct thinca_main)); + thinca_stub->impl1 = (struct thinca_impl *)malloc(sizeof(struct thinca_impl)); + + thinca_stub->impl1->unk8 = thinca_unk8; + thinca_stub->impl1->initialize = thinca_initialize; + thinca_stub->impl1->dispose = thinca_dispose; + thinca_stub->impl1->setResource = thinca_set_resource; + thinca_stub->impl1->setThincaPaymentLog = thinca_set_pay_log; + thinca_stub->impl1->setThincaEventInterface = thinca_set_evt_handler; + thinca_stub->impl1->setIcasClientLog = thinca_set_client_log; + thinca_stub->impl1->setIcasClientConfig = thinca_set_client_cfg; + thinca_stub->impl1->setGoodsCode = thinca_set_goods_code; + thinca_stub->impl1->setTerminalSerial = thinca_set_serial; + thinca_stub->impl1->setClientCertificate = thinca_set_cert; + thinca_stub->impl1->checkDeal = thinca_check_deal; + thinca_stub->impl1->cancelRequest = thinca_cancel; + thinca_stub->impl1->selectButton = thinca_select; + thinca_stub->impl1->unk220 = thinca_unk; + thinca_stub->impl1->unk228 = thinca_unk; + + dprintf("Epay: Init\n"); + + return hr; +} + +static HRESULT misc_read_thinca_adapter(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"aime_rw_adapterMD.dll"); +} + +static HRESULT misc_read_ca_loc(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"ca.pem"); +} + +static HRESULT misc_read_ca_client_loc(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"thincatcapclient.dll"); +} + +static HRESULT misc_read_network_timeout(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_u32(bytes, nbytes, 20000); +} + +static HRESULT misc_read_pattern0(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L".*\\.jsp"); +} + +static HRESULT misc_read_network_timeout0(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_u32(bytes, nbytes, 5000); +} + +static HRESULT misc_read_pattern1(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L".*(closing|remove).*"); +} + +static HRESULT misc_read_network_timeout1(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_u32(bytes, nbytes, 60000); +} + +static uint64_t thinca_initialize(struct thinca_impl * self, uint64_t val) +{ + dprintf("Epay: Thinca Initialize %lld\n", val); + return 0; +} + +static uint64_t thinca_dispose(struct thinca_impl * self) +{ + dprintf("Epay: Thinca Dispose\n"); + return 0; +} + +static uint64_t thinca_set_resource(struct thinca_impl * self, char * res) +{ + dprintf("Epay: Thinca Set Resource %s\n", res); + return 0; +} + +static uint64_t thinca_set_pay_log(struct thinca_impl * self, uint64_t val, char * log, uint64_t val2, const char * size_lim) +{ + dprintf("Epay: Thinca Set Paylog %lld | %s | %lld | %s\n", val, log, val2, size_lim); + return 0; +} + +static uint64_t thinca_set_client_log(struct thinca_impl * self, uint64_t val, char * log) +{ + dprintf("Epay: Thinca Set ICAS Client log %lld | %s\n", val, log); + return 0; +} + +static uint64_t thinca_set_client_cfg(struct thinca_impl * self, char * log, uint64_t val) +{ + dprintf("Epay: Thinca Set ICAS Client Config %s | %lld\n", log, val); + return 0; +} + +static uint64_t thinca_set_goods_code(struct thinca_impl * self, char * code) +{ + dprintf("Epay: Thinca Set Goods Code %s\n", code); + return 0; +} + +static uint64_t thinca_set_evt_handler(struct thinca_impl * self, void* handler) +{ + dprintf("Epay: Thinca Set Event Handler %p\n", handler); + return 0; +} + +static uint64_t thinca_set_cert(struct thinca_impl * self, char * cert, uint64_t val) +{ + dprintf("Epay: Thinca Set Client Cert %s | %lld\n", cert, val); + return 0; +} + +static uint64_t thinca_set_serial(struct thinca_impl * self, char * cert) +{ + dprintf("Epay: Thinca Set Terminal Serial %s\n", cert); + return 0; +} + +static uint64_t thinca_check_deal(struct thinca_impl * self, void* deal) +{ + dprintf("Epay: Thinca Check Deal %p\n", deal); + return 0; +} + +static uint64_t thinca_cancel(struct thinca_impl * self) +{ + dprintf("Epay: Thinca Cancel\n"); + return 0; +} + +static uint64_t thinca_select(struct thinca_impl * self) +{ + dprintf("Epay: Thinca Select\n"); + return 0; +} + +static uint64_t thinca_unk(struct thinca_impl * self, uint64_t val) +{ + dprintf("Epay: Thinca Unknown 220/228 %lld\n", val); + return 0; +} + +static void thinca_unk8(struct thinca_impl * self) +{ + dprintf("Epay: Thinca Unknown 8\n"); +} + +static uint64_t my_ThincaPaymentGetVersion() +{ + return 0x1040B00; +} + +static struct thinca_main* my_ThincaPaymentGetInstance(uint64_t ver) +{ + dprintf("Epay: my_ThincaPaymentGetInstance hit!\n"); + return thinca_stub; +} \ No newline at end of file diff --git a/platform/epay.h b/platform/epay.h new file mode 100644 index 0000000..c94eceb --- /dev/null +++ b/platform/epay.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +#pragma pack(push,1) +struct epay_config { + bool enable; +}; + +/* The functions in these structs are how clients like amdaemon interface + * with thinca. We can simply replace these functions with our own stubs + * to bypass errors and such. Currently this DOES NOT allow for epay, and + * trying to do so will most likely just lead to misery. My goal isn't to + * reimplement epay, just to give amdaemon SOMETHING so we can boot properly. + */ +struct thinca_impl { + uint64_t* unk0; + void (*unk8)(struct thinca_impl *); + uint64_t (*initialize)(struct thinca_impl *, uint64_t); + uint64_t (*dispose)(struct thinca_impl *); + uint64_t (*setResource)(struct thinca_impl *, char *); + uint64_t (*setThincaPaymentLog)(struct thinca_impl *, uint64_t, char *, uint64_t, const char *); + uint64_t (*setIcasClientLog)(struct thinca_impl *, uint64_t, char *); + uint64_t (*setIcasClientConfig)(struct thinca_impl *, char *, uint64_t); + uint64_t* unk40; + uint64_t* unk48; + uint64_t (*setClientCertificate)(struct thinca_impl *, char *, uint64_t); + uint64_t (*setTerminalSerial)(struct thinca_impl *, char *); + uint64_t (*setGoodsCode)(struct thinca_impl *, char *); + uint64_t unk68; + uint64_t (*setThincaEventInterface)(struct thinca_impl *, void*); // probably a struct + uint64_t unkGap78[7]; + uint64_t (*checkDeal)(struct thinca_impl *, void *); // probably a struct + uint64_t unkGapB8[41]; + uint64_t (*cancelRequest)(struct thinca_impl *); + uint64_t (*selectButton)(struct thinca_impl *); + uint64_t unkGap210[2]; + uint64_t (*unk220)(struct thinca_impl *, uint64_t); + uint64_t (*unk228)(struct thinca_impl *, uint64_t); +}; + +/* I believe the actual struct is 0x310 bytes, so for now I'm just + * implementing what I need and hoping the rest don't cause issues + * later. AMDaemon seems to only care about impl1 and deal_thing, + * at least from what I can tell + */ +struct thinca_main { + struct thinca_impl* impl1; + struct thinca_impl* impl2; + HANDLE* mutex1; + HANDLE* mutex2; + HANDLE* mutex3; + uint64_t* unk28; + uint64_t* unk30; + uint64_t* unk38; + uint64_t* unk40; + uint64_t* deal_thing; + uint64_t filler[88]; +}; + +#pragma pack(pop) +HRESULT epay_hook_init(const struct epay_config *cfg); \ No newline at end of file diff --git a/platform/meson.build b/platform/meson.build index 4f0fbc9..a3e1fe5 100644 --- a/platform/meson.build +++ b/platform/meson.build @@ -16,6 +16,8 @@ platform_lib = static_library( 'config.h', 'dns.c', 'dns.h', + 'epay.c', + 'epay.h', 'hwmon.c', 'hwmon.h', 'hwreset.c', diff --git a/platform/platform.c b/platform/platform.c index 218204c..bf44800 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -5,6 +5,7 @@ #include "platform/amvideo.h" #include "platform/clock.h" #include "platform/dns.h" +#include "platform/epay.h" #include "platform/hwmon.h" #include "platform/misc.h" #include "platform/netenv.h" @@ -80,5 +81,11 @@ HRESULT platform_hook_init( return hr; } + hr = epay_hook_init(&cfg->epay); + + if (FAILED(hr)) { + return hr; + } + return S_OK; } diff --git a/platform/platform.h b/platform/platform.h index 69c65e2..def496c 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -5,6 +5,7 @@ #include "platform/amvideo.h" #include "platform/clock.h" #include "platform/dns.h" +#include "platform/epay.h" #include "platform/hwmon.h" #include "platform/hwreset.h" #include "platform/misc.h" @@ -17,6 +18,7 @@ struct platform_config { struct amvideo_config amvideo; struct clock_config clock; struct dns_config dns; + struct epay_config epay; struct hwmon_config hwmon; struct hwreset_config hwreset; struct misc_config misc;