-
Notifications
You must be signed in to change notification settings - Fork 444
/
dynCodeHelper.cpp
111 lines (88 loc) · 3.33 KB
/
dynCodeHelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "dynCodeHelper.h"
/*
* class AutoEnableDynamicCodeGen
*/
typedef
BOOL
(WINAPI *PGET_PROCESS_MITIGATION_POLICY_PROC)(
_In_ HANDLE hProcess,
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_Out_ PVOID lpBuffer,
_In_ SIZE_T dwLength
);
AutoEnableDynamicCodeGen::PSET_THREAD_INFORMATION_PROC AutoEnableDynamicCodeGen::SetThreadInformationProc = nullptr;
AutoEnableDynamicCodeGen::PGET_THREAD_INFORMATION_PROC AutoEnableDynamicCodeGen::GetThreadInformationProc = nullptr;
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY AutoEnableDynamicCodeGen::processPolicy;
volatile bool AutoEnableDynamicCodeGen::processPolicyObtained = false;
AutoEnableDynamicCodeGen::AutoEnableDynamicCodeGen(bool enable) : enabled(false)
{
if (enable == false)
{
return;
}
//
// Snap the dynamic code generation policy for this process so that we
// don't need to resolve APIs and query it each time. We expect the policy
// to have been established upfront.
//
if (processPolicyObtained == false)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_VIRTMEM);
if (processPolicyObtained == false)
{
PGET_PROCESS_MITIGATION_POLICY_PROC GetProcessMitigationPolicyProc = nullptr;
HMODULE module = GetModuleHandleW(_T("api-ms-win-core-processthreads-l1-1-3.dll"));
if (module != nullptr)
{
GetProcessMitigationPolicyProc = (PGET_PROCESS_MITIGATION_POLICY_PROC)GetProcAddress(module, "GetProcessMitigationPolicy");
SetThreadInformationProc = (PSET_THREAD_INFORMATION_PROC)GetProcAddress(module, "SetThreadInformation");
GetThreadInformationProc = (PGET_THREAD_INFORMATION_PROC)GetProcAddress(module, "GetThreadInformation");
}
if ((GetProcessMitigationPolicyProc == nullptr) ||
(!GetProcessMitigationPolicyProc(GetCurrentProcess(), ProcessDynamicCodePolicy, (PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY)&processPolicy, sizeof(processPolicy))))
{
processPolicy.ProhibitDynamicCode = 0;
}
processPolicyObtained = true;
}
}
//
// The process is not prohibiting dynamic code or does not allow threads
// to opt out. In either case, return to the caller.
//
// N.B. It is OK that this policy is mutable at runtime. If a process
// really does not allow thread opt-out, then the call below will fail
// benignly.
//
if ((processPolicy.ProhibitDynamicCode == 0) || (processPolicy.AllowThreadOptOut == 0))
{
return;
}
if (SetThreadInformationProc == nullptr || GetThreadInformationProc == nullptr)
{
return;
}
//
// If dynamic code is already allowed for this thread, then don't attempt to allow it again.
//
DWORD threadPolicy;
if ((GetThreadInformationProc(GetCurrentThread(), ThreadDynamicCodePolicy, &threadPolicy, sizeof(DWORD))) &&
(threadPolicy == THREAD_DYNAMIC_CODE_ALLOW))
{
return;
}
threadPolicy = THREAD_DYNAMIC_CODE_ALLOW;
BOOL result = SetThreadInformationProc(GetCurrentThread(), ThreadDynamicCodePolicy, &threadPolicy, sizeof(DWORD));
Assert(result);
enabled = true;
}
AutoEnableDynamicCodeGen::~AutoEnableDynamicCodeGen()
{
if (enabled)
{
DWORD threadPolicy = 0;
BOOL result = SetThreadInformationProc(GetCurrentThread(), ThreadDynamicCodePolicy, &threadPolicy, sizeof(DWORD));
Assert(result);
enabled = false;
}
}