Windows driver : PreOperationCallback not called - windows

I'm trying to create a basic minifilter driver using Microsoft examples (PassThough, minispy...), but my MfPreOperationCallback is not called. I tried different contexts (even if I'm not sure to understand how that works...). I tried the PassThrough example and it works very well and it is very similar to my code...
Here is my inf file and my code :
;
; KmdfMiniFilter.inf
;
[Version]
Signature = "$WINDOWS NT$"
Class = "ActivityMonitor"
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
Provider = %ProviderString%
DriverVer = 02/09/2017,1.0.0.0
CatalogFile = KmdfMiniFilter.cat
[DestinationDirs]
DefaultDestDir = 12
KmdfMiniFilter.DriverFiles = 12
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = KmdfMiniFilter.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,KmdfMiniFilter.Service
[DefaultUninstall]
DelFiles = KmdfMiniFilter.DriverFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200
[KmdfMiniFilter.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys
Dependencies = "FltMgr"
ServiceType = 2 ; SERVICE_FILE_SYSTEM_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = KmdfMiniFilter.AddRegistry
[KmdfMiniFilter.AddRegistry]
HKR,,"DebugFlags",0x00010001 ,0x0
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%
[KmdfMiniFilter.DriverFiles]
%DriverName%.sys
[SourceDisksFiles]
KmdfMiniFilter.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
[Strings]
ProviderString = "GUIDONO"
ServiceDescription = "KmdfMiniFilter mini-filter driver"
ServiceName = "KmdfMiniFilter"
DriverName = "KmdfMiniFilter"
DiskId1 = "File Change Monitoring Device Installation Disk"
DefaultInstance = "KmdfMiniFilter Instance"
Instance1.Name = "KmdfMiniFilter Middle Instance"
Instance1.Altitude = "370000"
Instance1.Flags = 0x1 ; Suppress automatic attachments
Registration.c
/**
Filter registration information
*/
#pragma once
#include <fltKernel.h>
#include "MiniFilter.h"
// Callbacks : list of FLT_OPERATION_REGISTRATION structures, one for each type of I/O for which the minifilter
// registers preoperation and postoperation callback routines.
// The last element must be IRP_MJ_OPERATION_END
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{
IRP_MJ_CREATE,
0,
MfPreOperationCallback,
MfPostOperationCallback
},
{ IRP_MJ_OPERATION_END }
};
// Defines the minifilter context structure
typedef struct _MINIFILTER_TRANSACTION_CONTEXT {
ULONG Flags;
ULONG Count;
} MINIFILTER_TRANSACTION_CONTEXT, *PMINIFILTER_CONTEXT;
// Contexts : a context structure is used to register context types
const FLT_CONTEXT_REGISTRATION Contexts[] =
{
{
FLT_TRANSACTION_CONTEXT, // Context type
0, // Flags
MfDeleteTxfContext, // ContextCleanupCallback
sizeof(MINIFILTER_TRANSACTION_CONTEXT), // Size
'ypsM' // PoolTag
},
{
FLT_CONTEXT_END
}
};
// This defines what we want to filter with FltMgr
CONST FLT_REGISTRATION FilterRegistration =
{
sizeof(FLT_REGISTRATION), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
Contexts, // Contexts
Callbacks, // Callbacks
MfUnload, // FilterUnload
MfInstanceSetup, // InstanceSetup
MfInstanceQueryTeardown, // InstanceQueryTeardown
MfInstanceTeardownStart, // InstanceTeardownStart
MfInstanceTeardownComplete, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL, // NormalizeNameComponent
};
Driver.c
#include <ntifs.h>
#include <wdf.h>
#include "RegistrationData.h"
#include "MiniFilter.h"
// Global data
MINIFILTER_DATA MfData;
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
//DbgSetDebugFilterState(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, TRUE);
NTSTATUS status;
MfData.Driver = DriverObject;
// Registering the minifilter driver
status = FltRegisterFilter(DriverObject, &FilterRegistration, &MfData.Filter);
KdPrint(("MINIFILTER INIT\n"));
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltRegisterFilter failed. Code 0x%x\n", status));
return STATUS_UNSUCCESSFUL;
}
status = FltStartFiltering(MfData.Filter);
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltStartFiltering faild. Code 0x%x\n", status));
FltUnregisterFilter(MfData.Filter);
return STATUS_UNSUCCESSFUL;
}
KdPrint(("MINIFILTER is Filtering!\n"));
return status;
}
NTSTATUS MfUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
KdPrint(("MINIFILTER UNLOAD\n"));
FltUnregisterFilter(MfData.Filter);
return STATUS_SUCCESS;
}
NTSTATUS MfQueryTearDown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
return STATUS_SUCCESS;
}
MiniFilter.h
#pragma once
#include <fltKernel.h>
typedef struct MINIFILTER_DATA {
PDRIVER_OBJECT Driver;
PFLT_FILTER Filter;
} MINIFILTER_DATA;
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
);
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
);
NTSTATUS MfInstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
);
NTSTATUS MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
);
NTSTATUS MfUnload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);
NTSTATUS MfQueryTearDown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
NTSTATUS MfInstanceQueryTeardown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
MiniFilter.c
#include "MiniFilter.h"
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
KdPrint(("MINIFILTER PreOperationCallback\n"));
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);
KdPrint(("MINIFILTER PostOperationCallback\n"));
return FLT_POSTOP_FINISHED_PROCESSING;
}
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
)
{
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(ContextType);
KdPrint(("MINIFILTER DeleteTxfContext\n"));
}
NTSTATUS
MfInstanceSetup (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeDeviceType );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceSetup: Entered\n") );
return STATUS_SUCCESS;
}
NTSTATUS
MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceQueryTeardown: Entered\n") );
return STATUS_SUCCESS;
}
VOID
MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownStart: Entered\n") );
}
VOID
MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownComplete: Entered\n") );
}
Does anyone see what's going on ?

