This commit is contained in:
lhodges1 2023-08-17 18:45:50 +10:00
parent 302e50f955
commit 676b3837ce
29 changed files with 751 additions and 107 deletions

26
ac.sln
View file

@ -5,22 +5,48 @@ VisualStudioVersion = 17.5.33502.453
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "user", "user\user.vcxproj", "{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "user", "user\user.vcxproj", "{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|ARM64.ActiveCfg = Debug|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|ARM64.Build.0 = Debug|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.ActiveCfg = Debug|x64 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.ActiveCfg = Debug|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.Build.0 = Debug|x64 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x64.Build.0 = Debug|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.ActiveCfg = Debug|Win32 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.ActiveCfg = Debug|Win32
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.Build.0 = Debug|Win32 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Debug|x86.Build.0 = Debug|Win32
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|ARM64.ActiveCfg = Release|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|ARM64.Build.0 = Release|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.ActiveCfg = Release|x64 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.ActiveCfg = Release|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.Build.0 = Release|x64 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x64.Build.0 = Release|x64
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.ActiveCfg = Release|Win32 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.ActiveCfg = Release|Win32
{3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.Build.0 = Release|Win32 {3C8194C7-9F20-4FF8-8C4C-B26C3D053611}.Release|x86.Build.0 = Release|Win32
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|ARM64.Build.0 = Debug|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|ARM64.Deploy.0 = Debug|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x64.ActiveCfg = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x64.Build.0 = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x64.Deploy.0 = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x86.ActiveCfg = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x86.Build.0 = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Debug|x86.Deploy.0 = Debug|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|ARM64.ActiveCfg = Release|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|ARM64.Build.0 = Release|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|ARM64.Deploy.0 = Release|ARM64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x64.ActiveCfg = Release|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x64.Build.0 = Release|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x64.Deploy.0 = Release|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x86.ActiveCfg = Release|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x86.Build.0 = Release|x64
{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}.Release|x86.Deploy.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

11
driver/common.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef COMMON_H
#define COMMON_H
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
#define DEBUG_LOG(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[+] " fmt "\n", ##__VA_ARGS__)
#define DEBUG_ERROR(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[-] " fmt "\n", ##__VA_ARGS__)
#endif

56
driver/driver.c Normal file
View file

@ -0,0 +1,56 @@
#include "driver.h"
#include "common.h"
#include "ioctl.h"
VOID DriverUnload(
_In_ PDRIVER_OBJECT DriverObject
)
{
IoDeleteSymbolicLink( &DEVICE_SYMBOLIC_LINK );
IoDeleteDevice( &DriverObject->DeviceObject );
}
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
UNREFERENCED_PARAMETER( RegistryPath );
NTSTATUS status;
status = IoCreateDevice(
DriverObject,
NULL,
&DEVICE_NAME,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DriverObject->DeviceObject
);
if ( !NT_SUCCESS( status ) )
return STATUS_FAILED_DRIVER_ENTRY;
status = IoCreateSymbolicLink(
&DEVICE_SYMBOLIC_LINK,
&DEVICE_NAME
);
if ( !NT_SUCCESS( status ) )
{
IoDeleteDevice( &DriverObject->DeviceObject );
return STATUS_FAILED_DRIVER_ENTRY;
}
DriverObject->MajorFunction[ IRP_MJ_CREATE ] = DeviceCreate;
DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = DeviceClose;
DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = DeviceControl;
DriverObject->DriverUnload = DriverUnload;
DEBUG_LOG( "DonnaAC Driver Entry Complete" );
return status;
}

11
driver/driver.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef DRIVER_H
#define DRIVER_H
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING( L"\\Device\\DonnaAC" );
UNICODE_STRING DEVICE_SYMBOLIC_LINK = RTL_CONSTANT_STRING( L"\\??\\DonnaAC" );
#endif

77
driver/driver.inf Normal file
View file

@ -0,0 +1,77 @@
;
; driver.inf
;
[Version]
Signature="$WINDOWS NT$"
Class=System ; TODO: specify appropriate Class
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid
Provider=%ManufacturerName%
CatalogFile=driver.cat
DriverVer= ; TODO: set DriverVer in stampinf property pages
PnpLockdown=1
[DestinationDirs]
DefaultDestDir = 12
driver_Device_CoInstaller_CopyFiles = 11
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
driver.sys = 1,,
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
;*****************************************
; Install Section
;*****************************************
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
[Standard.NT$ARCH$]
%driver.DeviceDesc%=driver_Device, Root\driver ; TODO: edit hw-id
[driver_Device.NT]
CopyFiles=Drivers_Dir
[Drivers_Dir]
driver.sys
;-------------- Service installation
[driver_Device.NT.Services]
AddService = driver,%SPSVCINST_ASSOCSERVICE%, driver_Service_Inst
; -------------- driver driver install sections
[driver_Service_Inst]
DisplayName = %driver.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\driver.sys
;
;--- driver_Device Coinstaller installation ------
;
[driver_Device.NT.CoInstallers]
AddReg=driver_Device_CoInstaller_AddReg
CopyFiles=driver_Device_CoInstaller_CopyFiles
[driver_Device_CoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
[driver_Device_CoInstaller_CopyFiles]
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
[driver_Device.NT.Wdf]
KmdfService = driver, driver_wdfsect
[driver_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer name
DiskName = "driver Installation Disk"
driver.DeviceDesc = "driver Device"
driver.SVCDESC = "driver Service"

129
driver/driver.vcxproj Normal file
View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0AE83EC6-DDEA-4EDE-B1B2-1B2AB1E8BB54}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<RootNamespace>driver</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Include="driver.inf" />
</ItemGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="driver.c" />
<ClCompile Include="ioctl.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h" />
<ClInclude Include="driver.h" />
<ClInclude Include="ioctl.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Inf Include="driver.inf">
<Filter>Driver Files</Filter>
</Inf>
</ItemGroup>
<ItemGroup>
<ClCompile Include="driver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ioctl.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="driver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ioctl.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

32
driver/ioctl.c Normal file
View file

@ -0,0 +1,32 @@
#include "ioctl.h"
#include "common.h"
NTSTATUS DeviceControl(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PIRP Irp
)
{
DEBUG_LOG( "Handle opened to DonnaAC" );
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Irp->IoStatus.Status;
}
NTSTATUS DeviceClose(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
)
{
DEBUG_LOG( "Handle closed to DonnaAC" );
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Irp->IoStatus.Status;
}
NTSTATUS DeviceCreate(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
)
{
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Irp->IoStatus.Status;
}

23
driver/ioctl.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef IOCTL_H
#define IOCTL_H
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
NTSTATUS DeviceControl(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PIRP Irp
);
NTSTATUS DeviceClose(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
);
NTSTATUS DeviceCreate(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
);
#endif

6
user/km/driver.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "driver.h"
kernelmode::Driver::Driver(LPCWSTR DriverName)
{
this->driver_name = DriverName;
}

22
user/km/driver.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef DRIVER_H
#define DRIVER_H
#include <Windows.h>
#include "../threadpool.h"
namespace kernelmode
{
class Driver
{
HANDLE driver_handle;
LPCWSTR driver_name;
public:
std::shared_ptr<global::ThreadPool> thread_pool;
Driver(LPCWSTR DriverName);
};
}
#endif

7
user/km/kmanager.cpp Normal file
View file

@ -0,0 +1,7 @@
#include "kmanager.h"
kernelmode::KManager::KManager( LPCWSTR DriverName, std::shared_ptr<global::ThreadPool> ThreadPool )
{
this->driver_interface = std::make_unique<Driver>(DriverName);
this->thread_pool = ThreadPool;
}

20
user/km/kmanager.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef KMANAGER_H
#define KMANAGER_H
#include <windows.h>
#include "..\threadpool.h"
#include "driver.h"
namespace kernelmode
{
class KManager
{
std::unique_ptr<Driver> driver_interface;
std::shared_ptr<global::ThreadPool> thread_pool;
public:
KManager( LPCWSTR DriverName, std::shared_ptr<global::ThreadPool> ThreadPool );
};
}
#endif

View file

@ -1 +0,0 @@
#pragma once

View file

@ -4,28 +4,64 @@
#include "common.h" #include "common.h"
#include "../user/um/threadpool.h" #include "threadpool.h"
#include "../user/um/manager.h"
void TestFunction() #include "../user/um/umanager.h"
#include "../user/km/kmanager.h"
DWORD WINAPI Init(HINSTANCE hinstDLL)
{ {
AllocConsole();
FILE* file;
freopen_s( &file, "CONOUT$", "w", stdout );
freopen_s( &file, "CONIN$", "r", stdin );
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
std::shared_ptr<global::ThreadPool> thread_pool = std::make_shared<global::ThreadPool>( 4 );
usermode::UManager umanager( thread_pool );
//kernelmode::KManager kmanager( L"DonnaAC", thread_pool);
umanager.ValidateProcessModules();
while ( !GetAsyncKeyState( VK_DELETE ) )
{
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
}
fclose( stdout );
fclose( stdin );
FreeConsole();
FreeLibraryAndExitThread( hinstDLL, 0);
return 0;
} }
int main(int argc, char* argv[]) BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved ) // reserved
{ {
//if ( argc == 1 ) // Perform actions based on the reason for calling.
//{ switch ( fdwReason )
// LOG_INFO( "No target process passed, terminating" ); {
// return ERROR; case DLL_PROCESS_ATTACH:
//}
usermode::Manager manager( "notepad.exe" ); DisableThreadLibraryCalls( hinstDLL );
manager.ValidateProcessThreads();
const auto thread = CreateThread(
nullptr,
0,
reinterpret_cast< LPTHREAD_START_ROUTINE >( Init ),
hinstDLL,
0,
nullptr
);
while ( 1 ) if ( thread )
{ CloseHandle( thread );
} break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
} }

View file

@ -4,7 +4,7 @@
* This is the idle loop each thread will be running until a job is ready * This is the idle loop each thread will be running until a job is ready
* for execution * for execution
*/ */
void usermode::ThreadPool::ThreadLoop() void global::ThreadPool::ThreadLoop()
{ {
while ( true ) while ( true )
{ {
@ -42,7 +42,7 @@ void usermode::ThreadPool::ThreadLoop()
} }
} }
usermode::ThreadPool::ThreadPool(int ThreadCount) global::ThreadPool::ThreadPool(int ThreadCount)
{ {
this->thread_count = ThreadCount; this->thread_count = ThreadCount;
this->should_terminate = false; this->should_terminate = false;
@ -54,7 +54,7 @@ usermode::ThreadPool::ThreadPool(int ThreadCount)
} }
} }
void usermode::ThreadPool::QueueJob( const std::function<void()>& job ) void global::ThreadPool::QueueJob( const std::function<void()>& job )
{ {
/* push a job into our job queue safely by holding our queue lock */ /* push a job into our job queue safely by holding our queue lock */
std::unique_lock<std::mutex> lock( this->queue_mutex ); std::unique_lock<std::mutex> lock( this->queue_mutex );
@ -63,7 +63,7 @@ void usermode::ThreadPool::QueueJob( const std::function<void()>& job )
mutex_condition.notify_one(); mutex_condition.notify_one();
} }
void usermode::ThreadPool::Stop() void global::ThreadPool::Stop()
{ {
/* safely set our termination flag to true */ /* safely set our termination flag to true */
std::unique_lock<std::mutex> lock( this->queue_mutex ); std::unique_lock<std::mutex> lock( this->queue_mutex );
@ -76,7 +76,7 @@ void usermode::ThreadPool::Stop()
threads.clear(); threads.clear();
} }
bool usermode::ThreadPool::Busy() bool global::ThreadPool::Busy()
{ {
/* allows us to wait for when the job queue is empty allowing us to safely call the destructor */ /* allows us to wait for when the job queue is empty allowing us to safely call the destructor */
std::unique_lock<std::mutex> lock( this->queue_mutex ); std::unique_lock<std::mutex> lock( this->queue_mutex );

View file

@ -6,7 +6,7 @@
#include <queue> #include <queue>
#include <functional> #include <functional>
namespace usermode namespace global
{ {
/* /*
* This ThreadPool class is a simple threadpool implementation that will allow us * This ThreadPool class is a simple threadpool implementation that will allow us

View file

@ -9,15 +9,19 @@ usermode::Imports::Imports()
this->ImportMap[ "NtQueryInformationThread" ] = NtQueryInformationThread; this->ImportMap[ "NtQueryInformationThread" ] = NtQueryInformationThread;
std::map<std::string, void*>::iterator it; std::map<std::string, void*>::iterator it;
for ( it = this->ImportMap.begin(); it != this->ImportMap.end(); it++ ) for ( it = this->ImportMap.begin(); it != this->ImportMap.end(); it++ )
{ {
HMODULE module_handle = GetModuleHandle( L"ntdll.dll" ); HMODULE module_handle = GetModuleHandle( L"ntdll.dll" );
if ( !module_handle ) if ( !module_handle )
{ {
LOG_ERROR( "GetModuleHandle failed with status code 0x%x", GetLastError() ); LOG_ERROR( "GetModuleHandle failed with status code 0x%x", GetLastError() );
return; return;
} }
it->second = GetProcAddress( module_handle, it->first.c_str()); it->second = GetProcAddress( module_handle, it->first.c_str());
if ( !it->second ) if ( !it->second )
{ {
LOG_ERROR( "GetProcAddress failed with status code 0x%x", GetLastError() ); LOG_ERROR( "GetProcAddress failed with status code 0x%x", GetLastError() );

View file

@ -14,7 +14,10 @@ namespace usermode
{ {
public: public:
std::map<std::string, void*> ImportMap; std::map<std::string, void*> ImportMap;
void* NtQueryInformationThread; void* NtQueryInformationThread;
void* NtQueryVirtualMemory;
Imports(); Imports();
}; };
} }

View file

@ -1,23 +0,0 @@
#include "manager.h"
#include "../common.h"
#include "process.h"
#include "../um/imports.h"
#include <TlHelp32.h>
usermode::Manager::Manager( std::string ProcessName )
{
this->process_name = ProcessName;
this->process = std::make_unique<Process>( 4, ProcessName );
}
usermode::Manager::~Manager()
{
}
void usermode::Manager::ValidateProcessThreads()
{
this->process->thread_pool->QueueJob( [ this ]() {this->process->ValidateProcessThreads(); } );
}

View file

@ -1 +0,0 @@
#include "module.h"

View file

@ -1,8 +0,0 @@
#ifndef MODULE_H
#define MODULE_H
#include <Windows.h>
#endif

View file

@ -2,30 +2,16 @@
#include "../common.h" #include "../common.h"
#include "../um/imports.h" #include "../um/imports.h"
#include "memory.h"
#include <ImageHlp.h>
#include <iostream> #include <iostream>
usermode::Process::Process( int ThreadCount, std::string ProcessName ) usermode::Process::Process()
{ {
this->process_name = ProcessName; this->process_handle = GetCurrentProcess();
this->thread_pool = std::make_unique<ThreadPool>( ThreadCount ); this->process_id = GetCurrentProcessId();
this->process_handle = GetHandleToProcessGivenName( ProcessName );
this->function_imports = std::make_unique<Imports>(); this->function_imports = std::make_unique<Imports>();
if ( this->process_handle == INVALID_HANDLE_VALUE )
{
this->thread_pool->Stop();
throw std::invalid_argument("Failed to initiate process class handle with error");
}
}
usermode::Process::~Process()
{
/* Wait for our jobs to be finished, then safely stop our pool */
while ( true )
{
if ( this->thread_pool->Busy() == FALSE ) { this->thread_pool->Stop(); }
}
} }
void usermode::Process::ValidateProcessThreads() void usermode::Process::ValidateProcessThreads()
@ -112,7 +98,7 @@ std::vector<UINT64> usermode::Process::GetProcessThreadsStartAddresses()
* of the module. A simple way to check if a thread is a valid thread, however there are ways around * of the module. A simple way to check if a thread is a valid thread, however there are ways around
* this check so it is not a perfect solution. * this check so it is not a perfect solution.
*/ */
bool usermode::Process::CheckIfAddressLiesWithinValidProcessModule( UINT64 Address, bool* result ) bool usermode::Process::CheckIfAddressLiesWithinValidProcessModule( UINT64 Address, bool* Result )
{ {
HANDLE process_modules_handle; HANDLE process_modules_handle;
MODULEENTRY32 module_entry; MODULEENTRY32 module_entry;
@ -145,14 +131,14 @@ bool usermode::Process::CheckIfAddressLiesWithinValidProcessModule( UINT64 Addre
{ {
LOG_INFO( "found valid module LOL" ); LOG_INFO( "found valid module LOL" );
CloseHandle( process_modules_handle ); CloseHandle( process_modules_handle );
*result = true; *Result = true;
return true; return true;
} }
} while ( Module32Next( process_modules_handle, &module_entry ) ); } while ( Module32Next( process_modules_handle, &module_entry ) );
CloseHandle( process_modules_handle ); CloseHandle( process_modules_handle );
*result = false; *Result = false;
return true; return true;
} }
@ -204,7 +190,6 @@ HANDLE usermode::Process::GetHandleToProcessGivenName( std::string ProcessName )
{ {
LOG_INFO( "Found target process" ); LOG_INFO( "Found target process" );
CloseHandle( process_snapshot_handle ); CloseHandle( process_snapshot_handle );
this->process_id = process_entry.th32ProcessID;
return process_handle; return process_handle;
} }
@ -213,3 +198,140 @@ HANDLE usermode::Process::GetHandleToProcessGivenName( std::string ProcessName )
CloseHandle( process_snapshot_handle ); CloseHandle( process_snapshot_handle );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
bool usermode::Process::GetProcessBaseAddress( UINT64* Result )
{
HANDLE process_modules_handle;
MODULEENTRY32 module_entry;
process_modules_handle = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, this->process_id );
if ( process_modules_handle == INVALID_HANDLE_VALUE )
{
LOG_ERROR( "CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x", GetLastError() );
return false;
}
module_entry.dwSize = sizeof( MODULEENTRY32 );
if ( !Module32First( process_modules_handle, &module_entry ) )
{
LOG_ERROR( "Module32First failed with status 0x%x", GetLastError() );
CloseHandle( process_modules_handle );
return false;
}
*Result = (UINT64)module_entry.modBaseAddr;
CloseHandle( process_modules_handle );
return true;
}
void usermode::Process::ScanProcessMemory()
{
MEMORY_BASIC_INFORMATION memory_info = { 0 };
UINT64 base_address;
if ( !GetProcessBaseAddress( &base_address ) )
{
LOG_ERROR( "Failed to get process base address with status 0x%x", GetLastError() );
return;
}
while ( VirtualQueryEx(
this->process_handle,
( PVOID )base_address,
&memory_info,
sizeof( MEMORY_BASIC_INFORMATION ))
)
{
this->CheckPageProtection( &memory_info );
this->PatternScanRegion(base_address, &memory_info);
base_address += memory_info.RegionSize;
}
}
void usermode::Process::PatternScanRegion( UINT64 Address, MEMORY_BASIC_INFORMATION* Page )
{
}
void usermode::Process::CheckPageProtection( MEMORY_BASIC_INFORMATION* Page )
{
/* MEM_IMAGE indicates the pages are mapped into view of an image section */
if ( Page->Type == MEM_IMAGE )
return;
if ( Page->AllocationProtect & PAGE_EXECUTE ||
Page->AllocationProtect & PAGE_EXECUTE_READ ||
Page->AllocationProtect & PAGE_EXECUTE_READWRITE ||
Page->AllocationProtect & PAGE_EXECUTE_WRITECOPY
)
{
// report area or smth
}
}
void usermode::Process::VerifyLoadedModuleChecksums()
{
HANDLE process_modules_handle;
MODULEENTRY32 module_entry;
PVOID mapped_image;
DWORD in_memory_header_sum;
DWORD in_memory_check_sum;
DWORD disk_header_sum;
DWORD disk_check_sum;
DWORD result;
process_modules_handle = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, this->process_id );
if ( process_modules_handle == INVALID_HANDLE_VALUE )
{
LOG_ERROR( "CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x", GetLastError() );
return;
}
module_entry.dwSize = sizeof( MODULEENTRY32 );
if ( !Module32First( process_modules_handle, &module_entry ) )
{
LOG_ERROR( "Module32First failed with status 0x%x", GetLastError() );
return;
}
do
{
/* compute checksum for the in memory module */
mapped_image = CheckSumMappedFile(
module_entry.modBaseAddr,
module_entry.modBaseSize,
&in_memory_header_sum,
&in_memory_check_sum
);
if ( !mapped_image )
{
LOG_ERROR( "CheckSumMappedFile failed with status 0x%x", GetLastError() );
goto end;
}
/* computer the checksum for the module on disk */
result = MapFileAndCheckSum(
(PCWSTR)module_entry.szExePath,
&disk_header_sum,
&disk_check_sum
);
if ( result != CHECKSUM_SUCCESS )
{
LOG_ERROR( "MapFileAndCheckSum failed with status 0x%x", GetLastError() );
goto end;
}
LOG_INFO( "in memory checksum: %x, disk checksum: %x", in_memory_check_sum, disk_check_sum );
} while ( Module32Next( process_modules_handle, &module_entry ) );
end:
CloseHandle( process_modules_handle );
}

