Skip to content

Commit

Permalink
Added KbTriggerCopyOnWrite function
Browse files Browse the repository at this point in the history
  • Loading branch information
HoShiMin committed Jul 11, 2020
1 parent 855416d commit a708e4d
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 65 deletions.
15 changes: 8 additions & 7 deletions Kernel-Bridge/API/PteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ namespace Pte {
// AVL:Write : 1;
// We're setting the CoW bit (0b001):
constexpr unsigned int COW_MASK = 0b001;
constexpr unsigned int WRITE_MASK = 0b100;

if (PageSize) *PageSize = 0;

Expand All @@ -165,43 +166,43 @@ namespace Pte {
case PAGE_TABLES_INFO::pt32NonPaePage4Kb:
// PDE -> PTE -> PA:
if (PageSize) *PageSize = 4096;
if (Info.Pte->x32.NonPae.Page4Kb.D) break;
if (!Info.Pte->x32.NonPae.Page4Kb.P || Info.Pte->x32.NonPae.Page4Kb.D || (Info.Pte->x32.NonPae.Page4Kb.AVL & WRITE_MASK)) break;
Info.Pte->x32.NonPae.Page4Kb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt32NonPaePage4Mb:
// PDE -> PA:
if (PageSize) *PageSize = 4096 * 1024;
if (Info.Pde->x32.NonPae.Page4Mb.D) break;
if (!Info.Pde->x32.NonPae.Page4Mb.P || Info.Pde->x32.NonPae.Page4Mb.D || (Info.Pde->x32.NonPae.Page4Mb.AVL & WRITE_MASK)) break;
Info.Pde->x32.NonPae.Page4Mb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt32PaePage4Kb:
// PDPE -> PDE -> PTE -> PA:
if (PageSize) *PageSize = 4096;
if (Info.Pte->x32.Pae.Page4Kb.D) break;
if (!Info.Pte->x32.Pae.Page4Kb.P || Info.Pte->x32.Pae.Page4Kb.D || (Info.Pte->x32.Pae.Page4Kb.AVL & WRITE_MASK)) break;
Info.Pte->x32.Pae.Page4Kb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt32PaePage2Mb:
// PDPE -> PDE -> PA:
if (PageSize) *PageSize = 2048 * 1024;
if (Info.Pde->x32.Pae.Page2Mb.D) break;
if (!Info.Pde->x32.Pae.Page2Mb.P || Info.Pde->x32.Pae.Page2Mb.D || (Info.Pde->x32.Pae.Page2Mb.AVL & WRITE_MASK)) break;
Info.Pde->x32.Pae.Page2Mb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt64Page4Kb:
// PML4E -> PDPE -> PDE -> PTE -> PA:
if (PageSize) *PageSize = 4096;
if (Info.Pte->x64.Page4Kb.D) break;
if (!Info.Pte->x64.Page4Kb.P || Info.Pte->x64.Page4Kb.D || (Info.Pte->x64.Page4Kb.AVL & WRITE_MASK)) break;
Info.Pte->x64.Page4Kb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt64Page2Mb:
// PML4E -> PDPE -> PDE -> PA:
if (PageSize) *PageSize = 2048 * 1024;
if (Info.Pde->x64.Page2Mb.D) break;
if (!Info.Pde->x64.Page2Mb.P || Info.Pde->x64.Page2Mb.D || (Info.Pde->x64.Page2Mb.AVL & WRITE_MASK)) break;
Info.Pde->x64.Page2Mb.AVL = COW_MASK;
break;
case PAGE_TABLES_INFO::pt64Page1Gb:
// PML4E -> PDPE -> PA:
if (PageSize) *PageSize = 1024 * 1024 * 1024;
if (Info.Pdpe->x64.PageSize.Page1Gb.D) break;
if (!Info.Pdpe->x64.PageSize.Page1Gb.P || Info.Pdpe->x64.PageSize.Page1Gb.D || (Info.Pdpe->x64.PageSize.Page1Gb.AVL & WRITE_MASK)) break;
Info.Pdpe->x64.PageSize.Page1Gb.AVL = COW_MASK;
break;
}
Expand Down
4 changes: 4 additions & 0 deletions Kernel-Bridge/Kernel-Bridge.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\HookLib\HookLib\HookLib\;..\HookLib\HookLib\Zydis\include\;$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<PostBuildEvent>
<Command>makecab /f ../x32-debug.ddf</Command>
Expand Down Expand Up @@ -191,6 +192,7 @@
</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\HookLib\HookLib\HookLib\;..\HookLib\HookLib\Zydis\include\;$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)</AdditionalIncludeDirectories>
<ControlFlowGuard>false</ControlFlowGuard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<PostBuildEvent>
<Command>makecab /f ../x32-release.ddf</Command>
Expand All @@ -215,6 +217,7 @@
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\HookLib\HookLib\HookLib\;..\HookLib\HookLib\Zydis\include\;$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<PostBuildEvent>
<Command>makecab /f ../x64-debug.ddf</Command>
Expand Down Expand Up @@ -243,6 +246,7 @@
<AdditionalIncludeDirectories>..\HookLib\HookLib\HookLib\;..\HookLib\HookLib\Zydis\include\;$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)</AdditionalIncludeDirectories>
<WholeProgramOptimization>true</WholeProgramOptimization>
<ControlFlowGuard>false</ControlFlowGuard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<PostBuildEvent>
<Command>makecab /f ../x64-release.ddf</Command>
Expand Down
78 changes: 50 additions & 28 deletions Kernel-Bridge/Kernel-Bridge/IOCTLHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,27 @@ namespace
return Status;
}

