├── Misdirection - Seth Troxler Kyle Martin.pdf ├── FileSpy ├── FileSpy.rc ├── ProcTrace.h ├── ComIface.h ├── FileSpySupport.h ├── DecisionTreeGlobal.h ├── IOheuristics.h ├── DecisionTree.h ├── ProcTrace.c ├── FileSpy.vcxproj.filters ├── FileSpy.inf ├── FileSpy.h ├── DecisionTree.c ├── ComIface.c ├── FileSpySupport.c ├── FileSpy.vcxproj ├── IOheuristics.c └── FileSpy.c ├── README.md ├── .gitattributes ├── FileSpy.sln └── .gitignore /Misdirection - Seth Troxler Kyle Martin.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdmarti2/FileSpy/HEAD/Misdirection - Seth Troxler Kyle Martin.pdf -------------------------------------------------------------------------------- /FileSpy/FileSpy.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #define VER_FILETYPE VFT_DRV 6 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 7 | #define VER_FILEDESCRIPTION_STR "FileSpy Filter Driver" 8 | #define VER_INTERNALNAME_STR "FileSpy.sys" 9 | 10 | #include "common.ver" 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FileSpy 2 | 3 | A mechanism to protect files from ransomware. 4 | This driver will will force each program to use the shadow copy as if it was accessing the real copy. Changings to the real copy only occurs when the driver moves the changes over to the real file. 5 | 6 | FileSpy was the old name for this driver the project is called misdirection: Not the file you thought you wrote. 7 | -------------------------------------------------------------------------------- /FileSpy/ProcTrace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef PROC_TRACE_H 3 | #define PROC_TRACE_H 4 | 5 | 6 | #define PROCWLISTSIZE 8 7 | /** 8 | huge amount of guidance from this cite 9 | */ 10 | //http://www.adlice.com/making-an-antivirus-engine-the-guidelines/ 11 | #include 12 | #include 13 | #include 14 | #include "ComIface.h" 15 | 16 | BOOLEAN procNameWhiteList(PUNICODE_STRING Name); 17 | 18 | VOID CreateProcessNotifyEx( 19 | _Inout_ PEPROCESS Process, 20 | _In_ HANDLE ProcessId, 21 | _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo 22 | ); 23 | 24 | #endif -------------------------------------------------------------------------------- /FileSpy/ComIface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef COM_I_FACE_H 3 | #define COM_I_FACE_H 4 | 5 | #include "DecisionTreeGlobal.h" 6 | #include "DecisionTree.h" 7 | #include "IOheuristics.h" 8 | #define MAXPOINTS 100 9 | void InitComIface(); 10 | //void DestroyComIface(); 11 | 12 | //creating nodes 13 | Procmon* createProcessNode(unsigned long long PID, unsigned long long trustpoints); 14 | Childproc* createChildNode(unsigned long long PID, Procmon* n); 15 | 16 | //IO interactions need to make an initToSetUpSemaphores 17 | void recordProcess(unsigned long long pPID, unsigned long long cPID); 18 | void deleteProcess(unsigned long long cPID); 19 | void recordIO(unsigned long long PID,PUNICODE_STRING realFile, PUNICODE_STRING shadowFile); 20 | void updateIO(PUNICODE_STRING sFile, unsigned long long PID); 21 | 22 | #endif -------------------------------------------------------------------------------- /FileSpy/FileSpySupport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef FILE_SPY_SUPPORT_H 3 | #define FILE_SPY_SUPPORT_H 4 | 5 | #include 6 | #include 7 | 8 | #include "ComIface.h" 9 | 10 | #define WHITELISTSIZE 4 11 | 12 | 13 | BOOLEAN processWhiteList(PFLT_CALLBACK_DATA Data); 14 | BOOLEAN UStrncmp(PUNICODE_STRING, PUNICODE_STRING,USHORT POS); 15 | BOOLEAN WCStrncmp(wchar_t* dst, wchar_t* src, unsigned int len); 16 | 17 | USHORT findLashSlash(PUNICODE_STRING pnt); 18 | //void freeUnicodeString(PUNICODE_STRING str); 19 | void createUnicodeString(PUNICODE_STRING,USHORT MaxSize); 20 | 21 | void unicodePosCat(PUNICODE_STRING dst, PUNICODE_STRING src, USHORT start); 22 | void generateExt(PUNICODE_STRING ext, PFLT_CALLBACK_DATA Data); 23 | BOOLEAN redirectIO(PCFLT_RELATED_OBJECTS FltObjects,PFLT_CALLBACK_DATA Data, PFLT_FILE_NAME_INFORMATION nameInfo); 24 | //BOOLEAN redirectRenameIO(PFLT_CALLBACK_DATA Data); 25 | 26 | #endif -------------------------------------------------------------------------------- /FileSpy/DecisionTreeGlobal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef D_TREE_GLOBAL_H 3 | #define D_TREE_GLOBAL_H 4 | 5 | #include 6 | #include 7 | 8 | typedef struct IOtrace_t { 9 | struct IOtrace_t* next; 10 | unsigned int action; 11 | PUNICODE_STRING realFile;// PUNICDOE_STRING 12 | PUNICODE_STRING shadowFile;// PUNICODE_STRING 13 | } IOtrace; 14 | 15 | typedef struct Childproc_t { 16 | struct Childproc_t* next; 17 | unsigned long long CPID; 18 | struct Procmon_t* cpnt; 19 | } Childproc; 20 | 21 | typedef struct Procmon_t { 22 | struct Procmon_t* next; 23 | unsigned long long PID; 24 | struct Procmon_t* parent; 25 | struct Childproc_t* child; 26 | struct IOtrace_t* IO; 27 | int ghost; 28 | unsigned long long trustpoints; 29 | unsigned long long delFiles; 30 | unsigned long long touchFiles; 31 | unsigned long long highEntropyFiles; 32 | unsigned long long lowSimilarityScore; 33 | } Procmon; 34 | 35 | #endif -------------------------------------------------------------------------------- /FileSpy/IOheuristics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef IO_HEURISTICS_H 3 | #define IO_HEURISTICS_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DecisionTreeGlobal.h" 10 | #include "DecisionTree.h" 11 | 12 | 13 | /** 14 | IOTHold needs to be above 30 to allow for changes 15 | **/ 16 | #define IOThold 30 17 | #define MAXDELETEPNTS 50 18 | #define MAXENTROPYPNTS 50 19 | #define MAXPOINTS 100 20 | #define ENCRYPTTHOLD 70000 21 | //Constant for converting log(x) to log2(x) 22 | #define M_LOG2E 1.44269504088896340736 //log2(e) 23 | 24 | void initIOheuristics(); 25 | void IOhook(PCFLT_RELATED_OBJECTS FltObjects); 26 | void hhook(PCFLT_RELATED_OBJECTS FltObjects); 27 | void putProcess(Procmon* p); 28 | int shannonEntropy(PCFLT_RELATED_OBJECTS FltObjects, PUNICODE_STRING f); 29 | 30 | double approx_log(double x); 31 | double power(double x, int exp); 32 | double ln(double value); 33 | double log2(double value); 34 | 35 | #endif -------------------------------------------------------------------------------- /FileSpy/DecisionTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef D_TREE_H 3 | #define D_TREE_H 4 | 5 | #include 6 | #include 7 | 8 | typedef struct Iddnode_t { 9 | struct Iddnode_t* next; 10 | struct Iddnode_t* prev; 11 | unsigned long long ID; 12 | } Iddnode; 13 | 14 | typedef struct dnode_t { 15 | struct dnode_t* next; 16 | struct dnode_t* prev; 17 | } dnode; 18 | 19 | typedef struct snode_t { 20 | struct snode_t* next; 21 | } snode; 22 | 23 | typedef struct Idsnode_t { 24 | struct Idsnode_t* next; 25 | unsigned long long ID; 26 | } Idsnode; 27 | 28 | //sorted double linked list 29 | void addSortDlist(Iddnode** head, Iddnode* node); 30 | Iddnode* removeSortDlist(Iddnode** head, unsigned long long ID); 31 | Iddnode* findSortDlist(Iddnode** head, unsigned long long ID); 32 | 33 | //non sorted double linked list 34 | void addFirstDlist(dnode** head, dnode* node); 35 | void addLastDlist(dnode** head, dnode* node); 36 | dnode * removeDlist(dnode** head, dnode* node); 37 | 38 | //sorted single linked list 39 | void addSortSlist(Idsnode** head, Idsnode* node); 40 | Idsnode* removeSortSlist(Idsnode** head, unsigned long long ID); 41 | Idsnode* findSortSlist(Idsnode** head, unsigned long long ID); 42 | 43 | //non sorted single linked list 44 | void addFirstSlist(snode** head, snode* node); 45 | void addLastSlist(snode** head, snode* node); 46 | snode* removeSlist(snode** head, snode* node); 47 | 48 | #endif 49 | 50 | 51 | -------------------------------------------------------------------------------- /FileSpy/ProcTrace.c: -------------------------------------------------------------------------------- 1 | #include "ProcTrace.h" 2 | UNICODE_STRING wplist[] = { 3 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\explorer.exe"), 4 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\SearchProtocolHost.exe"), 5 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\SearchIndexer.exe"), 6 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\SearchFilterHost.exe"), 7 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\conhost.exe"), 8 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\csrss.exe"), 9 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\services.exe"), 10 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\svchost.exe") 11 | }; 12 | BOOLEAN procNameWhiteList(PUNICODE_STRING Name) { 13 | unsigned int i = 0; 14 | for (i = 0;i < PROCWLISTSIZE;i++) 15 | { 16 | if (RtlEqualUnicodeString(&wplist[i], Name,TRUE)) 17 | { 18 | return TRUE; 19 | } 20 | } 21 | return FALSE; 22 | } 23 | VOID CreateProcessNotifyEx( 24 | _Inout_ PEPROCESS Process, 25 | _In_ HANDLE ProcessId, 26 | _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo 27 | ) 28 | { 29 | //UNREFERENCED_PARAMETER(Process); 30 | //UNREFERENCED_PARAMETER(ProcessId); 31 | //UNREFERENCED_PARAMETER(CreateInfo); 32 | PUNICODE_STRING ProcName; 33 | SeLocateProcessImageName(Process, &ProcName); 34 | if (CreateInfo) 35 | { 36 | PUNICODE_STRING ParentProcName; 37 | PEPROCESS ParentHandle; 38 | PsLookupProcessByProcessId(CreateInfo->ParentProcessId, &ParentHandle); 39 | SeLocateProcessImageName(ParentHandle, &ParentProcName); 40 | //process created 41 | if (procNameWhiteList(ParentProcName)) { 42 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "created (WHITELIST) ---> child:%wZ: %ld\n", ProcName, ProcessId)); 43 | recordProcess(0, (unsigned long long)ProcessId); 44 | } 45 | else { 46 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "created parent: %wZ:%ld ---> child:%wZ: %ld\n", ParentProcName, CreateInfo->ParentProcessId, ProcName, ProcessId)); 47 | recordProcess((unsigned long long)CreateInfo->ParentProcessId, (unsigned long long)ProcessId); 48 | } 49 | } 50 | else { 51 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "Exit %wZ: %ld\n", ProcName,ProcessId)); 52 | deleteProcess((unsigned long long)ProcessId);//pretty much will trigger the whole minifilter 53 | } 54 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /FileSpy.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileSpy", "FileSpy\FileSpy.vcxproj", "{70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM.Build.0 = Debug|ARM 22 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x64.ActiveCfg = Debug|x64 27 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x64.Build.0 = Debug|x64 28 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x64.Deploy.0 = Debug|x64 29 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x86.ActiveCfg = Debug|Win32 30 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x86.Build.0 = Debug|Win32 31 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Debug|x86.Deploy.0 = Debug|Win32 32 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM.ActiveCfg = Release|ARM 33 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM.Build.0 = Release|ARM 34 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM.Deploy.0 = Release|ARM 35 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM64.Build.0 = Release|ARM64 37 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x64.ActiveCfg = Release|x64 39 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x64.Build.0 = Release|x64 40 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x64.Deploy.0 = Release|x64 41 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x86.ActiveCfg = Release|Win32 42 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x86.Build.0 = Release|Win32 43 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /FileSpy/FileSpy.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 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | 47 | 48 | Resource Files 49 | 50 | 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | Header Files 66 | 67 | 68 | Header Files 69 | 70 | 71 | Header Files 72 | 73 | 74 | -------------------------------------------------------------------------------- /FileSpy/FileSpy.inf: -------------------------------------------------------------------------------- 1 | ;;; 2 | ;;; FileSpy 3 | ;;; 4 | 5 | [Version] 6 | Signature = "$Windows NT$" 7 | Class = "ActivityMonitor" ;This is determined by the work this filter driver does 8 | ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determined by the Load Order Group value 9 | Provider = %ProviderString% 10 | DriverVer = 06/16/2007,1.0.0.1 11 | CatalogFile = FileSpy.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | MiniFilter.DriverFiles = 12 ;%windir%\system32\drivers 16 | 17 | ;; 18 | ;; Default install sections 19 | ;; 20 | 21 | [DefaultInstall] 22 | OptionDesc = %ServiceDescription% 23 | CopyFiles = MiniFilter.DriverFiles 24 | 25 | [DefaultInstall.Services] 26 | AddService = %ServiceName%,,MiniFilter.Service 27 | 28 | ;; 29 | ;; Default uninstall sections 30 | ;; 31 | 32 | [DefaultUninstall] 33 | DelFiles = MiniFilter.DriverFiles 34 | 35 | [DefaultUninstall.Services] 36 | DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting 37 | 38 | ; 39 | ; Services Section 40 | ; 41 | 42 | [MiniFilter.Service] 43 | DisplayName = %ServiceName% 44 | Description = %ServiceDescription% 45 | ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\ 46 | Dependencies = "FltMgr" 47 | ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER 48 | StartType = 3 ;SERVICE_DEMAND_START 49 | ErrorControl = 1 ;SERVICE_ERROR_NORMAL 50 | LoadOrderGroup = "FSFilter Activity Monitor" 51 | AddReg = MiniFilter.AddRegistry 52 | 53 | ; 54 | ; Registry Modifications 55 | ; 56 | 57 | [MiniFilter.AddRegistry] 58 | HKR,,"DebugFlags",0x00010001 ,0x0 59 | HKR,,"SupportedFeatures",0x00010001,0x3 60 | HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance% 61 | HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude% 62 | HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags% 63 | 64 | ; 65 | ; Copy Files 66 | ; 67 | 68 | [MiniFilter.DriverFiles] 69 | %DriverName%.sys 70 | 71 | [SourceDisksFiles] 72 | FileSpy.sys = 1,, 73 | 74 | [SourceDisksNames] 75 | 1 = %DiskId1%,,, 76 | 77 | ;; 78 | ;; String Section 79 | ;; 80 | 81 | [Strings] 82 | ; TODO - Add your manufacturer 83 | ProviderString = "FileSpy" 84 | ServiceDescription = "FileSpy Mini-Filter Driver" 85 | ServiceName = "FileSpy" 86 | DriverName = "FileSpy" 87 | DiskId1 = "FileSpy Device Installation Disk" 88 | 89 | ;Instances specific information. 90 | DefaultInstance = "FileSpy Instance" 91 | Instance1.Name = "FileSpy Instance" 92 | ;Instance1.Altitude = "370030" 93 | Instance1.Altitude = "44000" 94 | Instance1.Flags = 0x0 ; Allow all attachments 95 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /FileSpy/FileSpy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef FILE_SPY_MINIFILTER_H 3 | #define FILE_SPY_MINIFILTER_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "FileSpy.h" 13 | #include "FileSpySupport.h" 14 | #include "ProcTrace.h" 15 | #include "ComIface.h" 16 | #include "IOheuristics.h" 17 | 18 | #pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers") 19 | 20 | static UNICODE_STRING DirProtect = RTL_CONSTANT_STRING(L"\\Users\\WDKRemoteUser\\Documents\\"); 21 | wchar_t* wdirprotect = L"\\??\\C:\\Users\\WDKRemoteUser\\Documents\\"; 22 | wchar_t* wbin = L"\\??\\C:\\$RECYCLE.BIN\\"; 23 | 24 | 25 | PFLT_FILTER gFilterHandle; 26 | ULONG_PTR OperationStatusCtx = 1; 27 | 28 | #define PTDBG_TRACE_ROUTINES 0x00000001 29 | #define PTDBG_TRACE_OPERATION_STATUS 0x00000002 30 | 31 | ULONG gTraceFlags = 0; 32 | 33 | #define PT_DBG_PRINT( _dbgLevel, _string ) \ 34 | (FlagOn(gTraceFlags,(_dbgLevel)) ? \ 35 | DbgPrint _string : \ 36 | ((int)0)) 37 | 38 | EXTERN_C_START 39 | 40 | DRIVER_INITIALIZE DriverEntry; 41 | NTSTATUS 42 | DriverEntry( 43 | _In_ PDRIVER_OBJECT DriverObject, 44 | _In_ PUNICODE_STRING RegistryPath 45 | ); 46 | 47 | NTSTATUS 48 | FileSpyInstanceSetup( 49 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 50 | _In_ FLT_INSTANCE_SETUP_FLAGS Flags, 51 | _In_ DEVICE_TYPE VolumeDeviceType, 52 | _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType 53 | ); 54 | 55 | VOID 56 | FileSpyInstanceTeardownStart( 57 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 58 | _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags 59 | ); 60 | 61 | VOID 62 | FileSpyInstanceTeardownComplete( 63 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 64 | _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags 65 | ); 66 | 67 | NTSTATUS 68 | FileSpyUnload( 69 | _In_ FLT_FILTER_UNLOAD_FLAGS Flags 70 | ); 71 | 72 | NTSTATUS 73 | FileSpyInstanceQueryTeardown( 74 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 75 | _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags 76 | ); 77 | 78 | FLT_PREOP_CALLBACK_STATUS 79 | FileSpyPreCreate( 80 | _Inout_ PFLT_CALLBACK_DATA Data, 81 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 82 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 83 | ); 84 | FLT_POSTOP_CALLBACK_STATUS 85 | FileSpyPostCreate( 86 | _Inout_ PFLT_CALLBACK_DATA Data, 87 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 88 | _In_opt_ PVOID CompletionContext, 89 | _In_ FLT_POST_OPERATION_FLAGS Flags 90 | ); 91 | FLT_PREOP_CALLBACK_STATUS 92 | FileSpyPreSetInfo( 93 | _Inout_ PFLT_CALLBACK_DATA Data, 94 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 95 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 96 | ); 97 | FLT_POSTOP_CALLBACK_STATUS 98 | FileSpyPostSetInfo( 99 | _Inout_ PFLT_CALLBACK_DATA Data, 100 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 101 | _In_opt_ PVOID CompletionContext, 102 | _In_ FLT_POST_OPERATION_FLAGS Flags 103 | ); 104 | FLT_PREOP_CALLBACK_STATUS 105 | FileSpyPreWrite( 106 | _Inout_ PFLT_CALLBACK_DATA Data, 107 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 108 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 109 | ); 110 | FLT_POSTOP_CALLBACK_STATUS 111 | FileSpyPostWrite( 112 | _Inout_ PFLT_CALLBACK_DATA Data, 113 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 114 | _In_opt_ PVOID CompletionContext, 115 | _In_ FLT_POST_OPERATION_FLAGS Flags 116 | ); 117 | VOID 118 | FileSpyOperationStatusCallback( 119 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 120 | _In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot, 121 | _In_ NTSTATUS OperationStatus, 122 | _In_ PVOID RequesterContext 123 | ); 124 | FLT_PREOP_CALLBACK_STATUS 125 | FileSpyPreOperationNoPostOperation( 126 | _Inout_ PFLT_CALLBACK_DATA Data, 127 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 128 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 129 | ); 130 | 131 | BOOLEAN 132 | FileSpyDoRequestOperationStatus( 133 | _In_ PFLT_CALLBACK_DATA Data 134 | ); 135 | 136 | EXTERN_C_END 137 | 138 | 139 | #ifdef ALLOC_PRAGMA 140 | #pragma alloc_text(INIT, DriverEntry) 141 | #pragma alloc_text(PAGE, FileSpyUnload) 142 | #pragma alloc_text(PAGE, FileSpyInstanceQueryTeardown) 143 | #pragma alloc_text(PAGE, FileSpyInstanceSetup) 144 | #pragma alloc_text(PAGE, FileSpyInstanceTeardownStart) 145 | #pragma alloc_text(PAGE, FileSpyInstanceTeardownComplete) 146 | #endif 147 | 148 | CONST FLT_OPERATION_REGISTRATION Callbacks[] = { 149 | { IRP_MJ_CREATE, 150 | 0, 151 | FileSpyPreCreate, 152 | FileSpyPostCreate}, 153 | {IRP_MJ_WRITE, 154 | 0, 155 | FileSpyPreWrite, 156 | FileSpyPostWrite}, 157 | {IRP_MJ_SET_INFORMATION, 158 | 0, 159 | FileSpyPreSetInfo, 160 | FileSpyPostSetInfo}, 161 | { IRP_MJ_OPERATION_END } 162 | }; 163 | CONST FLT_REGISTRATION FilterRegistration = { 164 | 165 | sizeof(FLT_REGISTRATION), // Size 166 | FLT_REGISTRATION_VERSION, // Version 167 | 0, // Flags 168 | 169 | NULL, // Context 170 | Callbacks, // Operation callbacks 171 | 172 | FileSpyUnload, // MiniFilterUnload 173 | 174 | FileSpyInstanceSetup, // InstanceSetup 175 | FileSpyInstanceQueryTeardown, // InstanceQueryTeardown 176 | FileSpyInstanceTeardownStart, // InstanceTeardownStart 177 | FileSpyInstanceTeardownComplete, // InstanceTeardownComplete 178 | 179 | NULL, // GenerateFileName 180 | NULL, // GenerateDestinationFileName 181 | NULL // NormalizeNameComponent 182 | 183 | }; 184 | #endif 185 | -------------------------------------------------------------------------------- /FileSpy/DecisionTree.c: -------------------------------------------------------------------------------- 1 | #include "DecisionTree.h" 2 | 3 | //sorted double linked list 4 | //needs to be tested. 5 | void addSortDlist(Iddnode** head, Iddnode* node) { 6 | if (!head) 7 | return; 8 | 9 | if (!node) 10 | return; 11 | 12 | unsigned long long cid = node->ID; 13 | if (cid <= 0) 14 | return; 15 | 16 | if (!(*head)) 17 | { 18 | node->next = NULL; 19 | node->prev = NULL; 20 | *head = node; 21 | return; 22 | } 23 | 24 | //if the head is less than the pid of node 25 | if (cid >= (*head)->ID) 26 | { 27 | node->next = *head; 28 | node->prev = (*head)->prev; 29 | (*head)->prev = node; 30 | *head = node; 31 | return; 32 | } 33 | //insert into the list 34 | Iddnode* ppnt = (*head); 35 | Iddnode* cpnt = (*head)->next; 36 | 37 | while (cpnt) 38 | { 39 | if (cid >= cpnt->ID) 40 | { 41 | break; 42 | } 43 | ppnt = cpnt; 44 | cpnt = cpnt->next; 45 | } 46 | ppnt->next = node; 47 | node->next = cpnt; 48 | node->prev = ppnt; 49 | if (cpnt) 50 | cpnt->prev = node; 51 | } // needs te 52 | //needs to be tested 53 | Iddnode* removeSortDlist(Iddnode** head, unsigned long long ID) 54 | { 55 | if (!head) 56 | return 0; 57 | 58 | if (!(*head)) 59 | return 0; 60 | 61 | if ((*head)->ID == ID) { 62 | Iddnode* node = *head; 63 | (*head) = node->next; 64 | if (*head) 65 | (*head)->prev = node->prev; 66 | 67 | return node; 68 | } 69 | 70 | Iddnode* cpnt = (Iddnode*)(*head)->next; 71 | Iddnode* ppnt = (Iddnode*)(*head); 72 | 73 | while (cpnt) 74 | { 75 | if (cpnt->ID == ID) 76 | { 77 | break; 78 | } 79 | ppnt = cpnt; 80 | cpnt = cpnt->next; 81 | } 82 | if (cpnt) 83 | { 84 | Iddnode* node = cpnt; 85 | ppnt->next = cpnt->next; 86 | if (cpnt->next) { 87 | cpnt->next->prev = ppnt; 88 | } 89 | return node; 90 | } 91 | return 0; 92 | } 93 | //needs to be tested 94 | Iddnode* findSortDlist(Iddnode** head, unsigned long long ID) 95 | { 96 | if (!head) 97 | return 0; 98 | 99 | if (ID <= 0) 100 | return 0; 101 | 102 | //make a better search algorithm 103 | Iddnode* cpnt = (*head); 104 | while (cpnt) 105 | { 106 | if (cpnt->ID == ID) 107 | { 108 | return cpnt; 109 | } 110 | cpnt = cpnt->next; 111 | } 112 | return cpnt; 113 | } 114 | 115 | //non sorted double linked list 116 | //needs to be tested 117 | void addFirstDlist(dnode** head, dnode* node) 118 | { 119 | //make sure that something was submitted 120 | if (!head) 121 | return; 122 | //make sure a node was submitted 123 | if (!node) 124 | return; 125 | 126 | //insert the node to the beginning of the double linked list 127 | dnode* cpnt = *head; 128 | *head = node; 129 | (*head)->next = cpnt; 130 | 131 | // if cpnt is not null the prev of cpnt needs to be over written as 132 | // the head needs to have the prev of cpn just incase the head prev is nut null. 133 | if (cpnt) 134 | { 135 | (*head)->prev = cpnt->prev; 136 | cpnt->prev = (*head); 137 | } 138 | 139 | } 140 | //needs to be tested 141 | void addLastDlist(dnode** head, dnode* node) 142 | { 143 | //make sure that something was submitted as the head node 144 | if (!head) 145 | return; 146 | 147 | //make sure a node was submitted 148 | if (!node) 149 | return; 150 | 151 | //if the head is null add it as the head 152 | if (!(*head)) 153 | { 154 | *head = node; 155 | (*head)->next = NULL; 156 | (*head)->prev = NULL; 157 | } 158 | 159 | //find the last node 160 | dnode* cpnt = *head; 161 | while (cpnt->next) 162 | { 163 | cpnt = cpnt->next; 164 | } 165 | //add to the last of the linked list of a non sorted list 166 | cpnt->next = node; 167 | node->prev = cpnt; 168 | node->next = NULL; 169 | } 170 | //needs to be tested 171 | dnode* removeDlist(dnode** head, dnode* node) 172 | { 173 | if (!head) 174 | return 0; 175 | 176 | if (!node) 177 | return 0; 178 | 179 | if (!(*head)) 180 | return 0; 181 | 182 | dnode* cpnt = *head; 183 | dnode* ppnt = (*head)->prev; 184 | 185 | while (cpnt) 186 | { 187 | //if the node address is the same as the node to submit then it is the same node 188 | if (cpnt == node) 189 | { 190 | break; 191 | } 192 | ppnt = cpnt; 193 | cpnt = cpnt->next; 194 | } 195 | if (!cpnt) 196 | return 0; 197 | 198 | if (ppnt) 199 | { 200 | dnode* n = cpnt; 201 | ppnt->next = cpnt->next; 202 | if (cpnt->next) 203 | { 204 | cpnt->next->prev = ppnt; 205 | } 206 | n->next = NULL; 207 | n->prev = NULL; 208 | return n; 209 | } 210 | else { 211 | dnode* n = cpnt; 212 | (*head) = cpnt->next; 213 | if (cpnt->next) 214 | (*head)->prev = 0; 215 | 216 | return n; 217 | } 218 | } 219 | 220 | //sorted single linked list 221 | //needs to be tested 222 | void addSortSlist(Idsnode** head, Idsnode* node) 223 | { 224 | if (!head) 225 | return; 226 | 227 | if (!node) 228 | return; 229 | 230 | if (node->ID <= 0) 231 | return; 232 | 233 | if (!(*head)) 234 | { 235 | *head = node; 236 | return; 237 | } 238 | Idsnode* ppnt = 0; 239 | Idsnode* cpnt = *head; 240 | 241 | while (cpnt) 242 | { 243 | if (node->ID >= cpnt->ID) 244 | { 245 | break; 246 | } 247 | ppnt = cpnt; 248 | cpnt = cpnt->next; 249 | } 250 | if (ppnt) 251 | { 252 | ppnt->next = node; 253 | node->next = cpnt; 254 | } 255 | else { //this can only happen if the node is greater than the head 256 | node->next = *head; 257 | *head = node; 258 | } 259 | } 260 | //needs to be tested 261 | Idsnode* removeSortSlist(Idsnode** head, unsigned long long ID) 262 | { 263 | if (!head) 264 | return 0; 265 | 266 | if (ID <= 0) 267 | return 0; 268 | 269 | if (!(*head)) 270 | return 0; 271 | 272 | Idsnode* ppnt = NULL; 273 | Idsnode* cpnt = *head; 274 | while (cpnt) { 275 | 276 | if (cpnt->ID == ID) 277 | { 278 | Idsnode* npnt = cpnt; 279 | if (ppnt) 280 | { 281 | ppnt->next = cpnt->next; 282 | } 283 | else { 284 | *head = cpnt->next; 285 | } 286 | npnt->next = 0; 287 | return npnt; 288 | } 289 | ppnt = cpnt; 290 | cpnt = cpnt->next; 291 | } 292 | return 0; 293 | } 294 | //needs to be developed 295 | Idsnode* findSortSlist(Idsnode** head, unsigned long long ID) 296 | { 297 | if (!head) 298 | return 0; 299 | 300 | if (ID <= 0) 301 | return 0; 302 | 303 | Idsnode* cpnt = *head; 304 | while (cpnt) 305 | { 306 | if (cpnt->ID == ID) 307 | { 308 | return cpnt; 309 | } 310 | cpnt = cpnt->next; 311 | } 312 | return 0; 313 | } 314 | 315 | //non sortded single linked list 316 | //needs to be developed 317 | void addFirstSlist(snode** head, snode* node) 318 | { 319 | if (!head) 320 | return; 321 | 322 | if (!node) 323 | return; 324 | 325 | snode* cpnt = *head; 326 | *head = node; 327 | node->next = cpnt; 328 | } 329 | //needs to be developed 330 | void addLastSlist(snode** head, snode* node) 331 | { 332 | if (!head) 333 | return; 334 | 335 | if (!node) 336 | return; 337 | 338 | if (!(*head)) 339 | { 340 | *head = node; 341 | return; 342 | } 343 | snode* cpnt = *head; 344 | while (cpnt->next) 345 | { 346 | cpnt = cpnt->next; 347 | } 348 | cpnt->next = node; 349 | return; 350 | } 351 | //needs to be tested 352 | snode* removeSlist(snode** head, snode* node) 353 | { 354 | if (!head) 355 | return 0; 356 | 357 | if (!(*head)) 358 | return 0; 359 | 360 | if (!node) 361 | return 0; 362 | 363 | snode* ppnt = NULL; 364 | snode* cpnt = *head; 365 | while (cpnt) 366 | { 367 | if (cpnt == node) 368 | { 369 | break; 370 | } 371 | ppnt = cpnt; 372 | cpnt = cpnt->next; 373 | } 374 | if (!cpnt) 375 | return 0; 376 | 377 | if (!ppnt) 378 | { 379 | *head = cpnt->next; 380 | return cpnt; 381 | } 382 | else { 383 | ppnt->next = cpnt->next; 384 | return cpnt; 385 | } 386 | } -------------------------------------------------------------------------------- /FileSpy/ComIface.c: -------------------------------------------------------------------------------- 1 | #include "ComIface.h" 2 | 3 | Procmon* ProcessList = 0; 4 | IOtrace* ChangeList = 0; 5 | 6 | KGUARDED_MUTEX DTMutex; 7 | KGUARDED_MUTEX CLMutex; 8 | 9 | //https://github.com/Microsoft/Windows-driver-samples/blob/master/general/obcallback/driver/tdriver.c 10 | void InitComIface() 11 | { 12 | KeInitializeGuardedMutex(&DTMutex); 13 | KeInitializeGuardedMutex(&CLMutex); 14 | initIOheuristics(); 15 | } 16 | void destroyComIface() 17 | { 18 | return; 19 | } 20 | Procmon* createProcessNode(unsigned long long PID, unsigned long long trustpoints) 21 | { 22 | Procmon* n = ExAllocatePool(NonPagedPool, sizeof(Procmon)); 23 | if (n) 24 | { 25 | RtlZeroMemory(n, sizeof(Procmon)); 26 | n->PID = PID; 27 | n->trustpoints = trustpoints; 28 | return n; 29 | } 30 | return 0; 31 | } 32 | Childproc* createChildNode(unsigned long long PID, Procmon* n) 33 | { 34 | Childproc* c = ExAllocatePool(NonPagedPool, sizeof(Childproc)); 35 | if (c) 36 | { 37 | RtlZeroMemory(c, sizeof(Childproc)); 38 | c->CPID = PID; 39 | c->cpnt = n; 40 | return c; 41 | } 42 | return 0; 43 | } 44 | void updateIO(PUNICODE_STRING sFile, unsigned long long PID) 45 | { 46 | if (!sFile) 47 | return; 48 | 49 | if (!PID) 50 | return; 51 | 52 | KeAcquireGuardedMutex(&DTMutex); 53 | 54 | Procmon * proc = (Procmon*)findSortSlist((Idsnode**)&ProcessList, PID); 55 | if (!proc) 56 | { 57 | KeReleaseGuardedMutex(&DTMutex); 58 | return; 59 | } 60 | IOtrace* IO = proc->IO; 61 | while (IO) 62 | { 63 | if (RtlEqualUnicodeString(sFile, IO->shadowFile,TRUE)) 64 | { 65 | IO->action = 1; //note that a changed occured 66 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Write Action recoreded\n", PID)); 67 | break; 68 | } 69 | IO = IO->next; 70 | } 71 | KeReleaseGuardedMutex(&DTMutex); 72 | } 73 | //hook located in redirectIO 74 | void recordIO(unsigned long long PID,PUNICODE_STRING realFile, PUNICODE_STRING shadowFile) 75 | { 76 | //UNREFERENCED_PARAMETER(realFile); 77 | //UNREFERENCED_PARAMETER(shadowFile); 78 | //UNREFERENCED_PARAMETER(PID); 79 | if (!PID) 80 | return; 81 | 82 | if (!realFile) 83 | return; 84 | 85 | if (!shadowFile) 86 | return; 87 | 88 | KeAcquireGuardedMutex(&DTMutex); 89 | 90 | Procmon* p = (Procmon*)findSortSlist((Idsnode**)&ProcessList, PID); 91 | if (!p) 92 | { 93 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Process Node not found, %ld creating...\n", PID)); 94 | p = createProcessNode(PID, MAXPOINTS); 95 | if (!p) 96 | { 97 | KeReleaseGuardedMutex(&DTMutex); 98 | return; 99 | } 100 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)p); //nodes not there you have to add it 101 | } 102 | 103 | IOtrace* nIO = ExAllocatePool(NonPagedPool, sizeof(IOtrace)); 104 | nIO->realFile = (PUNICODE_STRING)ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); 105 | RtlCopyMemory(nIO->realFile, realFile, sizeof(UNICODE_STRING)); 106 | nIO->realFile->Buffer = (PWCH)ExAllocatePool(NonPagedPool, realFile->MaximumLength); 107 | RtlCopyMemory(nIO->realFile->Buffer, realFile->Buffer, realFile->Length); 108 | 109 | nIO->shadowFile = (PUNICODE_STRING)ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); 110 | RtlCopyMemory(nIO->shadowFile, shadowFile, sizeof(UNICODE_STRING)); 111 | nIO->shadowFile->Buffer = (PWCH)ExAllocatePool(NonPagedPool, shadowFile->MaximumLength); 112 | RtlCopyMemory(nIO->shadowFile->Buffer, shadowFile->Buffer, shadowFile->Length); 113 | 114 | //increment the touched files 115 | p->touchFiles += 1; 116 | 117 | addFirstSlist((snode**)&p->IO, (snode*)nIO); 118 | 119 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "added IOTrace %ld\n %wZ\n %wZ\n", PID, *(nIO->realFile), *(nIO->shadowFile))); 120 | KeReleaseGuardedMutex(&DTMutex); 121 | } 122 | void recordProcess(unsigned long long pPID, unsigned long long cPID) 123 | { 124 | if (!cPID) 125 | return; 126 | 127 | KeAcquireGuardedMutex(&DTMutex); 128 | if (!pPID) 129 | { 130 | //no parent. 131 | Procmon* n = createProcessNode(cPID,MAXPOINTS); 132 | if (!n) 133 | { 134 | KeReleaseGuardedMutex(&DTMutex); 135 | return; 136 | } 137 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "created Process node %d\n", n->PID)); 138 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)n); 139 | KeReleaseGuardedMutex(&DTMutex); 140 | return; 141 | } 142 | else { 143 | Procmon* pnode = (Procmon*)findSortSlist((Idsnode**)&ProcessList, pPID); 144 | Procmon* cnode = createProcessNode(cPID,MAXPOINTS); 145 | if (!cnode) 146 | { 147 | KeReleaseGuardedMutex(&DTMutex); 148 | return; 149 | } 150 | Childproc* childpnt = createChildNode(cPID, cnode); 151 | if (!childpnt) 152 | { 153 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)cnode); 154 | KeReleaseGuardedMutex(&DTMutex); 155 | return; 156 | } 157 | //Parentnode exists 158 | if (pnode) 159 | { 160 | cnode->parent = pnode; 161 | cnode->trustpoints = pnode->trustpoints; 162 | addSortSlist((Idsnode**)&pnode->child, (Idsnode*)childpnt); 163 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)cnode); 164 | } 165 | //parentnode does not exist 166 | else { 167 | pnode = (Procmon*)createProcessNode(pPID,MAXPOINTS); 168 | if (!pnode) 169 | { 170 | ExFreePool(childpnt); 171 | } 172 | else { 173 | addSortSlist((Idsnode**)&pnode->child, (Idsnode*)childpnt); 174 | } 175 | cnode->parent = pnode; 176 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)cnode); 177 | } 178 | } 179 | KeReleaseGuardedMutex(&DTMutex); 180 | } 181 | void inheritProcessNode(Procmon* child) 182 | { 183 | if (!child) 184 | return; 185 | 186 | Procmon * p = child->parent; 187 | Procmon * np = p; 188 | while (p) 189 | { 190 | np = p; 191 | p = p->parent; 192 | } 193 | if (np) 194 | { 195 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Inherit PID:%ld ->> %ld\n", child->PID,np->PID)); 196 | addLastSlist((snode**)&np->IO, (snode*)child->IO); 197 | np->touchFiles += child->touchFiles; 198 | child->IO = 0; 199 | } 200 | } 201 | /* 202 | The litteral main trigger to this whole program 203 | A very important function that triggers the heuristics and decision making of the minifilter 204 | this will determine the very success and failure of this defense 205 | Simple test this needs to be fixed to handle an actual process close 206 | This CODE IS Fixed. 207 | */ 208 | void deleteProcess(unsigned long long cPID) 209 | { 210 | if (!cPID) 211 | return; 212 | 213 | KeAcquireGuardedMutex(&DTMutex); 214 | Procmon* c = (Procmon*)removeSortSlist((Idsnode**)&ProcessList, cPID); 215 | if (!c) 216 | { 217 | KeReleaseGuardedMutex(&DTMutex); 218 | return; 219 | } 220 | if (c->parent && c->child) 221 | { 222 | inheritProcessNode(c); 223 | c->ghost = 1; 224 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)c); 225 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "GHOST1 \nPID:%ld\n", c->PID)); 226 | } 227 | else if (!c->parent && c->child) { 228 | c->ghost = 1; 229 | addSortSlist((Idsnode**)&ProcessList, (Idsnode*)c); 230 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "GHOST2 \nPID:%ld\n", c->PID)); 231 | } 232 | else if (!c->parent && !c->child) { 233 | c->next = 0; 234 | if (c->IO) 235 | { 236 | putProcess(c); 237 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "added proc \nPID:%ld\n", c->PID)); 238 | } 239 | else { 240 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "NO IO Deleting\nPID:%ld\n", c->PID)); 241 | ExFreePool(c); 242 | } 243 | } 244 | else if (c->parent && !c->child) { 245 | inheritProcessNode(c); // this moves the IO 246 | Procmon* p = c->parent; 247 | Childproc* childpnt = (Childproc*)removeSortSlist((Idsnode**)&p->child, c->PID); 248 | if (childpnt) 249 | { 250 | ExFreePool(childpnt); 251 | } 252 | ExFreePool(c); 253 | c = p; 254 | while (c) 255 | { 256 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "LOOP TEST\n")); 257 | childpnt = 0; 258 | p = c->parent; 259 | if (p && c->ghost && !c->child) { 260 | removeSortSlist((Idsnode**)&ProcessList, c->PID); 261 | if (c->IO) 262 | inheritProcessNode(c); 263 | 264 | childpnt = (Childproc*)removeSortSlist((Idsnode**)&p->child, c->PID); 265 | if (childpnt) 266 | { 267 | ExFreePool(childpnt); 268 | } 269 | ExFreePool(c); 270 | } 271 | else if (!p && c->ghost && !c->child) { 272 | removeSortSlist((Idsnode**)&ProcessList, c->PID); 273 | if (c->IO) 274 | { 275 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "added proc2 \nPID:%ld\n", c->PID)); 276 | putProcess(c); 277 | } 278 | else { 279 | ExFreePool(c); 280 | } 281 | } 282 | c = p; 283 | } 284 | } 285 | KeReleaseGuardedMutex(&DTMutex); 286 | } -------------------------------------------------------------------------------- /FileSpy/FileSpySupport.c: -------------------------------------------------------------------------------- 1 | #include "FileSpySupport.h" 2 | UNICODE_STRING proclist[] = { 3 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\explorer.exe"), 4 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\System32\\SearchProtocolHost.exe"), 5 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\SearchIndexer.exe"), 6 | RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\Windows\\SearchFilterHost.exe") 7 | }; 8 | //https://aonprog.wordpress.com/2009/02/16/process-name-and-id-in-file-filter-driver-callbacks/ 9 | BOOLEAN processWhiteList(PFLT_CALLBACK_DATA Data) { 10 | //GetProcessImageFileName 11 | PEPROCESS objCurProcess = IoThreadToProcess(Data->Thread); 12 | PUNICODE_STRING ProcName; 13 | SeLocateProcessImageName(objCurProcess,&ProcName); 14 | unsigned int i = 0; 15 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Proccess, %wZ...\n", *ProcName)); 16 | for (i = 0;i < WHITELISTSIZE;i++) 17 | { 18 | if(RtlEqualUnicodeString(ProcName, &proclist[i], TRUE)) 19 | { 20 | return TRUE; 21 | } 22 | } 23 | return FALSE; 24 | } 25 | BOOLEAN UStrncmp(PUNICODE_STRING dst, PUNICODE_STRING src,USHORT POS) 26 | { 27 | USHORT Len = 0; 28 | if (dst->Length-(POS*2) <= src->Length) 29 | { 30 | Len = dst->Length-(POS*2); 31 | } 32 | else{ 33 | return FALSE; 34 | } 35 | int i = 0; 36 | for (i = 0;i < (Len/2);i++) 37 | { 38 | if (dst->Buffer[i+POS] != src->Buffer[i]) 39 | { 40 | return FALSE; 41 | } 42 | } 43 | return TRUE; 44 | } 45 | USHORT findLashSlash(PUNICODE_STRING pnt) 46 | { 47 | USHORT i = 0; 48 | USHORT POS = 0; 49 | USHORT Len = pnt->Length / 2; 50 | for (i = 0;i < Len;i++) 51 | { 52 | if (pnt->Buffer[i] == L'\\') 53 | { 54 | POS = i; 55 | } 56 | } 57 | return POS; 58 | } 59 | void freeUnicodeString(PUNICODE_STRING str) 60 | { 61 | ExFreePool(str->Buffer); 62 | } 63 | void createUnicodeString(PUNICODE_STRING dst,USHORT MaxSize) 64 | { 65 | dst->Length = 0; 66 | dst->Buffer = (PWCH)ExAllocatePool(NonPagedPool, MaxSize); 67 | dst->MaximumLength = MaxSize; 68 | } 69 | void unicodePosCat(PUNICODE_STRING dst, PUNICODE_STRING src, USHORT start) 70 | { 71 | USHORT i = 0; 72 | USHORT Len = src->Length / 2; 73 | for (i = 0;i < Len;i++) 74 | { 75 | dst->Buffer[i + start] = src->Buffer[i]; 76 | } 77 | dst->Length += src->Length; 78 | } 79 | 80 | //https://aonprog.wordpress.com/2009/02/16/process-name-and-id-in-file-filter-driver-callbacks/ 81 | void generateExt(PUNICODE_STRING newExt, PFLT_CALLBACK_DATA Data) { 82 | UNICODE_STRING PID; 83 | 84 | PEPROCESS objCurProcess = IoThreadToProcess(Data->Thread); 85 | unsigned long long ProcId = (unsigned long long)PsGetProcessId(objCurProcess); 86 | PID.Buffer = (PWSTR)ExAllocatePool(NonPagedPool, 32); 87 | PID.Length = 0; 88 | PID.MaximumLength = 32; 89 | RtlIntegerToUnicodeString((ULONG)ProcId, 0, &PID); 90 | 91 | newExt->Buffer = (PWSTR)ExAllocatePool(NonPagedPool, PID.Length+4); 92 | newExt->Length = 0; 93 | newExt->MaximumLength = PID.Length + 4; 94 | newExt->Length = 4; 95 | newExt->Buffer[0] = L'.'; 96 | newExt->Buffer[1] = L'$'; 97 | unicodePosCat(newExt, &PID, 2); 98 | ExFreePool(PID.Buffer); 99 | } 100 | BOOLEAN redirectIO(PCFLT_RELATED_OBJECTS FltObjects,PFLT_CALLBACK_DATA Data, PFLT_FILE_NAME_INFORMATION nameInfo) 101 | { 102 | /*http://www.progtown.com/topic259586-fltcreatefile-in-precreate-callback.html 103 | */ 104 | OBJECT_ATTRIBUTES objATT; 105 | HANDLE FHANDLE; 106 | IO_STATUS_BLOCK ioStatusBlock; 107 | NTSTATUS status; 108 | PFILE_OBJECT realFileObject; 109 | InitializeObjectAttributes(&objATT, &nameInfo->Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 110 | status = FltCreateFileEx( 111 | FltObjects->Filter, 112 | FltObjects->Instance, 113 | &FHANDLE, 114 | &realFileObject, 115 | FILE_READ_DATA, 116 | &objATT, 117 | &ioStatusBlock, 118 | (PLARGE_INTEGER)NULL, 119 | FILE_ATTRIBUTE_NORMAL, 120 | FILE_SHARE_READ, 121 | FILE_OPEN, 122 | 0, 123 | NULL, 124 | 0, 125 | IO_IGNORE_SHARE_ACCESS_CHECK 126 | ); 127 | if (!NT_SUCCESS(status)) 128 | { 129 | return FALSE; 130 | } 131 | else { 132 | UNICODE_STRING newExt; 133 | UNICODE_STRING reTarget; 134 | generateExt(&newExt, Data); 135 | createUnicodeString(&reTarget, nameInfo->Name.Length + newExt.Length + 2); 136 | RtlCopyUnicodeString(&reTarget, &nameInfo->Name); 137 | unicodePosCat(&reTarget, &newExt, reTarget.Length / 2); 138 | freeUnicodeString(&newExt); 139 | 140 | HANDLE THANDLE; 141 | IO_STATUS_BLOCK ioStatBlock2; 142 | OBJECT_ATTRIBUTES objATT3; 143 | InitializeObjectAttributes(&objATT3, &reTarget, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 144 | status = FltCreateFile( 145 | FltObjects->Filter, 146 | FltObjects->Instance, 147 | &THANDLE, 148 | FILE_READ_DATA | FILE_WRITE_DATA | DELETE, 149 | &objATT3, 150 | &ioStatBlock2, 151 | (PLARGE_INTEGER)NULL, 152 | FILE_ATTRIBUTE_NORMAL, 153 | FILE_SHARE_READ|FILE_SHARE_WRITE, 154 | FILE_OPEN, //test replace with overwrite 155 | 0, 156 | NULL, 157 | 0, 158 | IO_IGNORE_SHARE_ACCESS_CHECK 159 | ); 160 | if (NT_SUCCESS(status)) 161 | { 162 | FltClose(THANDLE); 163 | } else { 164 | HANDLE OUTHANDLE; 165 | IO_STATUS_BLOCK ioStatBlock; 166 | OBJECT_ATTRIBUTES objATT2; 167 | PFILE_OBJECT shadowfile; 168 | InitializeObjectAttributes(&objATT2, &reTarget, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 169 | status = FltCreateFileEx( 170 | FltObjects->Filter, 171 | FltObjects->Instance, 172 | &OUTHANDLE, 173 | &shadowfile, 174 | FILE_READ_DATA | FILE_WRITE_DATA | DELETE, 175 | &objATT2, 176 | &ioStatBlock, 177 | (PLARGE_INTEGER)NULL, 178 | FILE_ATTRIBUTE_NORMAL, 179 | FILE_SHARE_READ | FILE_SHARE_WRITE, 180 | FILE_OVERWRITE_IF, //test replace with overwrite 181 | 0, 182 | NULL, 183 | 0, 184 | IO_IGNORE_SHARE_ACCESS_CHECK 185 | ); 186 | if (NT_SUCCESS(status)) 187 | { 188 | unsigned char* buf = FltAllocatePoolAlignedWithTag(FltObjects->Instance, NonPagedPool, 1024, 'read'); 189 | LARGE_INTEGER Pos; 190 | Pos.HighPart = 0; 191 | Pos.LowPart = 0; 192 | LARGE_INTEGER oldPos; 193 | oldPos.HighPart = 0; 194 | oldPos.LowPart = 0; 195 | ULONG readBytes = 0; 196 | do { 197 | NTSTATUS s = STATUS_SUCCESS; 198 | readBytes = 0; 199 | s = FltReadFile( 200 | FltObjects->Instance, 201 | realFileObject, 202 | &Pos, 203 | 1024, 204 | buf, 205 | FLTFL_IO_OPERATION_NON_CACHED, 206 | &readBytes, 207 | 0, 208 | 0 209 | ); 210 | Pos.QuadPart += readBytes; 211 | FltWriteFile( 212 | FltObjects->Instance, 213 | shadowfile, 214 | &oldPos, 215 | readBytes, 216 | buf, 217 | FLTFL_IO_OPERATION_NON_CACHED, 218 | 0, 219 | 0, 220 | 0 221 | ); 222 | oldPos.QuadPart += readBytes; 223 | } while (readBytes); 224 | FltFreePoolAlignedWithTag(FltObjects->Instance, buf, 'read'); 225 | FltClose(OUTHANDLE); 226 | PEPROCESS objCurProcess = IoThreadToProcess(Data->Thread); 227 | unsigned long long PID = (unsigned long long)PsGetProcessId(objCurProcess); 228 | if (PID != 4 && PID != 0) 229 | recordIO(PID, &nameInfo->Name, &reTarget); 230 | /** 231 | recording IO here 232 | **/ 233 | } 234 | } 235 | //bug fix that system becomes the main parent 236 | 237 | Data->IoStatus.Information = IO_REPARSE; 238 | Data->IoStatus.Status = STATUS_REPARSE; 239 | Data->Iopb->TargetFileObject->RelatedFileObject = NULL; 240 | ExFreePool(Data->Iopb->TargetFileObject->FileName.Buffer); 241 | Data->Iopb->TargetFileObject->FileName.Buffer = reTarget.Buffer; 242 | Data->Iopb->TargetFileObject->FileName.Length = reTarget.Length; 243 | Data->Iopb->TargetFileObject->FileName.MaximumLength = reTarget.MaximumLength; 244 | FltSetCallbackDataDirty(Data); 245 | FltClose(FHANDLE); 246 | return TRUE; 247 | } 248 | 249 | } 250 | BOOLEAN WCStrncmp(wchar_t* dst, wchar_t* src, unsigned int len) 251 | { 252 | unsigned int i = 0; 253 | for (i = 0;i < len;i++) 254 | { 255 | if (dst[i] != src[i]) 256 | { 257 | return FALSE; 258 | } 259 | } 260 | return TRUE; 261 | } 262 | /* 263 | BOOLEAN redirectRenameIO(PFLT_CALLBACK_DATA Data) 264 | { 265 | /*UNICODE_STRING newExt; 266 | generateExt(&newExt, Data); 267 | PFILE_RENAME_INFORMATION fri = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer; 268 | 269 | wchar_t * newpath = ExAllocatePool(NonPagedPool, fri->FileNameLength + newExt.Length); 270 | RtlCopyMemory(newpath, fri->FileName, fri->FileNameLength); 271 | RtlCopyMemory(&newpath[fri->FileNameLength/2], newExt.Buffer, newExt.Length); 272 | 273 | PFILE_RENAME_INFORMATION newFri = ExAllocatePool(NonPagedPool, sizeof(FILE_RENAME_INFORMATION)); 274 | 275 | RtlCopyMemory(newFri->FileName, newpath, fri->FileNameLength + newExt.Length); 276 | newFri->FileNameLength = fri->FileNameLength + newExt.Length; 277 | newFri->Flags = fri->Flags; 278 | newFri->ReplaceIfExists = fri->ReplaceIfExists; 279 | newFri->RootDirectory = fri->RootDirectory; 280 | 281 | Data->Iopb->Parameters.SetFileInformation.InfoBuffer = newFri; 282 | ExFreePool(fri); 283 | ExFreePool(newpath); 284 | 285 | Data->IoStatus.Information = IO_REPARSE; 286 | Data->IoStatus.Status = STATUS_REPARSE; 287 | FltSetCallbackDataDirty(Data); 288 | 289 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, " new path %ws :::: ext %wZ\n", newpath,newExt)); 290 | return TRUE; 291 | } 292 | */ -------------------------------------------------------------------------------- /FileSpy/FileSpy.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {70B30B57-0EF7-4D7B-BAA2-0CE7F9A9C6A8} 49 | {f2f62967-0815-4fd7-9b86-6eedcac766eb} 50 | v4.5 51 | 12.0 52 | Debug 53 | Win32 54 | FileSpy 55 | 56 | 57 | 58 | Windows10 59 | true 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | WDM 63 | 64 | 65 | Windows10 66 | false 67 | WindowsKernelModeDriver10.0 68 | Driver 69 | WDM 70 | 71 | 72 | Windows7 73 | true 74 | WindowsKernelModeDriver10.0 75 | Driver 76 | WDM 77 | Desktop 78 | true 79 | 80 | 81 | Windows10 82 | false 83 | WindowsKernelModeDriver10.0 84 | Driver 85 | WDM 86 | 87 | 88 | Windows10 89 | true 90 | WindowsKernelModeDriver10.0 91 | Driver 92 | WDM 93 | 94 | 95 | Windows10 96 | false 97 | WindowsKernelModeDriver10.0 98 | Driver 99 | WDM 100 | 101 | 102 | Windows10 103 | true 104 | WindowsKernelModeDriver10.0 105 | Driver 106 | WDM 107 | 108 | 109 | Windows10 110 | false 111 | WindowsKernelModeDriver10.0 112 | Driver 113 | WDM 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | DbgengKernelDebugger 125 | 126 | 127 | DbgengKernelDebugger 128 | 129 | 130 | DbgengKernelDebugger 131 | 132 | 133 | DbgengKernelDebugger 134 | 135 | 136 | DbgengKernelDebugger 137 | 138 | 139 | DbgengKernelDebugger 140 | 141 | 142 | DbgengKernelDebugger 143 | 144 | 145 | DbgengKernelDebugger 146 | 147 | 148 | 149 | fltmgr.lib;%(AdditionalDependencies) 150 | 151 | 152 | 153 | 154 | fltmgr.lib;%(AdditionalDependencies) 155 | 156 | 157 | 158 | 159 | fltmgr.lib;%(AdditionalDependencies) 160 | /INTEGRITYCHECK %(AdditionalOptions) 161 | 162 | 163 | 164 | 165 | fltmgr.lib;%(AdditionalDependencies) 166 | 167 | 168 | 169 | 170 | fltmgr.lib;%(AdditionalDependencies) 171 | 172 | 173 | 174 | 175 | fltmgr.lib;%(AdditionalDependencies) 176 | 177 | 178 | 179 | 180 | fltmgr.lib;%(AdditionalDependencies) 181 | 182 | 183 | 184 | 185 | fltmgr.lib;%(AdditionalDependencies) 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /FileSpy/IOheuristics.c: -------------------------------------------------------------------------------- 1 | #include "IOheuristics.h" 2 | 3 | Procmon* Pact; // contains all the process to test 4 | IOtrace* IOact; //contains all the list of the trace IO need to apply 5 | int _fltused; 6 | KGUARDED_MUTEX IOMutex; 7 | KGUARDED_MUTEX PMutex; 8 | /* 9 | initialies callback functions to redirect into create 10 | registers simaphores 11 | */ 12 | void initIOheuristics() 13 | { 14 | KeInitializeGuardedMutex(&IOMutex); 15 | KeInitializeGuardedMutex(&PMutex); 16 | Pact = 0; 17 | IOact = 0; 18 | } 19 | void overWriteFile(PCFLT_RELATED_OBJECTS FltObjects,PUNICODE_STRING rFile, PUNICODE_STRING sFile) 20 | { 21 | OBJECT_ATTRIBUTES objATT; 22 | HANDLE SHANDLE; 23 | IO_STATUS_BLOCK ioStatusBlock; 24 | NTSTATUS status; 25 | PFILE_OBJECT sFileObject; 26 | 27 | InitializeObjectAttributes(&objATT, sFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 28 | status = FltCreateFileEx( 29 | FltObjects->Filter, 30 | FltObjects->Instance, 31 | &SHANDLE, 32 | &sFileObject, 33 | FILE_READ_DATA | DELETE, 34 | &objATT, 35 | &ioStatusBlock, 36 | (PLARGE_INTEGER)NULL, 37 | FILE_ATTRIBUTE_NORMAL, 38 | FILE_SHARE_READ, 39 | FILE_OPEN, 40 | FILE_DELETE_ON_CLOSE, 41 | NULL, 42 | 0, 43 | IO_IGNORE_SHARE_ACCESS_CHECK 44 | ); 45 | if (!NT_SUCCESS(status)) 46 | { 47 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "failed shadow File %wZ\n", sFile)); 48 | return; 49 | } 50 | HANDLE RHANDLE; 51 | IO_STATUS_BLOCK ioStatBlock; 52 | OBJECT_ATTRIBUTES objATT2; 53 | PFILE_OBJECT rFileObject; 54 | InitializeObjectAttributes(&objATT2, rFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 55 | status = FltCreateFileEx( 56 | FltObjects->Filter, 57 | FltObjects->Instance, 58 | &RHANDLE, 59 | &rFileObject, 60 | FILE_READ_DATA | FILE_WRITE_DATA | DELETE, 61 | &objATT2, 62 | &ioStatBlock, 63 | (PLARGE_INTEGER)NULL, 64 | FILE_ATTRIBUTE_NORMAL, 65 | FILE_SHARE_READ | FILE_SHARE_WRITE, 66 | FILE_OVERWRITE_IF, //test replace with overwrite 67 | 0, 68 | NULL, 69 | 0, 70 | IO_IGNORE_SHARE_ACCESS_CHECK 71 | ); 72 | if (!NT_SUCCESS(status)) 73 | { 74 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "failed real File %wZ\n", sFile)); 75 | FltClose(SHANDLE); 76 | return; 77 | } 78 | unsigned char* buf = FltAllocatePoolAlignedWithTag(FltObjects->Instance, NonPagedPool, 1024, 'IOup'); 79 | LARGE_INTEGER Pos; 80 | Pos.HighPart = 0; 81 | Pos.LowPart = 0; 82 | LARGE_INTEGER oldPos; 83 | oldPos.HighPart = 0; 84 | oldPos.LowPart = 0; 85 | ULONG readBytes = 0; 86 | do { 87 | NTSTATUS s = STATUS_SUCCESS; 88 | readBytes = 0; 89 | s = FltReadFile( 90 | FltObjects->Instance, 91 | sFileObject, 92 | &Pos, 93 | 1024, 94 | buf, 95 | FLTFL_IO_OPERATION_NON_CACHED, 96 | &readBytes, 97 | 0, 98 | 0 99 | ); 100 | Pos.QuadPart += readBytes; 101 | FltWriteFile( 102 | FltObjects->Instance, 103 | rFileObject, 104 | &oldPos, 105 | readBytes, 106 | buf, 107 | FLTFL_IO_OPERATION_NON_CACHED, 108 | 0, 109 | 0, 110 | 0 111 | ); 112 | oldPos.QuadPart += readBytes; 113 | } while (readBytes); 114 | FltFreePoolAlignedWithTag(FltObjects->Instance, buf, 'IOup'); 115 | FltClose(SHANDLE); 116 | FltClose(RHANDLE); 117 | } 118 | void deleteFile(PCFLT_RELATED_OBJECTS FltObjects, PUNICODE_STRING sFile) 119 | { 120 | OBJECT_ATTRIBUTES objATT; 121 | HANDLE SHANDLE; 122 | IO_STATUS_BLOCK ioStatusBlock; 123 | NTSTATUS status; 124 | PFILE_OBJECT sFileObject; 125 | 126 | InitializeObjectAttributes(&objATT, sFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 127 | status = FltCreateFileEx( 128 | FltObjects->Filter, 129 | FltObjects->Instance, 130 | &SHANDLE, 131 | &sFileObject, 132 | FILE_READ_DATA | DELETE, 133 | &objATT, 134 | &ioStatusBlock, 135 | (PLARGE_INTEGER)NULL, 136 | FILE_ATTRIBUTE_NORMAL, 137 | FILE_SHARE_READ, 138 | FILE_OPEN, 139 | FILE_DELETE_ON_CLOSE, 140 | NULL, 141 | 0, 142 | IO_IGNORE_SHARE_ACCESS_CHECK 143 | ); 144 | 145 | if (NT_SUCCESS(status)) 146 | FltClose(SHANDLE); 147 | } 148 | void IOhook(PCFLT_RELATED_OBJECTS FltObjects) 149 | { 150 | KeAcquireGuardedMutex(&IOMutex); 151 | if (!IOact) 152 | { 153 | KeReleaseGuardedMutex(&IOMutex); 154 | return; 155 | } 156 | IOtrace* IO = (IOtrace*)removeSlist((snode**)&IOact,(snode*)IOact); 157 | while (IO) 158 | { 159 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "change real File %wZ\n", *IO->realFile)); 160 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "change shdw File %wZ\n", *IO->shadowFile)); 161 | 162 | if (IO->action) 163 | overWriteFile(FltObjects, IO->realFile, IO->shadowFile); 164 | else 165 | deleteFile(FltObjects, IO->shadowFile); 166 | 167 | ExFreePool(IO->realFile->Buffer); 168 | ExFreePool(IO->shadowFile->Buffer); 169 | ExFreePool(IO->realFile); 170 | ExFreePool(IO->shadowFile); 171 | ExFreePool(IO); 172 | 173 | IO = (IOtrace*)removeSlist((snode**)&IOact, (snode*)IOact); 174 | } 175 | 176 | KeReleaseGuardedMutex(&IOMutex); 177 | return; 178 | } 179 | void hhook(PCFLT_RELATED_OBJECTS FltObjects) 180 | { 181 | KeAcquireGuardedMutex(&PMutex); 182 | if (!Pact) 183 | { 184 | KeReleaseGuardedMutex(&PMutex); 185 | return; 186 | } 187 | Procmon* proc = (Procmon*)removeSlist((snode**)&Pact, (snode*)Pact); 188 | KeReleaseGuardedMutex(&PMutex); 189 | 190 | if (!proc) 191 | { 192 | return; 193 | } 194 | 195 | IOtrace* IO = 0; 196 | for (IO = proc->IO;IO!=0;IO = IO->next) 197 | { 198 | int result = 0; 199 | result = shannonEntropy(FltObjects, IO->shadowFile); 200 | if (0 > result) 201 | { 202 | proc->delFiles += 1; 203 | continue; 204 | } 205 | if (result >= ENCRYPTTHOLD) //Checks for entropy to be above 7. In quick/informal testing this indicates encryption 206 | { 207 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "shadowFile is encrypted\n")); 208 | if (IO->action) { 209 | proc->highEntropyFiles += 1; 210 | } 211 | } 212 | } 213 | 214 | if (!proc->touchFiles) 215 | { 216 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "no touched files\n")); 217 | ExFreePool(proc); 218 | return; 219 | } 220 | 221 | 222 | double delRmScore = (double)proc->delFiles / proc->touchFiles * MAXDELETEPNTS; 223 | double entRmScore = (double)proc->highEntropyFiles / proc->touchFiles * MAXENTROPYPNTS; 224 | long score = MAXPOINTS - ((long)delRmScore + (long)entRmScore); 225 | 226 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "delScore %ld\n entRmScore %ld\n score %ld\n",(long)delRmScore,(long)entRmScore,(long)score)); 227 | 228 | if (score >= IOThold) 229 | { 230 | KeAcquireGuardedMutex(&IOMutex); 231 | ExFreePool(proc); 232 | addLastSlist((snode**)&IOact, (snode*)proc->IO); 233 | KeReleaseGuardedMutex(&IOMutex); 234 | } 235 | else { 236 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Malicious Node Detected!!\n")); 237 | IOtrace* nIO = proc->IO; 238 | IO = proc->IO; 239 | proc->IO = 0; 240 | while (IO) 241 | { 242 | nIO = IO->next; 243 | 244 | 245 | ExFreePool(IO->realFile->Buffer); 246 | ExFreePool(IO->realFile); 247 | 248 | deleteFile(FltObjects, IO->shadowFile); 249 | 250 | ExFreePool(IO->shadowFile->Buffer); 251 | ExFreePool(IO->shadowFile); 252 | ExFreePool(IO); 253 | 254 | IO = nIO; 255 | } 256 | ExFreePool(proc); 257 | } 258 | return; 259 | } 260 | void putProcess(Procmon* p) 261 | { 262 | if (!p) 263 | return; 264 | 265 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Put proccess node for testing %d\n", p->PID)); 266 | KeAcquireGuardedMutex(&PMutex); 267 | addLastSlist((snode**)&Pact, (snode*)p); 268 | KeReleaseGuardedMutex(&PMutex); 269 | } 270 | 271 | /* 272 | This is the shannon entropy function seth you can play in here 273 | //http://stackoverflow.com/questions/25985005/calculating-entropy-in-c 274 | */ 275 | //estimation of a log function 276 | int log2f(int num) 277 | { 278 | return num; 279 | } 280 | int shannonEntropy(PCFLT_RELATED_OBJECTS FltObjects,PUNICODE_STRING f) 281 | { 282 | double byte_count[256]; 283 | ULONG i = 0; 284 | double count = 0.0; 285 | double entropy = 0.0; 286 | int length = 0; 287 | 288 | 289 | OBJECT_ATTRIBUTES objATT; 290 | HANDLE FHANDLE; 291 | IO_STATUS_BLOCK ioStatusBlock; 292 | NTSTATUS status; 293 | PFILE_OBJECT fFileObject; 294 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "shannon Entroy %wZ\n", *f)); 295 | InitializeObjectAttributes(&objATT, f, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); 296 | status = FltCreateFileEx( 297 | FltObjects->Filter, 298 | FltObjects->Instance, 299 | &FHANDLE, 300 | &fFileObject, 301 | FILE_READ_DATA, 302 | &objATT, 303 | &ioStatusBlock, 304 | (PLARGE_INTEGER)NULL, 305 | FILE_ATTRIBUTE_NORMAL, 306 | FILE_SHARE_READ, 307 | FILE_OPEN, 308 | 0, 309 | NULL, 310 | 0, 311 | IO_IGNORE_SHARE_ACCESS_CHECK 312 | ); 313 | 314 | if (!NT_SUCCESS(status)) 315 | return -1; 316 | // do math 317 | 318 | unsigned char* buf = FltAllocatePoolAlignedWithTag(FltObjects->Instance, NonPagedPool, 1024, 'shen'); 319 | LARGE_INTEGER Pos; 320 | Pos.HighPart = 0; 321 | Pos.LowPart = 0; 322 | LARGE_INTEGER oldPos; 323 | oldPos.HighPart = 0; 324 | oldPos.LowPart = 0; 325 | ULONG readBytes = 0; 326 | //RtlZeroMemory(byte_count, 256); 327 | for (i = 0; i < 256; i++) 328 | { 329 | byte_count[i] = 0.0; 330 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Print Shannon Entroy cleared byte_count[%ld]: %ld\n", i, byte_count[i])); //Test to see if buffer being cleared properly 331 | } 332 | do { 333 | NTSTATUS s = STATUS_SUCCESS; 334 | readBytes = 0; 335 | s = FltReadFile( 336 | FltObjects->Instance, 337 | fFileObject, 338 | &Pos, 339 | 1024, 340 | buf, 341 | FLTFL_IO_OPERATION_NON_CACHED, 342 | &readBytes, 343 | 0, 344 | 0 345 | ); 346 | Pos.QuadPart += readBytes; 347 | //Read in byte & store # of each byte 348 | //http://stackoverflow.com/questions/25985005/calculating-entropy-in-c 349 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Print Shannon Entroy readBytes: %ld\n", readBytes)); //Test to see if reading from real file 350 | for (i = 0; i < readBytes; i++) 351 | { 352 | byte_count[(int)buf[i]]++; 353 | length++; 354 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Print Shannon Entroy (int)buf[i]: %ld\n", (int)buf[i])); //Check what's actually going in to byte_count 355 | } 356 | RtlZeroMemory(buf, 1024); 357 | } while (readBytes); 358 | 359 | //Calculate entropy, should match the given algorithm now (tested algorithm on another machine) 360 | for (i = 0; i < 256; i++) 361 | { 362 | if ((byte_count[i] != 0.0) && (length != 0)) 363 | { 364 | count = (double) byte_count[i] / (double) length; 365 | entropy += -count * log2(count); 366 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Print Shannon Entroy math: i = %ld; byte_count[i] = %ld; length = %ld; count %ld; entropy %ld\n", i, (int)byte_count[i], length, (int)count, (int)entropy)); 367 | } 368 | } 369 | FltFreePoolAlignedWithTag(FltObjects->Instance, buf, 'shen'); 370 | FltClose(FHANDLE); 371 | entropy = entropy * 10000; //Basically move decimal places over so they can be seen as ints 372 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x8, "Shannon Entroy result %ld\n", (int)entropy)); 373 | return (int)entropy; 374 | } 375 | 376 | double log2(double value) { 377 | return ln(value) * M_LOG2E; 378 | } 379 | 380 | 381 | double ln(double value) { 382 | short reciprocal = 0; 383 | double x = 0; 384 | 385 | if (value > 2.0) {// Utilize ln(x) = -ln(1/x) for accuracy 386 | value = 1 / value; 387 | reciprocal = 1; 388 | } 389 | x = approx_log(value); 390 | 391 | if (reciprocal) { //Correct for the ln(1/x) = -ln(x) 392 | x = x * -1; 393 | } 394 | return x; 395 | } 396 | 397 | double power(double x, int exp) { 398 | int counter = exp; 399 | double result = x; 400 | if (exp == 0) { //x^0 = 1 401 | return 1; 402 | } 403 | while (counter > 1) { //Do exponentiation 404 | result = result*x; 405 | counter--; 406 | } 407 | return result; 408 | } 409 | 410 | double approx_log(double x) { 411 | 412 | double result = 0; 413 | int count = 1; 414 | while (count < 1000) { //The constant 1000 is a "precision" indicator, maybe change if a performance hit? 415 | result += power(-1, count + 1) * (power((x - 1), count) / count); 416 | count++; 417 | } 418 | return result; 419 | } -------------------------------------------------------------------------------- /FileSpy/FileSpy.c: -------------------------------------------------------------------------------- 1 | #include "FileSpy.h" 2 | 3 | 4 | NTSTATUS 5 | FileSpyInstanceSetup ( 6 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 7 | _In_ FLT_INSTANCE_SETUP_FLAGS Flags, 8 | _In_ DEVICE_TYPE VolumeDeviceType, 9 | _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType 10 | ) 11 | { 12 | UNREFERENCED_PARAMETER( FltObjects ); 13 | UNREFERENCED_PARAMETER( Flags ); 14 | UNREFERENCED_PARAMETER( VolumeDeviceType ); 15 | UNREFERENCED_PARAMETER( VolumeFilesystemType ); 16 | 17 | PAGED_CODE(); 18 | 19 | PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, 20 | ("FileSpy!FileSpyInstanceSetup: Entered\n") ); 21 | 22 | return STATUS_SUCCESS; 23 | } 24 | NTSTATUS 25 | FileSpyInstanceQueryTeardown ( 26 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 27 | _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags 28 | ) 29 | { 30 | UNREFERENCED_PARAMETER( FltObjects ); 31 | UNREFERENCED_PARAMETER( Flags ); 32 | 33 | PAGED_CODE(); 34 | 35 | PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, 36 | ("FileSpy!FileSpyInstanceQueryTeardown: Entered\n") ); 37 | 38 | return STATUS_SUCCESS; 39 | } 40 | 41 | VOID 42 | FileSpyInstanceTeardownStart( 43 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 44 | _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags 45 | ) 46 | { 47 | UNREFERENCED_PARAMETER(FltObjects); 48 | UNREFERENCED_PARAMETER(Flags); 49 | 50 | PAGED_CODE(); 51 | 52 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 53 | ("FileSpy!FileSpyInstanceTeardownStart: Entered\n")); 54 | } 55 | VOID 56 | FileSpyInstanceTeardownComplete( 57 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 58 | _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags 59 | ) 60 | { 61 | UNREFERENCED_PARAMETER(FltObjects); 62 | UNREFERENCED_PARAMETER(Flags); 63 | 64 | PAGED_CODE(); 65 | 66 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 67 | ("FileSpy!FileSpyInstanceTeardownComplete: Entered\n")); 68 | } 69 | NTSTATUS 70 | DriverEntry( 71 | _In_ PDRIVER_OBJECT DriverObject, 72 | _In_ PUNICODE_STRING RegistryPath 73 | ) 74 | { 75 | NTSTATUS status; 76 | UNREFERENCED_PARAMETER(RegistryPath); 77 | 78 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 79 | ("FileSpy!DriverEntry: Entered\n")); 80 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "Entry\n")); 81 | status = FltRegisterFilter(DriverObject, 82 | &FilterRegistration, 83 | &gFilterHandle); 84 | 85 | FLT_ASSERT(NT_SUCCESS(status)); 86 | InitComIface(); 87 | if (NT_SUCCESS(status)) { 88 | status = FltStartFiltering(gFilterHandle); 89 | if (!NT_SUCCESS(status)) { 90 | 91 | FltUnregisterFilter(gFilterHandle); 92 | return status; 93 | } 94 | status = PsSetCreateProcessNotifyRoutineEx(&CreateProcessNotifyEx, FALSE); 95 | if (!NT_SUCCESS(status)) 96 | { 97 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "failed to register proctrace\n")); 98 | FltUnregisterFilter(gFilterHandle); 99 | return status; 100 | } 101 | } 102 | return status; 103 | } 104 | 105 | NTSTATUS 106 | FileSpyUnload( 107 | _In_ FLT_FILTER_UNLOAD_FLAGS Flags 108 | ) 109 | { 110 | UNREFERENCED_PARAMETER(Flags); 111 | 112 | PAGED_CODE(); 113 | 114 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 115 | ("FileSpy!FileSpyUnload: Entered\n")); 116 | 117 | FltUnregisterFilter(gFilterHandle); 118 | PsSetCreateProcessNotifyRoutineEx(&CreateProcessNotifyEx, TRUE); 119 | return STATUS_SUCCESS; 120 | } 121 | FLT_PREOP_CALLBACK_STATUS 122 | FileSpyPreWrite( 123 | _Inout_ PFLT_CALLBACK_DATA Data, 124 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 125 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 126 | ) 127 | { 128 | UNREFERENCED_PARAMETER(Data); 129 | UNREFERENCED_PARAMETER(FltObjects); 130 | UNREFERENCED_PARAMETER(CompletionContext); 131 | 132 | PFLT_FILE_NAME_INFORMATION nameInfo; 133 | 134 | 135 | if (FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE)) { 136 | 137 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 138 | } 139 | if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY)) { 140 | 141 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 142 | } 143 | if (processWhiteList(Data)) 144 | { 145 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 146 | } 147 | //dont use FLT_FILE_NAME_NORMALIZED its slow as fuck for pre_create 148 | NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo); 149 | if (!NT_SUCCESS(status)) 150 | { 151 | // KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "potential file tunnel\n")); 152 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 153 | } 154 | if (UStrncmp(&DirProtect, &nameInfo->ParentDir, 0)) 155 | { 156 | FltParseFileNameInformation(nameInfo); 157 | PEPROCESS objCurProcess = IoThreadToProcess(Data->Thread); 158 | unsigned long long PID = (unsigned long long)PsGetProcessId(objCurProcess); 159 | if (PID != 4 && PID != 0) 160 | { 161 | KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "wrote to %wZ\n", nameInfo->Name)); 162 | updateIO(&nameInfo->Name, PID); 163 | } 164 | FltReleaseFileNameInformation(nameInfo); 165 | } 166 | return FLT_PREOP_SUCCESS_WITH_CALLBACK; 167 | } 168 | FLT_POSTOP_CALLBACK_STATUS 169 | FileSpyPostWrite( 170 | _Inout_ PFLT_CALLBACK_DATA Data, 171 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 172 | _In_opt_ PVOID CompletionContext, 173 | _In_ FLT_POST_OPERATION_FLAGS Flags 174 | ) 175 | { 176 | UNREFERENCED_PARAMETER(Data); 177 | UNREFERENCED_PARAMETER(FltObjects); 178 | UNREFERENCED_PARAMETER(CompletionContext); 179 | UNREFERENCED_PARAMETER(Flags); 180 | 181 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 182 | ("FileSpy!FileSpyPostOperation: Entered\n")); 183 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "PostOp\n")); 184 | return FLT_POSTOP_FINISHED_PROCESSING;; 185 | } 186 | /* 187 | 188 | 189 | MIGHT BE REMOVED as it holds no need for it 190 | 191 | */ 192 | FileSpyPreSetInfo( 193 | _Inout_ PFLT_CALLBACK_DATA Data, 194 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 195 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 196 | ) 197 | { 198 | UNREFERENCED_PARAMETER(FltObjects); 199 | UNREFERENCED_PARAMETER(CompletionContext); 200 | NTSTATUS status; 201 | PFLT_FILE_NAME_INFORMATION nameInfo; 202 | 203 | if (FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE)) { 204 | 205 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 206 | } 207 | if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY)) { 208 | 209 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 210 | } 211 | if (processWhiteList(Data)) 212 | { 213 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 214 | } 215 | //need to test if the rename is going to be in the destination of just ioredirect it. 216 | if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation) 217 | { 218 | PFILE_RENAME_INFORMATION fri = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer; 219 | if (WCStrncmp(fri->FileName, wdirprotect, 37)) 220 | { 221 | //This is when the file is going to be overwritten through the rename process of either copy/move for now it may be just denied its accesss 222 | //preform IO redirect 223 | //Just denied it for right now.... this needs to be an IO redirect but I do not have a solution for it 224 | Data->IoStatus.Status = STATUS_ACCESS_DENIED; 225 | Data->IoStatus.Information = 0; 226 | return FLT_PREOP_COMPLETE; 227 | } 228 | } 229 | status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo); 230 | if (NT_SUCCESS(status)) 231 | { 232 | status = FltParseFileNameInformation(nameInfo); 233 | if (NT_SUCCESS(status)) 234 | { 235 | if (UStrncmp(&DirProtect, &nameInfo->ParentDir, 0)) 236 | { 237 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "setInfo %wZ\n %ld\n", nameInfo->Name, Data->Iopb->Parameters.SetFileInformation.FileInformationClass)); 238 | //https://www.osronline.com/showthread.cfm?link=226825 239 | if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation && 240 | ((PFILE_DISPOSITION_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer)->DeleteFile) 241 | { 242 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "File Delete %wZ %d\n", nameInfo->Name, Data->Iopb->Parameters.SetFileInformation.FileInformationClass)); 243 | //just report that an attempt to delete happend 244 | //will delete its own shadow copy lol 245 | } 246 | else if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation) 247 | { 248 | PFILE_RENAME_INFORMATION fri = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer; 249 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "Compared against %ws\n", wbin)); 250 | if (WCStrncmp(wbin, fri->FileName, 20)) 251 | { 252 | // KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "Deleted %ws\n %ws\n", fri->FileName, fri->RootDirectory)); 253 | //just report that an attempt to delete happend 254 | //will delete its own shadow copy lol 255 | } 256 | else { 257 | // KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "Moved %ws\n %ws\n", fri->FileName, fri->RootDirectory)); 258 | //touched 259 | } 260 | } 261 | } 262 | } 263 | FltReleaseFileNameInformation(nameInfo); 264 | } 265 | return FLT_PREOP_SUCCESS_WITH_CALLBACK; 266 | } 267 | FLT_POSTOP_CALLBACK_STATUS 268 | FileSpyPostSetInfo( 269 | _Inout_ PFLT_CALLBACK_DATA Data, 270 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 271 | _In_opt_ PVOID CompletionContext, 272 | _In_ FLT_POST_OPERATION_FLAGS Flags 273 | ) 274 | { 275 | UNREFERENCED_PARAMETER(Data); 276 | UNREFERENCED_PARAMETER(FltObjects); 277 | UNREFERENCED_PARAMETER(CompletionContext); 278 | UNREFERENCED_PARAMETER(Flags); 279 | 280 | PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, 281 | ("FileSpy!FileSpyPostOperation: Entered\n")); 282 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "PostOp\n")); 283 | return FLT_POSTOP_FINISHED_PROCESSING; 284 | } 285 | FLT_PREOP_CALLBACK_STATUS 286 | FileSpyPreCreate ( 287 | _Inout_ PFLT_CALLBACK_DATA Data, 288 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 289 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 290 | ) 291 | { 292 | // NTSTATUS status; 293 | PFLT_FILE_NAME_INFORMATION nameInfo; 294 | 295 | UNREFERENCED_PARAMETER( CompletionContext ); 296 | /* 297 | CHECK TO SEE IF I NEED TO DO an IO HIGHJACK HERE 298 | */ 299 | 300 | //HOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOK 301 | IOhook(FltObjects); 302 | hhook(FltObjects); 303 | 304 | /* 305 | CHECK TO SEE IF I NEED TO DO an IO HIGHJACK HERE 306 | */ 307 | /* 308 | Needs to be a function called isDirecotyr 309 | */ 310 | if (FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE)) { 311 | 312 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 313 | } 314 | if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY)) { 315 | 316 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 317 | } 318 | if (processWhiteList(Data)) 319 | { 320 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 321 | } 322 | //dont use FLT_FILE_NAME_NORMALIZED its slow as fuck for pre_create 323 | NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo); 324 | if (!NT_SUCCESS(status)) 325 | { 326 | // KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "potential file tunnel\n")); 327 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 328 | } 329 | 330 | FltParseFileNameInformation(nameInfo); 331 | 332 | // Need to denied access to shadow files pretty much we will denied them 333 | // This needs to be denied here 334 | unsigned int Len = nameInfo->Extension.Length / 2; 335 | unsigned int i = 0; 336 | for (i = 0;i < Len;i++) 337 | { 338 | if (nameInfo->Extension.Buffer[i] == L'$') 339 | { 340 | UNICODE_STRING ext; 341 | generateExt(&ext, Data); 342 | if (UStrncmp(&ext, &nameInfo->Extension, 1)) 343 | { 344 | FltReleaseFileNameInformation(nameInfo); 345 | ExFreePool(ext.Buffer); 346 | return FLT_PREOP_SUCCESS_WITH_CALLBACK; 347 | } 348 | ExFreePool(ext.Buffer); 349 | 350 | Data->IoStatus.Status = STATUS_ACCESS_DENIED; 351 | Data->IoStatus.Information = 0; 352 | FltReleaseFileNameInformation(nameInfo); 353 | return FLT_PREOP_COMPLETE; 354 | } 355 | } 356 | if (UStrncmp(&DirProtect, &nameInfo->ParentDir,0)) 357 | { 358 | //need to re 359 | if (redirectIO(FltObjects, Data, nameInfo)) 360 | { 361 | FltReleaseFileNameInformation(nameInfo); 362 | return FLT_PREOP_COMPLETE; 363 | } 364 | } 365 | FltReleaseFileNameInformation(nameInfo); 366 | return FLT_PREOP_SUCCESS_WITH_CALLBACK; 367 | } 368 | VOID 369 | FileSpyOperationStatusCallback ( 370 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 371 | _In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot, 372 | _In_ NTSTATUS OperationStatus, 373 | _In_ PVOID RequesterContext 374 | ) 375 | { 376 | UNREFERENCED_PARAMETER( FltObjects ); 377 | 378 | PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, 379 | ("FileSpy!FileSpyOperationStatusCallback: Entered\n") ); 380 | 381 | PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS, 382 | ("FileSpy!FileSpyOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n", 383 | OperationStatus, 384 | RequesterContext, 385 | ParameterSnapshot->MajorFunction, 386 | ParameterSnapshot->MinorFunction, 387 | FltGetIrpName(ParameterSnapshot->MajorFunction)) ); 388 | } 389 | FLT_POSTOP_CALLBACK_STATUS 390 | FileSpyPostCreate ( 391 | _Inout_ PFLT_CALLBACK_DATA Data, 392 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 393 | _In_opt_ PVOID CompletionContext, 394 | _In_ FLT_POST_OPERATION_FLAGS Flags 395 | ) 396 | { 397 | UNREFERENCED_PARAMETER( Data ); 398 | UNREFERENCED_PARAMETER( FltObjects ); 399 | UNREFERENCED_PARAMETER( CompletionContext ); 400 | UNREFERENCED_PARAMETER( Flags ); 401 | 402 | PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, 403 | ("FileSpy!FileSpyPostOperation: Entered\n") ); 404 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "PostOp\n")); 405 | return FLT_POSTOP_FINISHED_PROCESSING; 406 | } 407 | FLT_PREOP_CALLBACK_STATUS 408 | FileSpyPreOperationNoPostOperation ( 409 | _Inout_ PFLT_CALLBACK_DATA Data, 410 | _In_ PCFLT_RELATED_OBJECTS FltObjects, 411 | _Flt_CompletionContext_Outptr_ PVOID *CompletionContext 412 | ) 413 | { 414 | UNREFERENCED_PARAMETER( Data ); 415 | UNREFERENCED_PARAMETER( FltObjects ); 416 | UNREFERENCED_PARAMETER( CompletionContext ); 417 | 418 | PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, 419 | ("FileSpy!FileSpyPreOperationNoPostOperation: Entered\n") ); 420 | 421 | //KdPrintEx((DPFLTR_IHVDRIVER_ID, 0x08, "PreNoPostOp\n")); 422 | return FLT_PREOP_SUCCESS_NO_CALLBACK; 423 | } 424 | BOOLEAN 425 | FileSpyDoRequestOperationStatus( 426 | _In_ PFLT_CALLBACK_DATA Data 427 | ) 428 | { 429 | PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb; 430 | return (BOOLEAN) 431 | (((iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && 432 | ((iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) || 433 | (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK) || 434 | (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) || 435 | (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2))) 436 | 437 | || 438 | 439 | ((iopb->MajorFunction == IRP_MJ_DIRECTORY_CONTROL) && 440 | (iopb->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)) 441 | ); 442 | } 443 | --------------------------------------------------------------------------------