I solved my problem : I had the wrong flag in my inf file. The good one is 0x0 flag in order to attach the minifilter automatically to the different volumes.
Instance1.Flags = 0x1 ; Suppress automatic attachments
to
Instance1.Flags = 0x0 ; Automatic attachments

Related

Spoofing hard disk serial number via a driver

I modified a windows driver that spoofs hard disk number by generating a random serial, I modified it to spoof a pre-known serial, now when it get loaded and query for the first time via wmi for the serial then it shows the pre-defined serial, but if I query again, it shows an empty string.
The driver implementation:
#include <ntifs.h>
#include <Ntdddisk.h>
#include <windef.h>
#include "main.h"
#include <sys/stat.h>
#include <tchar.h>
#include <stdio.h>
#include <winapifamily.h>
#include <iostream.h>
#include <sys/stat.h>
#include <Ntstrsafe.h>
PDRIVER_DISPATCH RealDiskDeviceControl = NULL;
char NumTable[] = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char SpoofedHWID[] = "XYXYXYYYYYXYXXYXYYYXXYYXXXXYYXYYYXYYX\0";
BOOL HWIDGenerated = 0;
char* newDiskId = "WD-WMATV3142957\0";
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[MAX_PATH];
TCHAR cAlternateFileName[14];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
PDRIVER_OBJECT GetDriverObject(PUNICODE_STRING DriverName)
{
PDRIVER_OBJECT DrvObject;
if (NT_SUCCESS(ObReferenceObjectByName(DriverName, 0, NULL, 0, *IoDriverObjectType, KernelMode, NULL, &DrvObject)))
{
return DrvObject;
}
return NULL;
}
NTSTATUS SpoofSerialNumber(char* serialNumber)
{
//RtlSecureZeroMemory
if (!HWIDGenerated)
{
HWIDGenerated = 1;
size_t newDiskIdLen = 0;
RtlStringCchLengthA(newDiskId, NTSTRSAFE_MAX_CCH, &newDiskIdLen);
RtlCopyMemory((void*)serialNumber, (void*)newDiskId, ++newDiskIdLen);
}
return STATUS_SUCCESS;
}
NTSTATUS StorageQueryCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
PIO_COMPLETION_ROUTINE OldCompletionRoutine = NULL;
PVOID OldContext = NULL;
ULONG OutputBufferLength = 0;
PSTORAGE_DEVICE_DESCRIPTOR descriptor = NULL;
if (Context != NULL)
{
REQUEST_STRUCT* pRequest = (REQUEST_STRUCT*)Context;
OldCompletionRoutine = pRequest->OldRoutine;
OldContext = pRequest->OldContext;
OutputBufferLength = pRequest->OutputBufferLength;
descriptor = pRequest->StorageDescriptor;
ExFreePool(Context);
}
if (FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, SerialNumberOffset) < OutputBufferLength && descriptor->SerialNumberOffset > 0 && descriptor->SerialNumberOffset < OutputBufferLength)
{
char* SerialNumber = ((char*)descriptor) + descriptor->SerialNumberOffset;
size_t SerialNumberLen = 0;
RtlStringCchLengthA(SerialNumber, NTSTRSAFE_MAX_CCH, &SerialNumberLen);
RtlSecureZeroMemory(SerialNumber, SerialNumberLen);
SpoofSerialNumber(SerialNumber);
}
if ((Irp->StackCount >(ULONG)1) && (OldCompletionRoutine != NULL))
return OldCompletionRoutine(DeviceObject, Irp, OldContext);
return STATUS_SUCCESS;
}
NTSTATUS SmartCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_COMPLETION_ROUTINE OldCompletionRoutine = NULL;
PVOID OldContext = NULL;
if (Context != NULL)
{
REQUEST_STRUCT* pRequest = (REQUEST_STRUCT*)Context;
OldCompletionRoutine = pRequest->OldRoutine;
OldContext = pRequest->OldContext;
ExFreePool(Context);
}
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
return Irp->IoStatus.Status;
}
NTSTATUS DiskDriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Io = IoGetCurrentIrpStackLocation(Irp);
switch (Io->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_STORAGE_QUERY_PROPERTY:
{
PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
if (query->PropertyId == StorageDeviceProperty)
{
Io->Control = 0;
Io->Control |= SL_INVOKE_ON_SUCCESS;
PVOID OldContext = Io->Context;
Io->Context = (PVOID)ExAllocatePool(NonPagedPool, sizeof(REQUEST_STRUCT));
REQUEST_STRUCT *pRequest = (REQUEST_STRUCT*)Io->Context;
pRequest->OldRoutine = Io->CompletionRoutine;
pRequest->OldContext = OldContext;
pRequest->OutputBufferLength = Io->Parameters.DeviceIoControl.OutputBufferLength;
pRequest->StorageDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
Io->CompletionRoutine = (PIO_COMPLETION_ROUTINE)StorageQueryCompletionRoutine;
}
break;
}
case SMART_RCV_DRIVE_DATA:
{
Io->Control = 0;
Io->Control |= SL_INVOKE_ON_SUCCESS;
PVOID OldContext = Io->Context;
Io->Context = (PVOID)ExAllocatePool(NonPagedPool, sizeof(REQUEST_STRUCT));
REQUEST_STRUCT *pRequest = (REQUEST_STRUCT*)Io->Context;
pRequest->OldRoutine = Io->CompletionRoutine;
pRequest->OldContext = OldContext;
Io->CompletionRoutine = (PIO_COMPLETION_ROUTINE)SmartCompletionRoutine;
break;
}
}
return RealDiskDeviceControl(DeviceObject, Irp);
}
NTSTATUS UnsupportedDispatch(
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
NTSTATUS CreateDispatch(
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp
)
{
UNREFERENCED_PARAMETER(DeviceObject);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
NTSTATUS CloseDispatch(_In_ struct _DEVICE_OBJECT *DeviceObject, _Inout_ struct _IRP *Irp
)
{
UNREFERENCED_PARAMETER(DeviceObject);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING diskDrvName;
RtlInitUnicodeString(&diskDrvName, L"\\Driver\\disk");
PDRIVER_OBJECT diskDrvObj = GetDriverObject(&diskDrvName);
RealDiskDeviceControl = diskDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL];
diskDrvObj->DriverInit = &DriverEntry;
diskDrvObj->DriverStart = (PVOID)DriverObject;
diskDrvObj->DriverSize = (ULONG)RegistryPath;
diskDrvObj->FastIoDispatch = NULL;
diskDrvObj->DriverStartIo = NULL;
diskDrvObj->DriverUnload = NULL;
/*for (ULONG t = 0; t <= IRP_MJ_MAXIMUM_FUNCTION; t++)
diskDrvObj->MajorFunction[t] = &UnsupportedDispatch;*/
diskDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = &DiskDriverDispatch;
/*diskDrvObj->MajorFunction[IRP_MJ_CREATE] = &CreateDispatch;
diskDrvObj->MajorFunction[IRP_MJ_CLOSE] = &CloseDispatch;*/
return status;
}
NTSTATUS SpoofSerialNumber(char* serialNumber)
{
//RtlSecureZeroMemory
if (!HWIDGenerated)
{
HWIDGenerated = 1;
There's your issue, I'm not sure if your using this for game-cheating purposes but if you are this is detected on all major anticheats (maybe not eac but def BE). The reason it only spoofs once is due to the very unusual code in this driver which makes it only spoof once (defeating the whole purpose of hooking disks dispatch routine), this is hwidfaker from github which is not a great example to see how spoofers work its quite simple and unorganized (its pasted).

Windows Cmd Hook not working

i am trying to hook the CreateProcess under cmd.exe.
i manage to inject the dll the the cmd process but after the injection the dll process detach message receive and i fail to hook the createprocess function call.
i am using easyhook.
my code:
#include <windows.h>
#include <Shlwapi.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <easyhook.h>
BOOL WINAPI myCreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
){
OutputDebugString(L"\n !!!!!! In CreateProcess HOOK\n !!!!!!!!");
return CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCommandLine, lpStartupInfo, lpProcessInformation);
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
BOOL bErrorFlag = FALSE;
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
HOOK_TRACE_INFO hHook = { NULL }; // keep track of our hook
// Install the hook
NTSTATUS result = LhInstallHook(
GetProcAddress(GetModuleHandle(TEXT("kernel32")), "CreateProcessW"),
myCreateProcess,
NULL,
&hHook);
if (FAILED(result))
{
OutputDebugString(L"!!!!!!!!!!!FAIL!!!!!!!!");
return 1;
}
ULONG ACLEntries[1] = { 0 };
LhSetInclusiveACL(ACLEntries, 1, &hHook);
OutputDebugString(L"!!!!!!!!!!!!Injection Succeed!!!!!!!!!!!!");
break;
}
case DLL_THREAD_ATTACH:{
OutputDebugString(L"!!!!!!!!!!!!dll thread attach!!!!!!!!!!!!");
break;
}
case DLL_THREAD_DETACH:
{
OutputDebugString(L"!!!!!!!!!!!!dll thread Detach!!!!!!!!!!!!");
break;
}
case DLL_PROCESS_DETACH:
{
OutputDebugString(L"!!!!!!!!!!!!dll process Detach!!!!!!!!!!!!");
break;
}
}
}
i receive the "Injection Succeed" message and right after the "dll process Detach" message .
any ideas?
try changing :
LhSetInclusiveACL(ACLEntries, 1, &hHook);
to :
LhSetExclusiveACL(ACLEntries, 1, &hHook);