NTSTATUS FASTCALL KbTriggerCopyOnWrite(IN PIOCTL_INFO RequestInfo, OUT PSIZE_T ResponseLength)
{
UNREFERENCED_PARAMETER(ResponseLength);

if (RequestInfo->InputBufferSize != sizeof(KB_TRIGGER_COPY_ON_WRITE_IN))
return STATUS_INFO_LENGTH_MISMATCH;

auto Input = static_cast<PKB_TRIGGER_COPY_ON_WRITE_IN>(RequestInfo->InputBuffer);
if (!Input) return STATUS_INVALID_PARAMETER;

HANDLE ProcessId = Input->ProcessId ? reinterpret_cast<HANDLE>(Input->ProcessId) : PsGetCurrentProcessId();
PEPROCESS Process = Processes::Descriptors::GetEPROCESS(ProcessId);
if (!Process) return STATUS_UNSUCCESSFUL;

BOOLEAN Status = Pte::TriggerCopyOnWrite(Process, reinterpret_cast<PVOID>(Input->PageVirtualAddress));

ObDereferenceObject(Process);

return Status ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}

NTSTATUS FASTCALL KbSuspendProcess(IN PIOCTL_INFO RequestInfo, OUT PSIZE_T ResponseLength)
{
UNREFERENCED_PARAMETER(ResponseLength);
Expand Down Expand Up @@ -2428,42 +2449,43 @@ NTSTATUS FASTCALL DispatchIOCTL(IN PIOCTL_INFO RequestInfo, OUT PSIZE_T Response
/* 63 */ KbUnsecureVirtualMemory,
/* 64 */ KbReadProcessMemory,
/* 65 */ KbWriteProcessMemory,
/* 66 */ KbSuspendProcess,
/* 67 */ KbResumeProcess,
/* 68 */ KbGetThreadContext,
/* 69 */ KbSetThreadContext,
/* 70 */ KbCreateUserThread,
/* 71 */ KbCreateSystemThread,
/* 72 */ KbQueueUserApc,
/* 73 */ KbRaiseIopl,
/* 74 */ KbResetIopl,
/* 75 */ KbGetProcessCr3Cr4,
/* 66 */ KbTriggerCopyOnWrite,
/* 67 */ KbSuspendProcess,
/* 68 */ KbResumeProcess,
/* 69 */ KbGetThreadContext,
/* 70 */ KbSetThreadContext,
/* 71 */ KbCreateUserThread,
/* 72 */ KbCreateSystemThread,
/* 73 */ KbQueueUserApc,
/* 74 */ KbRaiseIopl,
/* 75 */ KbResetIopl,
/* 76 */ KbGetProcessCr3Cr4,

// Sections:
/* 76 */ KbCreateSection,
/* 77 */ KbOpenSection,
/* 78 */ KbMapViewOfSection,
/* 79 */ KbUnmapViewOfSection,
/* 77 */ KbCreateSection,
/* 78 */ KbOpenSection,
/* 79 */ KbMapViewOfSection,
/* 80 */ KbUnmapViewOfSection,

// Loadable modules:
/* 80 */ KbCreateDriver,
/* 81 */ KbLoadModule,
/* 82 */ KbGetModuleHandle,
/* 83 */ KbCallModule,
/* 84 */ KbUnloadModule,
/* 81 */ KbCreateDriver,
/* 82 */ KbLoadModule,
/* 83 */ KbGetModuleHandle,
/* 84 */ KbCallModule,
/* 85 */ KbUnloadModule,

// Hypervisor:
/* 85 */ KbVmmEnable,
/* 86 */ KbVmmDisable,
/* 87 */ KbVmmInterceptPage,
/* 88 */ KbVmmDeinterceptPage,
/* 86 */ KbVmmEnable,
/* 87 */ KbVmmDisable,
/* 88 */ KbVmmInterceptPage,
/* 89 */ KbVmmDeinterceptPage,

// Stuff u kn0w:
/* 89 */ KbExecuteShellCode,
/* 90 */ KbGetKernelProcAddress,
/* 91 */ KbStallExecutionProcessor,
/* 92 */ KbBugCheck,
/* 93 */ KbFindSignature
/* 90 */ KbExecuteShellCode,
/* 91 */ KbGetKernelProcAddress,
/* 92 */ KbStallExecutionProcessor,
/* 93 */ KbBugCheck,
/* 94 */ KbFindSignature
};

USHORT Index = EXTRACT_CTL_CODE(RequestInfo->ControlCode) - CTL_BASE;
Expand Down
4 changes: 4 additions & 0 deletions Kernel-Tests/Kernel-Tests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -121,6 +122,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ExceptionHandling>Sync</ExceptionHandling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -141,6 +143,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -164,6 +167,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ExceptionHandling>Sync</ExceptionHandling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand Down
32 changes: 32 additions & 0 deletions Kernel-Tests/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,40 @@ VOID TestHvPageInterception()
VirtualFree(Read, 0, MEM_RELEASE);
}