View file

@ -6,7 +6,7 @@
#include <TlHelp32.h> #include <TlHelp32.h>
#include <string> #include <string>
#include "../um/threadpool.h" #include "../threadpool.h"
#include "../um/imports.h" #include "../um/imports.h"
#define ThreadQuerySetWin32StartAddress 9 #define ThreadQuerySetWin32StartAddress 9
@ -23,22 +23,23 @@ namespace usermode
{ {
HANDLE process_handle; HANDLE process_handle;
DWORD process_id; DWORD process_id;
std::string process_name;
std::mutex mutex; std::mutex mutex;
std::unique_ptr<Imports> function_imports; std::unique_ptr<Imports> function_imports;
HANDLE GetHandleToProcessGivenName( std::string ProcessName ); HANDLE GetHandleToProcessGivenName( std::string ProcessName );
std::vector<UINT64> GetProcessThreadsStartAddresses(); std::vector<UINT64> GetProcessThreadsStartAddresses();
bool CheckIfAddressLiesWithinValidProcessModule( UINT64 Address, bool* result ); bool CheckIfAddressLiesWithinValidProcessModule( UINT64 Address, bool* Result );
bool GetProcessBaseAddress( UINT64* Result );
void CheckPageProtection( MEMORY_BASIC_INFORMATION* Page );
void PatternScanRegion( UINT64 Address, MEMORY_BASIC_INFORMATION* Page );
public: public:
std::unique_ptr<ThreadPool> thread_pool; Process();
Process( int ThreadCount, std::string ProcessName );
~Process();
void ValidateProcessThreads(); void ValidateProcessThreads();
void ScanProcessMemory();
void VerifyLoadedModuleChecksums();
}; };
} }

