diff --git a/src/client/component/arxan.cpp b/src/client/component/arxan.cpp index 1df686a2..2e37504d 100644 --- a/src/client/component/arxan.cpp +++ b/src/client/component/arxan.cpp @@ -33,10 +33,6 @@ namespace arxan utils::hook::detour nt_query_system_information_hook; utils::hook::detour nt_query_information_process_hook; utils::hook::detour create_mutex_ex_a_hook; - utils::hook::detour get_window_text_a_hook; - utils::hook::detour get_window_text_w_hook; - utils::hook::detour get_class_name_a_hook; - utils::hook::detour get_class_name_w_hook; HANDLE create_mutex_ex_a_stub(const LPSECURITY_ATTRIBUTES attributes, const LPCSTR name, const DWORD flags, const DWORD access) @@ -116,45 +112,20 @@ namespace arxan return true; } - int WINAPI get_window_text_w_stub(const HWND wnd, const LPWSTR str, const int max_count) - { - const auto res = get_window_text_w_hook.invoke(wnd, str, max_count); - if (res) - { - remove_evil_keywords_from_string(str, res); - } - - return res; - } int WINAPI get_window_text_a_stub(const HWND wnd, const LPSTR str, const int max_count) { - const auto res = get_window_text_a_hook.invoke(wnd, str, max_count); + std::wstring wstr{}; + wstr.resize(max_count); + + const auto res = GetWindowTextW(wnd, &wstr[0], max_count); if (res) { - remove_evil_keywords_from_string(str, res); - } + remove_evil_keywords_from_string(wstr.data(), res); - return res; - } - - int WINAPI get_class_name_a_stub(const HWND wnd, const LPSTR class_name, const int max_count) - { - const auto res = get_class_name_a_hook.invoke(wnd, class_name, max_count); - if (res) - { - remove_evil_keywords_from_string(class_name, res); - } - - return res; - } - - int WINAPI get_class_name_w_stub(const HWND wnd, const LPWSTR class_name, const int max_count) - { - const auto res = get_class_name_w_hook.invoke(wnd, class_name, max_count); - if (res) - { - remove_evil_keywords_from_string(class_name, res); + const std::string regular_str(wstr.begin(), wstr.end()); + memset(str, 0, max_count); + memcpy(str, regular_str.data(), res); } return res; @@ -317,31 +288,36 @@ namespace arxan create_mutex_ex_a_hook.create(CreateMutexExA, create_mutex_ex_a_stub); + const utils::nt::library ntdll("ntdll.dll"); nt_close_hook.create(ntdll.get_proc("NtClose"), nt_close_stub); const auto nt_query_information_process = ntdll.get_proc("NtQueryInformationProcess"); nt_query_information_process_hook.create(nt_query_information_process, nt_query_information_process_stub); - utils::hook::move_hook(nt_query_information_process); const auto nt_query_system_information = ntdll.get_proc("NtQuerySystemInformation"); nt_query_system_information_hook.create(nt_query_system_information, nt_query_system_information_stub); - utils::hook::move_hook(nt_query_system_information); // Satisfy arxan + nt_query_system_information_hook.move(); - /*get_window_text_a_hook.create(GetWindowTextA, get_window_text_a_stub); - get_window_text_w_hook.create(GetWindowTextW, get_window_text_w_stub); - get_class_name_a_hook.create(GetClassNameA, get_class_name_a_stub); - get_class_name_w_hook.create(GetClassNameW, get_class_name_w_stub); - - // Satisfy arxan + utils::hook::copy(this->window_text_buffer_, GetWindowTextA, sizeof(this->window_text_buffer_)); + utils::hook::jump(GetWindowTextA, get_window_text_a_stub, true, true); utils::hook::move_hook(GetWindowTextA); - utils::hook::move_hook(GetWindowTextW); - utils::hook::move_hook(GetClassNameA); - utils::hook::move_hook(GetClassNameW);*/ AddVectoredExceptionHandler(1, exception_filter); } + + void pre_destroy() override + { + utils::hook::copy(GetWindowTextA, this->window_text_buffer_, sizeof(this->window_text_buffer_)); + nt_query_system_information_hook.clear(); + nt_query_information_process_hook.clear(); + nt_close_hook.clear(); + create_mutex_ex_a_hook.clear(); + } + + private: + uint8_t window_text_buffer_[15]{}; }; } diff --git a/src/common/utils/hook.cpp b/src/common/utils/hook.cpp index 3b89b471..39a94e02 100644 --- a/src/common/utils/hook.cpp +++ b/src/common/utils/hook.cpp @@ -109,13 +109,19 @@ namespace utils::hook this->clear(); } - void detour::enable() const + void detour::enable() { MH_EnableHook(this->place_); + + if (!this->moved_data_.empty()) + { + this->move(); + } } - void detour::disable() const + void detour::disable() { + this->un_move(); MH_DisableHook(this->place_); } @@ -141,11 +147,18 @@ namespace utils::hook { if (this->place_) { + this->un_move(); MH_RemoveHook(this->place_); } this->place_ = nullptr; this->original_ = nullptr; + this->moved_data_ = {}; + } + + void detour::move() + { + this->moved_data_ = move_hook(this->place_); } void* detour::get_original() const @@ -153,6 +166,14 @@ namespace utils::hook return this->original_; } + void detour::un_move() + { + if (!this->moved_data_.empty()) + { + copy(this->place_, this->moved_data_.data(), this->moved_data_.size()); + } + } + bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub) { if (!library.is_valid()) return false; @@ -309,27 +330,37 @@ namespace utils::hook return inject(reinterpret_cast(pointer), data); } - void move_hook(void* pointer) + std::vector move_hook(void* pointer) { + std::vector original_data{}; + auto* data_ptr = static_cast(pointer); if (data_ptr[0] == 0xE9) { + original_data.resize(6); + memmove(original_data.data(), pointer, original_data.size()); + auto* target = follow_branch(data_ptr); nop(data_ptr, 1); jump(data_ptr + 1, target); } else if (data_ptr[0] == 0xFF && data_ptr[1] == 0x25) { - copy(data_ptr + 1, data_ptr, 0x14); + original_data.resize(15); + memmove(original_data.data(), pointer, original_data.size()); + + copy(data_ptr + 1, data_ptr, 14); nop(data_ptr, 1); } else { throw std::runtime_error("No branch instruction found"); } + + return original_data; } - void move_hook(const size_t pointer) + std::vector move_hook(const size_t pointer) { return move_hook(reinterpret_cast(pointer)); } diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp index bdaadcf3..22174664 100644 --- a/src/common/utils/hook.hpp +++ b/src/common/utils/hook.hpp @@ -99,13 +99,15 @@ namespace utils::hook { if (this != &other) { - this->~detour(); + this->clear(); this->place_ = other.place_; this->original_ = other.original_; + this->moved_data_ = other.moved_data_; other.place_ = nullptr; other.original_ = nullptr; + other.moved_data_ = {}; } return *this; @@ -114,13 +116,15 @@ namespace utils::hook detour(const detour&) = delete; detour& operator=(const detour&) = delete; - void enable() const; - void disable() const; + void enable(); + void disable(); void create(void* place, void* target); void create(size_t place, void* target); void clear(); + void move(); + template T* get() const { @@ -136,8 +140,11 @@ namespace utils::hook [[nodiscard]] void* get_original() const; private: + std::vector moved_data_{}; void* place_{}; void* original_{}; + + void un_move(); }; bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub); @@ -163,8 +170,8 @@ namespace utils::hook void inject(void* pointer, const void* data); void inject(size_t pointer, const void* data); - void move_hook(void* pointer); - void move_hook(size_t pointer); + std::vector move_hook(void* pointer); + std::vector move_hook(size_t pointer); template T extract(void* address)