diff --git a/src/main/hook/patch/hasp.c b/src/main/hook/patch/hasp.c index a90177e..33acbb2 100644 --- a/src/main/hook/patch/hasp.c +++ b/src/main/hook/patch/hasp.c @@ -17,12 +17,24 @@ static const uint8_t patch_hasp_id_sig[] = { 0xC7, 0x44, 0x24, 0x10 }; +static const uint8_t patch_hasp_get_session_info_sig[] = { + 0x55, 0x57, 0x56, 0x53, + 0x83, 0xEC, 0x3C, 0xE8, + 0x00, 0x00, 0x00, 0x00, + 0x5B, 0x81, 0xC3, 0x98, + 0xA2, 0x10, 0x00, 0xBE, + 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x7C, 0x24, 0x50, + 0x8B, 0x44, 0x24, 0x54 +}; + void patch_hasp_init(const uint8_t* key_data, size_t len) { void* func_api_login; void* func_api_logout; void* func_api_decrypt; void* func_api_getid; + void* func_api_get_session_info; func_api_login = util_patch_find_signiture(patch_hasp_login_sig, sizeof(patch_hasp_login_sig), -16, (void*) 0x80c0000, (void*) 0x80f0000, @@ -52,10 +64,27 @@ void patch_hasp_init(const uint8_t* key_data, size_t len) log_debug("ApiGetid at %p", func_api_getid); + func_api_get_session_info = util_patch_find_signiture( + patch_hasp_get_session_info_sig, + sizeof(patch_hasp_get_session_info_sig), + 0, + (void*) 0x8060000, + (void*) 0x80F0000, + 16); + + if (!func_api_get_session_info) { + log_error("Could not find ApiGetSessionInfo address"); + return; + } + + log_debug("ApiGetSessionInfo at %p", func_api_get_session_info); + util_patch_function((uintptr_t) func_api_login, sec_hasp_api_login); util_patch_function((uintptr_t) func_api_logout, sec_hasp_api_logout); util_patch_function((uintptr_t) func_api_decrypt, sec_hasp_api_decrypt); util_patch_function((uintptr_t) func_api_getid, sec_hasp_api_getid); + util_patch_function((uintptr_t) func_api_get_session_info, + sec_hasp_api_get_session_info); sec_hasp_init(key_data, len); diff --git a/src/main/sec/hasp/old/hasp.c b/src/main/sec/hasp/old/hasp.c index b365255..d7901fa 100644 --- a/src/main/sec/hasp/old/hasp.c +++ b/src/main/sec/hasp/old/hasp.c @@ -18,6 +18,7 @@ struct sec_hasp_key_table { /* static const uint32_t sec_hasp_features[] = {2, 3001}; */ static const uint32_t sec_hasp_key_id = 0xDEADBEEF; static struct sec_hasp_key_table sec_hasp_keys; +static uint32_t sec_hasp_buffer_leak_count; void sec_hasp_init(const uint8_t* key_data, size_t len) { @@ -57,6 +58,30 @@ unsigned int sec_hasp_api_getid(void) return sec_hasp_key_id; } +int sec_hasp_api_get_session_info(int handle, const char* format, char** info) +{ + log_debug("get session info, handle 0x%X, format %s", handle, format); + + // The string to be returned should be in some XML format. However, the + // game is just using strstr to check for the following substring + // Furthermore, memory leaking the returned *info buffer as well as not + // knowing if other versions are actually freeing this using the correct + // free method of the hasp API. + // Since this function is not called a lot, i guess letting it leak is the + // most pragmatic solution. Let's keep track of that anyway and print + // some warnings once we reach quite a number of leaked buffers to not + // lose visibility if something bad ever happens + *info = util_str_dup("p id 322376503"); // 0x13371337 + + // Assuming the above buffers with alignment and some metadata needs + // ~32 bytes -> 1 MB = 32768 -> ~10 MB = 327680 + if (++sec_hasp_buffer_leak_count >= 327680) { + log_warn("Memory leakage for unmanaged buffer exceeds 10 MB"); + } + + return 0; +} + int sec_hasp_api_decrypt(int handle, void* buffer, size_t length) { char* buf; diff --git a/src/main/sec/hasp/old/hasp.h b/src/main/sec/hasp/old/hasp.h index 582ae0c..48781a0 100644 --- a/src/main/sec/hasp/old/hasp.h +++ b/src/main/sec/hasp/old/hasp.h @@ -30,6 +30,8 @@ int sec_hasp_api_logout(int handle); unsigned int sec_hasp_api_getid(void); +int sec_hasp_api_get_session_info(int handle, const char* format, char** info); + int sec_hasp_api_decrypt(int handle, void* buffer, size_t length); #endif \ No newline at end of file