Skip to content

Commit ae63e43

Browse files
committed
Vutils
1 parent 20beaaa commit ae63e43

File tree

9 files changed

+481
-0
lines changed

9 files changed

+481
-0
lines changed

Vutils.vcxproj

+6
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@
329329
<ClInclude Include="3rdparty\UND\include\undname.h" />
330330
<ClInclude Include="3rdparty\WHW\WinHttpWrapper.h" />
331331
<ClInclude Include="include\3rdparty\BI\BigInt.hpp" />
332+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\common.h" />
333+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\hooking.h" />
334+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\iat_hooking.h" />
335+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\inl_hooking.h" />
336+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\invokable.h" />
332337
<ClInclude Include="include\3rdparty\EP\include\easyprint.hpp" />
333338
<ClInclude Include="include\3rdparty\NO\include\base\named_operator.hpp" />
334339
<ClInclude Include="include\3rdparty\NO\include\util\io_helpers.hpp" />
@@ -401,6 +406,7 @@
401406
<None Include="include\inline\types.inl" />
402407
<None Include="include\inline\spechrs.inl" />
403408
<None Include="include\template\easyprint.tpl" />
409+
<None Include="include\template\fnhooking.tpl" />
404410
<None Include="include\template\handle.tpl" />
405411
<None Include="include\template\math.tpl" />
406412
<None Include="include\template\misc.tpl" />

Vutils.vcxproj.filters