WdkTypes::PVOID GetPhysAddr(OPTIONAL WdkTypes::PEPROCESS Process, PVOID VirtualAddress)
{
using namespace PhysicalMemory;
WdkTypes::PVOID64 Pa = 0;
KbGetPhysicalAddress(Process, reinterpret_cast<WdkTypes::PVOID>(VirtualAddress), &Pa);
return Pa;
}

VOID VirtualMemoryTests()
{
using namespace Processes::MemoryManagement;

HMODULE hModule = GetModuleHandle(L"ntdll.dll");
__assume(hModule != 0);
PVOID Address = GetProcAddress(hModule, "NtTestAlert");

printf("NtTestAlert: VA:%p, PA:0x%I64X\n", Address, GetPhysAddr(NULL, Address));
KbTriggerCopyOnWrite(0, reinterpret_cast<WdkTypes::PVOID>(Address));
printf("NtTestAlert: CoW-PA:0x%I64X\n", GetPhysAddr(NULL, Address));

KbTriggerCopyOnWrite(0, reinterpret_cast<WdkTypes::PVOID>(Address));
printf("NtTestAlert: Double CoW-PA:0x%I64X\n", GetPhysAddr(NULL, Address));

for (unsigned long long i = 0; i < 100000; ++i)
{
KbTriggerCopyOnWrite(0, reinterpret_cast<WdkTypes::PVOID>(Address) + i * 4096ull);
}
}