42
user/um/umanager.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "umanager.h"
#include "../common.h"
#include "process.h"
#include "../um/imports.h"
#include <TlHelp32.h>
usermode::UManager::UManager( std::shared_ptr<global::ThreadPool> ThreadPool )
{
this->thread_pool = ThreadPool;
this->process = std::make_unique<Process>();
}
usermode::UManager::~UManager()
{
/* Wait for our jobs to be finished, then safely stop our pool */
while ( true )
{
if ( this->thread_pool->Busy() == FALSE )
{
this->thread_pool->Stop();
break;
}
}
}
void usermode::UManager::ValidateProcessThreads()
{
this->thread_pool->QueueJob( [ this ]() {this->process->ValidateProcessThreads(); } );
}
void usermode::UManager::ValidateProcessMemory()
{
this->thread_pool->QueueJob( [ this ]() {this->process->ScanProcessMemory(); } );
}
void usermode::UManager::ValidateProcessModules()
{
this->thread_pool->QueueJob( [ this ]() {this->process->VerifyLoadedModuleChecksums(); } );
}

View file

@ -1,5 +1,5 @@
#ifndef MANAGER_H #ifndef UMANAGER_H
#define MANAGER_H #define UMANAGER_H
#include <string> #include <string>
#include <winternl.h> #include <winternl.h>
@ -17,16 +17,18 @@ namespace usermode
* class and the threadpool class to allow a single thread (or multiple) to easily run * class and the threadpool class to allow a single thread (or multiple) to easily run
* the core business logic of running tasks in a certain order. * the core business logic of running tasks in a certain order.
*/ */
class Manager class UManager
{ {
std::string process_name;
std::unique_ptr<Process> process; std::unique_ptr<Process> process;
std::shared_ptr<global::ThreadPool> thread_pool;
public: public:
Manager( std::string ProcessName ); UManager( std::shared_ptr<global::ThreadPool> ThreadPool );
~Manager(); ~UManager();
void ValidateProcessThreads(); void ValidateProcessThreads();
void ValidateProcessMemory();
void ValidateProcessModules();
}; };
} }