+21
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
<Filter Include="Header Files\Third Files\EP">
6565
<UniqueIdentifier>{0e80967e-0e61-4762-98d0-e9774dcee22f}</UniqueIdentifier>
6666
</Filter>
67+
<Filter Include="Header Files\Third Files\CH">
68+
<UniqueIdentifier>{09804e65-3ba8-4b2d-ac74-8f7e22ab2be0}</UniqueIdentifier>
69+
</Filter>
6770
</ItemGroup>
6871
<ItemGroup>
6972
<ClInclude Include="include\Vutils.h">
@@ -156,6 +159,21 @@
156159
<ClInclude Include="include\3rdparty\EP\include\easyprint.hpp">
157160
<Filter>Header Files\Third Files\EP</Filter>
158161
</ClInclude>
162+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\common.h">
163+
<Filter>Header Files\Third Files\CH</Filter>
164+
</ClInclude>
165+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\hooking.h">
166+
<Filter>Header Files\Third Files\CH</Filter>
167+
</ClInclude>
168+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\iat_hooking.h">
169+
<Filter>Header Files\Third Files\CH</Filter>
170+
</ClInclude>
171+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\inl_hooking.h">
172+
<Filter>Header Files\Third Files\CH</Filter>
173+
</ClInclude>
174+
<ClInclude Include="include\3rdparty\CH\cpp-hooking\invokable.h">
175+
<Filter>Header Files\Third Files\CH</Filter>
176+
</ClInclude>
159177
</ItemGroup>
160178
<ItemGroup>
161179
<ClCompile Include="src\Vutils.cpp">
@@ -358,5 +376,8 @@
358376
<None Include="include\template\easyprint.tpl">
359377
<Filter>Header Files\Template Files</Filter>
360378
</None>
379+
<None Include="include\template\fnhooking.tpl">
380+
<Filter>Header Files\Template Files</Filter>
381+
</None>
361382
</ItemGroup>
362383
</Project>
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @file common.h
3+
* @author Vic P.
4+
* @brief Header for common use.
5+
*/
6+
7+
#pragma once
8+
9+
#include "invokable.h"
10+
11+
#include <memory>
12+
#include <vu>
13+
14+
/**
15+
* @brief The structure that holds the hooking information of a function.
16+
*/
17+
struct Hooked
18+
{
19+
void* m_function;
20+
void* m_trampoline;
21+
std::shared_ptr<Invokable> m_invoker;
22+
23+
Hooked() : m_function(nullptr), m_trampoline(nullptr) {}
24+
25+
Hooked(const Hooked& right)
26+
{
27+
*this = right;
28+
}
29+
30+
const Hooked& operator=(const Hooked& right)
31+
{
32+
if (this != &right)
33+
{
34+
m_function = right.m_function;
35+
m_trampoline = right.m_trampoline;
36+
m_invoker = right.m_invoker;
37+
}
38+
39+
return *this;
40+
}
41+
};
42+
43+
template <typename T>
44+
struct LibraryT;
45+
46+
template <>
47+
struct LibraryT<std::string>
48+
{
49+
typedef vu::LibraryA self;
50+
};
51+
52+
template <>
53+
struct LibraryT<std::wstring>
54+
{
55+
typedef vu::LibraryW self;
56+
};
57+
58+
/**
59+
* @brief Get the address of an exported function from the given dynamic-link module.
60+
* @param module The module name.
61+
* @param function The function name.
62+
* @returns The address of the function or null.
63+
*/
64+
template<typename StdString>
65+
inline void* get_proc_address(const StdString& module, const StdString& function)
66+
{
67+
if (module.empty() || function.empty())
68+
{
69+
return nullptr;
70+
}
71+
72+
return LibraryT<StdString>::self::quick_get_proc_address(module, function);
73+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @file hooking.h
3+
* @author Vic P.
4+
* @brief Header for Inline Hooking Manager & IAT Hooking Manager.
5+
*/
6+
7+
#pragma once
8+
9+
#include "inl_hooking.h"
10+
#include "iat_hooking.h"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/**
2+
* @file iat_hooking.h
3+
* @author Vic P.
4+
* @brief Header/Implementation for IAT Hooking Manager.
5+
*/
6+
7+
#pragma once
8+
9+
#include "common.h"
10+
11+
#include <vu>
12+
13+
/**
14+
* @brief IAT Hooking Manager.
15+
*/
16+
class IATHookingManager : public vu::SingletonT<IATHookingManager>
17+
{
18+
struct IAT_Hooked : public Hooked {};
19+
20+
std::unordered_map<void*, IAT_Hooked> m_list;
21+
22+
using Entry = vu::IATHookingA::Entry;
23+
24+
vu::IATHookingA& hooker()
25+
{
26+
return vu::IATHookingA::instance();
27+
}
28+
29+
void* get_proc_address(const Entry& entry)
30+
{
31+
Entry temp;
32+
33+
if (!this->hooker().exist(entry.target, entry.module, entry.function, &temp))
34+
{
35+
return nullptr;
36+
}
37+
38+
return temp.original;
39+
}
40+
41+
public:
42+
/**
43+
* @brief Hook a given function.
44+
* @param[in] entry The entry of function that want to hook ({ tartget name, module name, function name }).
45+
* @param[in] hk_function The hooking function.
46+
* @return true if succeeds otherwise return false.
47+
*/
48+
template<typename Function>
49+
bool hook(const Entry& entry, Function&& hk_function)
50+
{
51+
IAT_Hooked hooked;
52+
53+
auto ret = this->hooker().install(entry.target, entry.module, entry.function,
54+
(void*)hk_function, &hooked.m_trampoline);
55+
if (ret != vu::VU_OK)
56+
{
57+
return false;
58+
}
59+
60+
auto function = this->get_proc_address(entry);
61+
if (function == nullptr)
62+
{
63+
return false;
64+
}
65+
66+
using FunctionPtr = decltype(&hk_function);
67+
68+
hooked.m_function = function;
69+
hooked.m_invoker.reset(new Invokable(FunctionPtr(hooked.m_trampoline)));
70+
71+
void* key = hooked.m_function;
72+
m_list[key] = std::move(hooked);
73+
74+
return true;
75+
}
76+
77+
/**
78+
* @brief Unhook a given function that was hooked.
79+
* @param[in] entry The entry of function that want to un-hook ({ tartget name, module name, function name }).
80+
* @return true if succeeds otherwise return false.
81+
*/
82+
bool unhook(const Entry& entry)
83+
{
84+
auto function = this->get_proc_address(entry);
85+
if (function == nullptr)
86+
{
87+
return false;
88+
}
89+
90+
auto it = m_list.find(function);
91+
if (it == m_list.cend())
92+
{
93+
return false;
94+
}
95+
96+
auto ret = this->hooker().uninstall(entry.target, entry.module, entry.function);
97+
if (ret != vu::VU_OK)
98+
{
99+
return false;
100+
}
101+
102+
m_list.erase(it);
103+
104+
return true;
105+
}
106+
107+
/**
108+
* @brief Invoke the original function.
109+
* @param[in] entry The entry of function that want to invoke ({ tartget name, module name, function name }).
110+
* @param[in] args The arguments that pass to the original function.
111+
* @return Based on the result of the original function.
112+
*/
113+
template<typename Return, typename ... Args>
114+
Return invoke(const Entry& entry, Args ... args)
115+
{
116+
auto function = this->get_proc_address(entry);
117+
auto it = m_list.find(function);
118+
if (it == m_list.cend())
119+
{
120+
throw "invoke the function that did not hook";
121+
}
122+
123+
auto& hooked = it->second;
124+
125+
if (std::is_void<Return>::value)
126+
{
127+
hooked.m_invoker->invoke<Return>(std::forward<Args>(args)...);
128+
}
129+
else
130+
{
131+
return hooked.m_invoker->invoke<Return>(std::forward<Args>(args)...);
132+
}
133+
}
134+
};

0 commit comments

Comments
 (0)