From 54c7da0d9e1933932d357d0802a8e691b005388a Mon Sep 17 00:00:00 2001 From: Vic P Date: Tue, 7 Nov 2023 01:51:54 +0700 Subject: [PATCH] Vutils --- Test/Sample.IATHooking.h | 12 ++- Test/Sample.INLHooking.h | 10 +-- include/Vutils.h | 83 +++++++++----------- src/details/apihookiat.cpp | 153 +++++++++++++++++++++---------------- 4 files changed, 139 insertions(+), 119 deletions(-) diff --git a/Test/Sample.IATHooking.h b/Test/Sample.IATHooking.h index 27226fd..fe97f14 100644 --- a/Test/Sample.IATHooking.h +++ b/Test/Sample.IATHooking.h @@ -22,14 +22,18 @@ int WINAPI HfnMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uTy DEF_SAMPLE(IATHooking) { - VU_API_IAT_OVERRIDE(Test.exe, user32.dll, MessageBoxA); - VU_API_IAT_OVERRIDE(Test.exe, user32.dll, MessageBoxW); + vu::Process process; + process.attach(GetCurrentProcess()); + auto process_name = process.name(); + + vu::IATHooking::instance().install(process_name, ts("user32.dll"), ts("MessageBoxA"), HfnMessageBoxA, (void**)&pfnMessageBoxA); + vu::IATHooking::instance().install(process_name, ts("user32.dll"), ts("MessageBoxW"), HfnMessageBoxW, (void**)&pfnMessageBoxW); MessageBoxA(vu::get_console_window(), "The first message.", "A", MB_OK); MessageBoxW(vu::get_console_window(), L"The first message.", L"W", MB_OK); - VU_API_IAT_RESTORE(Test.exe, user32.dll, MessageBoxA); - VU_API_IAT_RESTORE(Test.exe, user32.dll, MessageBoxW); + vu::IATHooking::instance().uninstall(process_name, ts("user32.dll"), ts("MessageBoxA"), (void**)&pfnMessageBoxA); + vu::IATHooking::instance().uninstall(process_name, ts("user32.dll"), ts("MessageBoxW"), (void**)&pfnMessageBoxW); MessageBoxA(vu::get_console_window(), "The second message.", "A", MB_OK); MessageBoxW(vu::get_console_window(), L"The second message.", L"W", MB_OK); diff --git a/Test/Sample.INLHooking.h b/Test/Sample.INLHooking.h index 1013a7c..cda042f 100644 --- a/Test/Sample.INLHooking.h +++ b/Test/Sample.INLHooking.h @@ -17,16 +17,16 @@ DEF_SAMPLE(INLHooking) { vu::INLHooking inl[2]; - VU_API_INL_OVERRIDE(inl[0], user32.dll, MessageBoxA); - VU_API_INL_OVERRIDE(inl[1], user32.dll, MessageBoxW); + inl[0].install(ts("user32.dll"), ts("MessageBoxA"), HfnMessageBoxA, (void**)&pfnMessageBoxA); + inl[1].install(ts("user32.dll"), ts("MessageBoxW"), HfnMessageBoxW, (void**)&pfnMessageBoxW); MessageBoxA(vu::get_console_window(), "The first message.", "A", MB_OK); MessageBoxW(vu::get_console_window(), L"The first message.", L"W", MB_OK); - VU_API_INL_RESTORE(inl[0], user32.dll, MessageBoxA); - VU_API_INL_RESTORE(inl[1], user32.dll, MessageBoxW); + inl[0].uninstall(ts("user32.dll"), ts("MessageBoxA"), (void**)&pfnMessageBoxA); + inl[1].uninstall(ts("user32.dll"), ts("MessageBoxW"), (void**)&pfnMessageBoxW); - MessageBoxA(vu::get_console_window(), "The second message.", "A", MB_OK); + MessageBoxA(vu::get_console_window(), "The second message.", "A", MB_OK); MessageBoxW(vu::get_console_window(), L"The second message.", L"W", MB_OK); return vu::VU_OK; diff --git a/include/Vutils.h b/include/Vutils.h index 876154c..5017b8f 100644 --- a/include/Vutils.h +++ b/include/Vutils.h @@ -1436,18 +1436,6 @@ class AsyncSocket : public LastError * API Hooking - Inline */ - /** - * @brief Hook/Unhook a function in a module by name. - * @define The prefix of redirection function must be : Hfn - * @define The prefix of real function pointer must be : pfn - * @param[in] O The INLHooking instance. - * @param[in] M The module name. - * @param[in] F The function name. - * @return true if the function succeeds. Otherwise false. - */ -#define VU_API_INL_OVERRIDE(O, M, F) O.install(ts( # M ), ts( # F ), (void*)&Hfn ## F, (void**)&pfn ## F) -#define VU_API_INL_RESTORE(O, M, F) O.uninstall(ts( # M ), ts( # F ), (void**)&pfn ## F) - enum class memory_address_type { MAT_NONE = 0, @@ -1551,21 +1539,28 @@ class INLHookingW: public INLHookingX * API Hooking - IAT */ -#define VU_API_IAT_OVERRIDE(O, M, F)\ - vu::IATHooking::instance().install(\ - _T( # O ), _T( # M ), _T( # F ),\ - (const void*)(reinterpret_cast(&Hfn ## F)),\ - (const void**)(reinterpret_cast(&pfn ## F))) - -#define VU_API_IAT_RESTORE(O, M, F)\ - vu::IATHooking::instance().uninstall(\ - _T( # O ), _T( # M ), _T( # F )) - -struct IATElement; - class IATHookingA : public SingletonT { public: + struct Entry + { + std::string target; + std::string module; + std::string function; + void* original; + void* replacement; + + Entry(); + Entry( + const std::string& t, const std::string& m, const std::string& f, + void* o = nullptr, void* r = nullptr); + + Entry(const Entry& right); + const Entry& operator=(const Entry& right); + bool operator==(const Entry& right) const; + bool operator!=(const Entry& right) const; + }; + IATHookingA(); virtual ~IATHookingA(); @@ -1573,17 +1568,24 @@ class IATHookingA : public SingletonT const std::string& target, const std::string& module, const std::string& function, - const void* replacement = nullptr, - const void** original = nullptr + void* replacement = nullptr, + void** original = nullptr ); VUResult uninstall( const std::string& target, const std::string& module, const std::string& function, - const void** replacement = nullptr + void** replacement = nullptr ); + bool exist( + const std::string& target, + const std::string& module, + const std::string& function, + Entry* ptr_entry = nullptr); + +private: /** * Iterate all imported-functions in a module. * @param[out] module The imported-module name. @@ -1598,31 +1600,20 @@ class IATHookingA : public SingletonT PIMAGE_THUNK_DATA& ptr_iat, PIMAGE_THUNK_DATA& ptr_int)> fn); -private: enum iat_action { IAT_INSTALL, IAT_UNINSTALL, }; - typedef std::vector IATElements; + typedef std::vector EntryList; - IATElements m_iat_elements; + EntryList m_iat_entry_list; private: - IATElements::iterator find(const IATElement& element); - - IATElements::iterator find( - const std::string& target, - const std::string& module, - const std::string& function); - - bool exist( - const std::string& target, - const std::string& module, - const std::string& function); - - VUResult perform(const iat_action action, IATElement& element); + VUResult perform(const iat_action action, Entry& entry); + EntryList::iterator find(const Entry& entry); + EntryList::iterator find(const std::string& target, const std::string& module, const std::string& function); }; class IATHookingW : public SingletonT @@ -1635,15 +1626,15 @@ class IATHookingW : public SingletonT const std::wstring& target, const std::wstring& module, const std::wstring& function, - const void* replacement = nullptr, - const void** original = nullptr + void* replacement, + void** original ); VUResult uninstall( const std::wstring& target, const std::wstring& module, const std::wstring& function, - const void** replacement = nullptr + void** replacement ); }; diff --git a/src/details/apihookiat.cpp b/src/details/apihookiat.cpp index 5c235b9..170f090 100644 --- a/src/details/apihookiat.cpp +++ b/src/details/apihookiat.cpp @@ -18,49 +18,59 @@ namespace vu #endif // _MSC_VER /** - * IATElement + * IATHookingA::Entry */ -struct IATElement +IATHookingA::Entry::Entry() + : target(""), module(""), function("") + , original(nullptr), replacement(nullptr) { - std::string target; - std::string module; - std::string function; - const void* original; - const void* replacement; - - IATElement() : target(""), module(""), function(""), original(nullptr), replacement(nullptr) {} - - IATElement( - const std::string& t, - const std::string& m, - const std::string& f, - const void* o = 0, - const void* r = 0) : target(t), module(m), function(f), original(o), replacement(r) {} - - const IATElement& operator=(const IATElement& right) +} + +IATHookingA::Entry::Entry( + const std::string& t, const std::string& m, const std::string& f, + void* o, void* r) + : target(t), module(m), function(f) + , original(o), replacement(r) +{ +} + +IATHookingA::Entry::Entry(const Entry& right) +{ + *this = right; +} + +const IATHookingA::Entry& IATHookingA::Entry::operator=(const Entry& right) +{ + if (this != &right) { - target = right.target; - module = right.module; - function = right.function; - original = right.original; + target = right.target; + module = right.module; + function = right.function; + original = right.original; replacement = right.replacement; - return *this; } - bool operator==(const IATElement& right) const - { - return\ - upper_string_A(target) == upper_string_A(right.target) && - upper_string_A(module) == upper_string_A(right.module) && - upper_string_A(function) == upper_string_A(right.function); - } + return *this; +} - bool operator!=(const IATElement& right) const +bool IATHookingA::Entry::operator==(const Entry& right) const +{ + if (this == &right) { - return !(*this == right); + return true; } -}; + + return\ + upper_string_A(target) == upper_string_A(right.target) && + upper_string_A(module) == upper_string_A(right.module) && + upper_string_A(function) == upper_string_A(right.function); +} + +bool IATHookingA::Entry::operator!=(const Entry& right) const +{ + return !(*this == right); +} /** * IATHookingA @@ -74,52 +84,69 @@ IATHookingA::~IATHookingA() { } -IATHookingA::IATElements::iterator IATHookingA::find( +IATHookingA::EntryList::iterator IATHookingA::find( const std::string& target, const std::string& module, const std::string& function) { - return std::find(m_iat_elements.begin(), m_iat_elements.end(), IATElement(target, module, function)); + if (module.empty() || function.empty()) + { + return m_iat_entry_list.end(); + } + + return std::find(m_iat_entry_list.begin(), m_iat_entry_list.end(), Entry(target, module, function)); } -IATHookingA::IATElements::iterator IATHookingA::find(const IATElement& element) +IATHookingA::EntryList::iterator IATHookingA::find(const Entry& entry) { - return this->find(element.target, element.module, element.function); + return this->find(entry.target, entry.module, entry.function); } bool IATHookingA::exist( const std::string& target, const std::string& module, - const std::string& function) + const std::string& function, + Entry* ptr_entry) { - return this->find(target, module, function) != m_iat_elements.end(); + auto it = this->find(target, module, function); + if (it == m_iat_entry_list.end()) + { + return false; + } + + if (ptr_entry != nullptr) + { + *ptr_entry = *it; + } + + return true; } VUResult IATHookingA::install( const std::string& target, const std::string& module, const std::string& function, - const void* replacement, - const void** original) + void* replacement, + void** original) { if (this->exist(target, module, function)) { return 1; } - auto element = IATElement(target, module, function, nullptr, replacement); + Entry entry(target, module, function, nullptr, replacement); - if (this->perform(iat_action::IAT_INSTALL, element) != VU_OK) + if (this->perform(iat_action::IAT_INSTALL, entry) != VU_OK) { return 2; } if (original != nullptr) { - *original = element.original; + *original = entry.original; } - m_iat_elements.emplace_back(element); + m_iat_entry_list.emplace_back(entry); return VU_OK; } @@ -128,56 +155,54 @@ VUResult IATHookingA::uninstall( const std::string& target, const std::string& module, const std::string& function, - const void** replacement) + void** replacement) { auto it = this->find(target, module, function); - if (it == m_iat_elements.end()) + if (it == m_iat_entry_list.end()) { return 1; } - auto element = *it; + auto& entry = *it; - if (this->perform(iat_action::IAT_UNINSTALL, element) != VU_OK) + if (this->perform(iat_action::IAT_UNINSTALL, entry) != VU_OK) { return 2; } if (replacement != nullptr) { - *replacement = element.replacement; + *replacement = entry.replacement; } - m_iat_elements.erase(it); + m_iat_entry_list.erase(it); return VU_OK; } -VUResult IATHookingA::perform(const iat_action action, IATElement& element) +VUResult IATHookingA::perform(const iat_action action, Entry& entry) { - if (element.target.empty() || element.module.empty() || element.function.empty()) + if (entry.target.empty() || entry.module.empty() || entry.function.empty()) { return 1; } - this->iterate(element.target, [&]( + this->iterate(entry.target, [&]( const std::string& m, const std::string& f, PIMAGE_THUNK_DATA& ptr_iat, PIMAGE_THUNK_DATA& ptr_int) { - // msg_debug_A("[%p] [%p] %s!%s\n", ptr_iat->u1.Function, ptr_int->u1.Function, m.c_str(), f.c_str()); - - if (element == IATElement(element.target, m, f)) + if (entry == Entry(entry.target, m, f)) { const void* address = 0; if (action == iat_action::IAT_INSTALL) { - element.original = reinterpret_cast(ptr_iat->u1.Function); - address = element.replacement; + entry.original = reinterpret_cast(ptr_iat->u1.Function); + address = entry.replacement; } else if (action == iat_action::IAT_UNINSTALL) { - element.replacement = reinterpret_cast(ptr_iat->u1.Function); - address = element.original; + entry.replacement = reinterpret_cast(ptr_iat->u1.Function); + address = entry.original; } if (address != 0) @@ -282,8 +307,8 @@ VUResult IATHookingW::install( const std::wstring& target, const std::wstring& module, const std::wstring& function, - const void* replacement, - const void** original) + void* replacement, + void** original) { return IATHookingA::instance().install( to_string_A(target), to_string_A(module), to_string_A(function), replacement, original); @@ -293,7 +318,7 @@ VUResult IATHookingW::uninstall( const std::wstring& target, const std::wstring& module, const std::wstring& function, - const void** replacement) + void** replacement) { return IATHookingA::instance().uninstall( to_string_A(target), to_string_A(module), to_string_A(function), replacement);