Skip to content

Commit 0e2906b

Browse files
committed
Update VirtualUnprotector class
1 parent de59f2e commit 0e2906b

1 file changed

Lines changed: 31 additions & 22 deletions

File tree

include/dynlibutils/vthook.hpp

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,58 @@
2121
#endif
2222

2323
#include <cassert>
24+
#include <cstddef>
25+
#include <cstdint>
2426

2527
namespace DynLibUtils {
2628

27-
class MemUnprotector
29+
using ProtectFlags_t = unsigned long;
30+
31+
class VirtualUnprotector
2832
{
2933
public:
30-
MemUnprotector(CMemory pAddress, size_t nLength = sizeof(void*))
34+
VirtualUnprotector(void *pTarget, std::size_t nLength = sizeof(void*))
3135
{
3236
#if _WIN32
33-
VirtualProtect(pAddress, nLength, PAGE_EXECUTE_READWRITE, &m_nOldProtection);
34-
35-
m_pAddress = pAddress;
3637
m_nLength = nLength;
38+
m_pTarget = pTarget;
39+
40+
assert(VirtualProtect(pTarget, nLength, PAGE_EXECUTE_READWRITE, &m_nOldProtect));
3741
#else
38-
long nPageSize = sysconf(_SC_PAGESIZE);
39-
CMemory pPageStart = pAddress & ~(nPageSize - 1l);
40-
CMemory pPageEnd = (pAddress + nLength + nPageSize - 1l) & ~(nPageSize - 1l);
41-
size_t nAligned = pPageEnd - pPageStart;
42+
long pageSize = sysconf(_SC_PAGESIZE);
43+
44+
assert(pageSize >= 0);
4245

43-
mprotect(pPageStart, nAligned, PROT_READ | PROT_WRITE | PROT_EXEC);
46+
auto nPageSize = static_cast<std::uintptr_t>(pageSize);
4447

45-
m_pAddress = pPageStart;
48+
auto pAddress = reinterpret_cast<std::uintptr_t>(pTarget);
49+
CMemory pPageStart = pAddress & ~(nPageSize - 1l);
50+
std::uintptr_t pPageEnd = (pAddress + nLength + nPageSize - 1l) & ~(nPageSize - 1l);
51+
auto nAligned = static_cast<std::size_t>(pPageEnd - pPageStart);
52+
53+
m_nOldProtect = PROT_READ;
4654
m_nLength = nAligned;
47-
m_nOldProtection = PROT_READ | PROT_WRITE; //TODO: Need to parse /proc/self/maps
55+
m_pTarget = pPageStart;
56+
57+
assert(!mprotect(pPageStart, nAligned, PROT_READ | PROT_WRITE));
4858
#endif
4959
}
5060

51-
~MemUnprotector()
61+
~VirtualUnprotector()
5262
{
5363
#if _WIN32
5464
DWORD origProtect;
55-
VirtualProtect(m_pAddress, m_nLength, m_nOldProtection, &origProtect);
65+
assert(VirtualProtect(m_pTarget, m_nLength, m_nOldProtect, &origProtect));
5666
#else
57-
mprotect(m_pAddress, m_nLength, m_nOldProtection);
67+
assert(!mprotect(m_pTarget, m_nLength, m_nOldProtect));
5868
#endif
5969
}
6070

6171
private:
62-
size_t m_nLength;
63-
unsigned long m_nOldProtection;
64-
65-
CMemory m_pAddress;
66-
}; // class MemUnprotector
72+
ProtectFlags_t m_nOldProtect;
73+
std::size_t m_nLength;
74+
CMemory m_pTarget;
75+
}; // class VirtualUnprotector
6776

6877
template <typename T, typename C, typename ...Args>
6978
class VTHook
@@ -102,14 +111,14 @@ class VTHook
102111
protected:
103112
void HookImpl(T(*pfnTarget)(C*, Args...))
104113
{
105-
MemUnprotector unprotector(m_vmpFn);
114+
VirtualUnprotector unprotect(m_vmpFn);
106115

107116
*m_vmpFn.RCast<T(**)(C*, Args...)>() = pfnTarget;
108117
}
109118

110119
void UnhookImpl()
111120
{
112-
MemUnprotector unprotector(m_vmpFn);
121+
VirtualUnprotector unprotect(m_vmpFn);
113122

114123
*m_vmpFn.RCast<void **>() = m_pOriginalFn;
115124
}

0 commit comments

Comments
 (0)