View file

@ -40,13 +40,13 @@
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
@ -108,6 +108,7 @@
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -124,25 +125,26 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="km\kprotection.cpp" /> <ClCompile Include="km\driver.cpp" />
<ClCompile Include="km\kmanager.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="um\imports.cpp" /> <ClCompile Include="um\imports.cpp" />
<ClCompile Include="um\module.cpp" />
<ClCompile Include="um\process.cpp" /> <ClCompile Include="um\process.cpp" />
<ClCompile Include="um\threadpool.cpp" /> <ClCompile Include="threadpool.cpp" />
<ClCompile Include="um\manager.cpp" /> <ClCompile Include="um\umanager.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="common.h" /> <ClInclude Include="common.h" />
<ClInclude Include="km\kprotection.h" /> <ClInclude Include="km\driver.h" />
<ClInclude Include="km\kmanager.h" />
<ClInclude Include="um\imports.h" /> <ClInclude Include="um\imports.h" />
<ClInclude Include="um\module.h" />
<ClInclude Include="um\process.h" /> <ClInclude Include="um\process.h" />
<ClInclude Include="um\threadpool.h" /> <ClInclude Include="threadpool.h" />
<ClInclude Include="um\manager.h" /> <ClInclude Include="um\umanager.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View file

@ -18,22 +18,22 @@
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="um\manager.cpp"> <ClCompile Include="um\umanager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="km\kprotection.cpp"> <ClCompile Include="km\kmanager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="um\process.cpp"> <ClCompile Include="um\process.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="um\threadpool.cpp"> <ClCompile Include="threadpool.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="um\imports.cpp"> <ClCompile Include="um\imports.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="um\module.cpp"> <ClCompile Include="km\driver.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
@ -41,22 +41,22 @@
<ClInclude Include="common.h"> <ClInclude Include="common.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="um\manager.h"> <ClInclude Include="um\umanager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="km\kprotection.h"> <ClInclude Include="km\kmanager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="um\process.h"> <ClInclude Include="um\process.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="um\threadpool.h"> <ClInclude Include="threadpool.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="um\imports.h"> <ClInclude Include="um\imports.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="um\module.h"> <ClInclude Include="km\driver.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>