From e86346f837d58c78488e3f2bb480a344d669718d Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Fri, 8 Dec 2023 13:29:37 -0500 Subject: [PATCH] add epay hooks --- platform/config.c | 8 +- platform/config.h | 5 +- platform/epay.c | 335 ++++++++++++++++++++++++++++++++++++++ platform/epay.h | 63 +++++++ platform/meson.build | 2 + platform/platform.c | 6 + platform/platform.h | 2 + saohook/unity.c | 9 +- subprojects/capnhook.wrap | 4 +- 9 files changed, 426 insertions(+), 8 deletions(-) create mode 100644 platform/epay.c create mode 100644 platform/epay.h diff --git a/platform/config.c b/platform/config.c index 2e89872..5f9d2dd 100644 --- a/platform/config.c +++ b/platform/config.c @@ -31,6 +31,7 @@ void platform_config_load(struct platform_config *cfg, const wchar_t *filename) jvs_config_load(&cfg->jvs, filename); misc_config_load(&cfg->misc, filename); es3sec_config_load(&cfg->dongle, filename); + epay_config_load(&cfg->epay, filename); } void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename) @@ -236,4 +237,9 @@ void es3sec_config_load(struct es3sec_config *cfg, const wchar_t *filename) cfg->serial, _countof(cfg->serial), filename); -} \ No newline at end of file +} + +void epay_config_load(struct epay_config *cfg, const wchar_t *filename) +{ + cfg->enable = GetPrivateProfileIntW(L"dongle", L"enable", 1, filename); +} diff --git a/platform/config.h b/platform/config.h index 5a50f73..3868e1e 100644 --- a/platform/config.h +++ b/platform/config.h @@ -14,6 +14,7 @@ #include "platform/dns.h" #include "platform/misc.h" #include "platform/es3sec.h" +#include "platform/epay.h" void platform_config_load( struct platform_config *cfg, @@ -33,4 +34,6 @@ void jvs_config_load(struct jvs_config *cfg, const wchar_t *filename); void misc_config_load(struct misc_config *cfg, const wchar_t *filename); -void es3sec_config_load(struct es3sec_config *cfg, const wchar_t *filename); \ No newline at end of file +void es3sec_config_load(struct es3sec_config *cfg, const wchar_t *filename); + +void epay_config_load(struct epay_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 e5805af..45cb228 100644 --- a/platform/meson.build +++ b/platform/meson.build @@ -15,6 +15,8 @@ platform_lib = static_library( sources : [ 'platform.c', 'platform.h', + 'epay.c', + 'epay.h', 'config.c', 'config.h', 'locale.c', diff --git a/platform/platform.c b/platform/platform.c index 24afb78..4e9b8de 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -63,5 +63,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 050878d..5cc0262 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -8,6 +8,7 @@ #include "platform/misc.h" #include "platform/vfs.h" #include "platform/es3sec.h" +#include "platform/epay.h" struct dongle_info { USHORT pid; @@ -25,6 +26,7 @@ struct platform_config { struct misc_config misc; struct vfs_config vfs; struct es3sec_config dongle; + struct epay_config epay; }; enum platform_type { diff --git a/saohook/unity.c b/saohook/unity.c index 97d32e3..ad65147 100644 --- a/saohook/unity.c +++ b/saohook/unity.c @@ -3,9 +3,12 @@ #include #include "hook/table.h" +#include "hook/iohook.h" #include "hooklib/dll.h" #include "hooklib/path.h" +#include "hooklib/serial.h" + #include "amcus/amcus.h" #include "board/usio.h" @@ -27,12 +30,8 @@ static const struct hook_symbol unity_kernel32_syms[] = { static const wchar_t *target_modules[] = { L"mono.dll", L"cri_ware_unity.dll", - L"aime_rw_adapter.dll", - L"AMPFServiceClient.dll", L"bnAMPF.dll", - L"bnAMUpdater.dll", L"bnReader.dll", - L"libamw.dll", }; static const size_t target_modules_len = _countof(target_modules); @@ -98,6 +97,8 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) path_hook_insert_hooks(result); amcus_insert_hooks(result); usio_hook_proc_addr(result); + iohook_apply_hooks(result); + serial_hook_apply_hooks(result); } } diff --git a/subprojects/capnhook.wrap b/subprojects/capnhook.wrap index 00539a9..2f42bff 100644 --- a/subprojects/capnhook.wrap +++ b/subprojects/capnhook.wrap @@ -1,4 +1,4 @@ [wrap-git] directory = capnhook -url = https://github.com/decafcode/capnhook -revision = f0e5f820288d33542dc222eb94f4b0221420dd4b \ No newline at end of file +url = https://github.com/Hay1tsme/capnhook +revision = 888d068d58e68cf702e0cee872959a71413a7b55 \ No newline at end of file