Find current PID and terminate him in kernel-mode

My file system minifilter driver for Windows 7x64 must denied access for some files. I`m get it, but associated application still work. I want to terminate process with this application. For example, when user try to open *.txt file, file and associated copy of notepad must be closed. I used example from WDK (Minispy) and functions ZwTerminateProcess and PsGetCurrentProcessId. Now, when user enter monitoring directory, my minifilter close explorer.exe. Example code:
minispy.c
...
NTSTATUS TermFunction( HANDLE ProcessID )
{
NTSTATUS ntStatus = STATUS_SUCCESS;
HANDLE hProcess;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
DbgPrint( "drvTerminateProcess( %u )", ProcessID );
InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL );
ClientId.UniqueProcess = (HANDLE)ProcessID;
ClientId.UniqueThread = NULL;
__try
{
ntStatus = ZwOpenProcess( &hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId );
if( NT_SUCCESS(ntStatus) )
{
ntStatus = ZwTerminateProcess( hProcess, 0 );
if( !NT_SUCCESS(ntStatus) )
DbgPrint( "ZwTerminateProcess failed with status : %08X\n", ntStatus );
ZwClose( hProcess );
}
else
DbgPrint( "ZwOpenProcess failed with status : %08X\n", ntStatus );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
ntStatus = STATUS_UNSUCCESSFUL;
DbgPrint( "Exception caught in drvTerminateProcess()" );
}
return ntStatus;
}
...
FLT_PREOP_CALLBACK_STATUS
SpyPreOperationCallback (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
UNICODE_STRING old_name;
PUNICODE_STRING new_old_name;
...
if (NT_SUCCESS( status )) {
nameToUse = &nameInfo->Name;
//
// Parse the name if requested
//
//Start of My func
RtlInitUnicodeString( &old_name, L"\\Device\\HarddiskVolume2\\secretfile.txt" );
new_old_name = &old_name;
if(RtlCompareUnicodeString(nameToUse, new_old_name, FALSE) == 0){
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
TermFunction(PsGetCurrentProcessId);
return FLT_PREOP_COMPLETE;
}
...
}
....
}
Any idea?
(Excuse me if my English is bad)

Filter hook driver: dispatch routine isn't called

I'm trying to write legacy filter-hook driver, firewall-like: look for dst port and block it.
But when packets are sent, dispatcher routine isn't called.
Register dispatch:
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
Start ipfilter driver:
C:\Users\unnamed>net start ipfilterdriver
After that, launch debug driver via Visual DDK. Driver load successfully, but breakpoint in dispatcher isn't reached. What am I doing wrong?
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING DeviceName,Win32Device;
PDEVICE_OBJECT DeviceObject = NULL;
NTSTATUS status;
unsigned i;
RtlInitUnicodeString(&DeviceName,L"\\Device\\driver10");
RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\driver10");
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = driver1DefaultHandler;
/*
DriverObject->MajorFunction[IRP_MJ_CREATE] = driver1CreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = driver1CreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
*/
status = IoCreateDevice(DriverObject, 0, &DeviceName,
FILE_DEVICE_DRVFLTIP, 0, FALSE,
&DeviceObject);
if (NT_SUCCESS(status)) {
status = IoCreateSymbolicLink(&Win32Device, &DeviceName);
if (!NT_SUCCESS(status))
dprintf("DrvFltIp.SYS: IoCreateSymbolicLink failed\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
DriverObject->DriverUnload = driver1Unload;
}
if (!NT_SUCCESS(status)) {
dprintf("Error in initialization. Unloading...");
driver1Unload(DriverObject);
}
if (!DeviceObject)
return STATUS_UNEXPECTED_IO_ERROR;
/*
DeviceObject->Flags |= DO_DIRECT_IO;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
*/
DbgPrint("Driver started\n");
return status;
}
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
dprintf("DrvDispatch called\n");
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
dprintf("DrvFltIp.SYS: IRP_MJ_CREATE\n");
break;
case IRP_MJ_CLOSE:
dprintf("DrvFltIp.SYS: IRP_MJ_CLOSE\n");
break;
case IRP_MJ_DEVICE_CONTROL:
dprintf("DrvFltIp.SYS: IRP_MJ_DEVICE_CONTROL\n");
break;
}
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
Just forgot register filter-hook callback function in the DriverEntry:
Registering and Clearing a Filter Hook

Asynchronous NtQueryDirectoryFile?

Has anyone managed to figure out how asynchronous calls to NtQueryDirectoryFile work?
By an asynchronous call, I mean calling NtQueryDirectoryFile on directories not opened with FILE_SYNCHRONOUS_IO_ALERT or with FILE_SYNCHRONOUS_IO_NONALERT.
For me, it seems to return STATUS_PENDING just like a normal NtReadFile request does on a normal file, but when I tried using NtWaitForSingleObject on the directory, it didn't end properly, and I still don't get all the data... why does this happen?
As far as I know, none of the Windows filesystems support asynchronous query directory calls.
The Win32 APIs never call NtQueryDirectoryFile asnchronously, so support for it is hit-or-miss.
NTFS theoretically supports asynchronous NtQueryDirectoryFile but (as I mentioned) it is not extensively tested so it may not work.
You response indicated that you called WaitForSingleObject on the directory - that's not how the async pattern works in NT - you need to call WaitForSingleObject on the event handle provided as a parameter to NtQueryDirectoryFile.
This update is a result of asking the NTFS developer for more information, he tested this scenario on his machine and it worked for him (on Windows 7).
NtQueryDirectoryFile works well in asynchronous!
pass callback in ApcRoutine, and callback data in ApcContext
asynchronous procedure calls only call when the thread is in alertable state(for example: calling SleepEx(INFINITE, TRUE), WSAaccept)
this program shows how asynchronous NtQueryDirectoryFile work.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <winnt.h>
#define LIST_DIR_SIZE 2000
#define STATUS_NO_MORE_FILES ((NTSTATUS)80000006)
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, * PFILE_NAMES_INFORMATION;
typedef struct {
HANDLE hFile;
OVERLAPPED ol;
DECLSPEC_ALIGN(4) FILE_NAMES_INFORMATION buf[LIST_DIR_SIZE];
IO_STATUS_BLOCK iob;
bool finished;
} LIST_DIR_DATA, * PLIST_DIR_DATA; // my private data
__kernel_entry NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_writes_bytes_(Length) PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass,
_In_ BOOLEAN ReturnSingleEntry,
_In_opt_ PUNICODE_STRING FileName,
_In_ BOOLEAN RestartScan
);
#define NTDLL_extern(s) typedef decltype(&s) s##T;s##T s##F;
#define NTDLL_import(s) s##F = (s##T)GetProcAddress(ntdll, #s);
NTDLL_extern(NtOpenFile);
NTDLL_extern(NtQueryDirectoryFile);
NTDLL_extern(NtClose);
NTDLL_extern(RtlInitUnicodeString);
HMODULE ntdll;
VOID NTAPI callback(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved) {
UNREFERENCED_PARAMETER(Reserved);
PFILE_NAMES_INFORMATION file_info = ((PLIST_DIR_DATA)ApcContext)->buf;
do {
fputws(file_info->FileName, stdout);
putwchar(L'\t');
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (file_info->NextEntryOffset);
fputws(file_info->FileName, stdout);
putwchar(L'\t');
PLIST_DIR_DATA c = (PLIST_DIR_DATA)ApcContext;
if (IoStatusBlock->Information != 0) {
NTSTATUS status = NtQueryDirectoryFileF(
c->hFile,
NULL,
callback,
ApcContext,
&c->iob,
c->buf,
sizeof(c->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
fputs("warning: status != STATUS_PENDING", stderr);
}
}
else {
c->finished = true;
}
}
BOOL init() {
ntdll = LoadLibraryW(L"NtDLL.dll");
if (ntdll == NULL) {
fputs("LoadLibraryW", stderr);
return FALSE;
}
NTDLL_import(NtQueryDirectoryFile);
NTDLL_import(NtOpenFile);
NTDLL_import(NtClose);
NTDLL_import(RtlInitUnicodeString);
if (NtCloseF != NULL && NtOpenFileF != NULL && NtCloseF != NULL) {
return TRUE;
}
else {
fputs("GetProcAddress", stderr);
return FALSE;
}
}
int main() {
if (init() == FALSE) {
fputs("error: init() failed!", stderr);
return -1;
}
NTSTATUS status;
PLIST_DIR_DATA data = new LIST_DIR_DATA{};
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING s;
RtlInitUnicodeStringF(&s, L"\\??\\c:\\Windows\\System32");
InitializeObjectAttributes(
&ObjectAttributes,
&s,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFileF(
&data->hFile,
FILE_READ_DATA | FILE_LIST_DIRECTORY, // | FILE_TRAVERSE | SYNCHRONIZE
&ObjectAttributes,
&data->iob,
FILE_SHARE_READ,
FILE_DIRECTORY_FILE); // | FILE_SYNCHRONOUS_IO_NONALERT
}
if (status < 0 || data->hFile == NULL) {
fputs("error: NtOpenFile failed", stderr);
return -2;
}
status = NtQueryDirectoryFileF(
data->hFile,
NULL,
callback,
data,
&data->iob,
data->buf,
sizeof(data->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
fputs("warning: status != STATUS_PENDING", stderr);
}
for (;data->finished==false;) SleepEx(INFINITE, TRUE); // put main thread into alertable wait
NtCloseF(data->hFile);
FreeLibrary(ntdll);
return 0;
}
if you want UTF-8 output, try this (note: recommand use support UTF-8 terminal)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winternl.h>
#include <winnt.h>
#include <crtdbg.h>
#include <cstdio>
#define LIST_DIR_SIZE 200
#define STATUS_NO_MORE_FILES ((NTSTATUS)80000006)
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, * PFILE_NAMES_INFORMATION;
typedef struct {
HANDLE hFile;
OVERLAPPED ol;
DECLSPEC_ALIGN(4) FILE_NAMES_INFORMATION buf[LIST_DIR_SIZE];
IO_STATUS_BLOCK iob;
bool finished;
} LIST_DIR_DATA, * PLIST_DIR_DATA; // my private data
__kernel_entry NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_writes_bytes_(Length) PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass,
_In_ BOOLEAN ReturnSingleEntry,
_In_opt_ PUNICODE_STRING FileName,
_In_ BOOLEAN RestartScan
);
#define NTDLL_extern(s) typedef decltype(&s) s##T;s##T s##F;
#define NTDLL_init(s) s##F = (s##T)GetProcAddress(ntdll, #s);
NTDLL_extern(NtOpenFile);
NTDLL_extern(NtQueryDirectoryFile);
NTDLL_extern(NtClose);
NTDLL_extern(RtlInitUnicodeString);
HMODULE ntdll;
HANDLE heap;
VOID NTAPI callback(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved) {
UNREFERENCED_PARAMETER(Reserved);
PLIST_DIR_DATA c = (PLIST_DIR_DATA)ApcContext;
if (IoStatusBlock->Information){
PFILE_NAMES_INFORMATION file_info = c->buf;
ULONG_PTR length = 0;
ULONG last;
do {
last = file_info->NextEntryOffset;
file_info->FileNameLength /= 2; // wide char length always base of 2 in bytes
length += (
file_info->FileIndex=WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS,
file_info->FileName, file_info->FileNameLength,
NULL, 0,
NULL, NULL)
)+1;
if (file_info->FileIndex == 0) { // FileIndex is how many byte is the UTF-8 string
_RPTF0(_CRT_WARN, "WideCharToMultiByte failed!");
}
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (last);
LPSTR pData = (LPSTR)HeapAlloc(heap, HEAP_NO_SERIALIZE, length), ptr=pData;
if (ptr == NULL) {
_RPTF0(_CRT_ERROR, "HeapAlloc failed!");
return;
}
file_info = c->buf;
do {
last = file_info->NextEntryOffset;
if (WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS,
file_info->FileName, file_info->FileNameLength,
pData, file_info->FileIndex,
NULL, NULL)==0) {
_RPTF0(_CRT_WARN, "WideCharToMultiByte failed!");
}
pData += file_info->FileIndex;
*pData++ = '\n';
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (last);
// use data here
fwrite(ptr, length, 1, stdout);
// use data here
HeapFree(heap, HEAP_NO_SERIALIZE, ptr);
NTSTATUS status = NtQueryDirectoryFileF(
c->hFile,
NULL,
callback,
ApcContext,
&c->iob,
c->buf,
sizeof(c->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
_RPTF0(_CRT_WARN, "status != STATUS_PENDING");
}
}else{
c->finished = true;
}
}
BOOL init() {
ntdll = LoadLibraryW(L"NtDLL.dll");
if (ntdll == NULL) {
_RPTF0(_CRT_ERROR, "fail to load NtDLL.dll");
return FALSE;
}
NTDLL_init(NtQueryDirectoryFile);
NTDLL_init(NtOpenFile);
NTDLL_init(NtClose);
NTDLL_init(RtlInitUnicodeString);
if (NtCloseF != NULL &&
NtOpenFileF != NULL &&
NtCloseF != NULL &&
(heap = HeapCreate(HEAP_NO_SERIALIZE, 4096,0))!=NULL
){
return TRUE;
}
else {
_RPTF0(_CRT_ERROR, "failed to load function and create heap");
return FALSE;
}
}
int main() {
if (init() == FALSE) {
_RPTF0(_CRT_ERROR, "init failed");
return -1;
}
SetConsoleCP(CP_UTF8);
NTSTATUS status;
PLIST_DIR_DATA data = new LIST_DIR_DATA{};
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING s;
RtlInitUnicodeStringF(&s, L"\\??\\c:\\Users");
InitializeObjectAttributes(
&ObjectAttributes,
&s,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFileF(
&data->hFile,
FILE_READ_DATA | FILE_LIST_DIRECTORY, // | FILE_TRAVERSE | SYNCHRONIZE
&ObjectAttributes,
&data->iob,
FILE_SHARE_READ,
FILE_DIRECTORY_FILE); // | FILE_SYNCHRONOUS_IO_NONALERT
}
if (status < 0 || data->hFile == NULL) {
_RPTF0(_CRT_ERROR, "NtOpenFile failed!");
return -2;
}
status = NtQueryDirectoryFileF(
data->hFile,
NULL,
callback,
data,
&data->iob,
data->buf,
sizeof(data->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
_RPTF0(_CRT_WARN, "status != STATUS_PENDING");
}
for (;data->finished==false;) SleepEx(INFINITE, TRUE); // put main thread into alertable wait
if (NtCloseF(data->hFile)<0) {
_RPTF0(_CRT_ERROR, "NtClose failed!");
}
if (FreeLibrary(ntdll) == FALSE) {
_RPTF0(_CRT_WARN, "failed to Free libary");
}
if (HeapDestroy(heap) == FALSE) {
_RPTF0(_CRT_WARN, "fail to destroy heap");
}
}

Resources