VOID RunAllTests()
{
VirtualMemoryTests();
return;

//ThreadingTests();
//return;

Expand Down
66 changes: 36 additions & 30 deletions SharedTypes/CtlTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,42 +92,43 @@ namespace Ctls
/* 63 */ KbUnsecureVirtualMemory,
/* 64 */ KbReadProcessMemory,
/* 65 */ KbWriteProcessMemory,
/* 66 */ KbSuspendProcess,
/* 67 */ KbResumeProcess,
/* 68 */ KbGetThreadContext,
/* 69 */ KbSetThreadContext,
/* 70 */ KbCreateUserThread,
/* 71 */ KbCreateSystemThread,
/* 72 */ KbQueueUserApc,
/* 73 */ KbRaiseIopl,
/* 74 */ KbResetIopl,
/* 75 */ KbGetProcessCr3Cr4,
/* 66 */ KbTriggerCopyOnWrite,
/* 67 */ KbSuspendProcess,
/* 68 */ KbResumeProcess,
/* 69 */ KbGetThreadContext,
/* 70 */ KbSetThreadContext,
/* 71 */ KbCreateUserThread,
/* 72 */ KbCreateSystemThread,
/* 73 */ KbQueueUserApc,
/* 74 */ KbRaiseIopl,
/* 75 */ KbResetIopl,
/* 76 */ KbGetProcessCr3Cr4,

// Sections:
/* 76 */ KbCreateSection,
/* 77 */ KbOpenSection,
/* 78 */ KbMapViewOfSection,
/* 79 */ KbUnmapViewOfSection,
/* 77 */ KbCreateSection,
/* 78 */ KbOpenSection,
/* 79 */ KbMapViewOfSection,
/* 80 */ KbUnmapViewOfSection,

// Loadable modules:
/* 80 */ KbCreateDriver,
/* 81 */ KbLoadModule,
/* 82 */ KbGetModuleHandle,
/* 83 */ KbCallModule,
/* 84 */ KbUnloadModule,
/* 81 */ KbCreateDriver,
/* 82 */ KbLoadModule,
/* 83 */ KbGetModuleHandle,
/* 84 */ KbCallModule,
/* 85 */ KbUnloadModule,

// Hypervisor:
/* 85 */ KbVmmEnable,
/* 86 */ KbVmmDisable,
/* 87 */ KbVmmInterceptPage,
/* 88 */ KbVmmDeinterceptPage,
/* 86 */ KbVmmEnable,
/* 87 */ KbVmmDisable,
/* 88 */ KbVmmInterceptPage,
/* 89 */ KbVmmDeinterceptPage,

// Stuff u kn0w:
/* 89 */ KbExecuteShellCode,
/* 90 */ KbGetKernelProcAddress,
/* 91 */ KbStallExecutionProcessor,
/* 92 */ KbBugCheck,
/* 93 */ KbFindSignature
/* 90 */ KbExecuteShellCode,
/* 91 */ KbGetKernelProcAddress,
/* 92 */ KbStallExecutionProcessor,
/* 93 */ KbBugCheck,
/* 94 */ KbFindSignature
};
}

Expand Down Expand Up @@ -527,20 +528,25 @@ DECLARE_STRUCT(KB_UNSECURE_VIRTUAL_MEMORY_IN, {
});

DECLARE_STRUCT(KB_READ_PROCESS_MEMORY_IN, {
UINT64 ProcessId;
OPTIONAL UINT64 ProcessId;
WdkTypes::PVOID BaseAddress;
WdkTypes::PVOID Buffer;
ULONG Size;
});

DECLARE_STRUCT(KB_WRITE_PROCESS_MEMORY_IN, {
UINT64 ProcessId;
OPTIONAL UINT64 ProcessId;
WdkTypes::PVOID BaseAddress;
WdkTypes::PVOID Buffer;
ULONG Size;
BOOLEAN PerformCopyOnWrite;
});

DECLARE_STRUCT(KB_TRIGGER_COPY_ON_WRITE_IN, {
OPTIONAL UINT64 ProcessId;
WdkTypes::PVOID PageVirtualAddress;
});

DECLARE_STRUCT(KB_SUSPEND_RESUME_PROCESS_IN, {
UINT64 ProcessId;
});
Expand Down
9 changes: 9 additions & 0 deletions User-Bridge/API/User-Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,15 @@ namespace Processes
return KbSendRequest(Ctls::KbWriteProcessMemory, &Input, sizeof(Input));
}

BOOL WINAPI KbTriggerCopyOnWrite(ULONG ProcessId, IN WdkTypes::PVOID PageVirtualAddress)
{
if (!PageVirtualAddress) return FALSE;
KB_TRIGGER_COPY_ON_WRITE_IN Input = {};
Input.ProcessId = ProcessId;
Input.PageVirtualAddress = PageVirtualAddress;
return KbSendRequest(Ctls::KbTriggerCopyOnWrite, &Input, sizeof(Input));
}

BOOL WINAPI KbGetProcessCr3Cr4(ULONG ProcessId, OUT OPTIONAL PUINT64 Cr3, OUT OPTIONAL PUINT64 Cr4)
{
if (!ProcessId) return FALSE;
Expand Down
2 changes: 2 additions & 0 deletions User-Bridge/API/User-Bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ namespace Processes
BOOLEAN PerformCopyOnWrite = TRUE
);

BOOL WINAPI KbTriggerCopyOnWrite(ULONG ProcessId, IN WdkTypes::PVOID PageVirtualAddress);

BOOL WINAPI KbGetProcessCr3Cr4(ULONG ProcessId, OUT OPTIONAL PUINT64 Cr3, OUT OPTIONAL PUINT64 Cr4);
}

Expand Down
Loading

0 comments on commit a708e4d

Please sign in to comment.