about memory leak in my driver.....somebody help me?

This is my first windows driver, I want to protect some directory. so I hook the ZwCreateFile, ZwSetInformationFile and ZwWriteFile functions in the SDT table.

But when I run the driver for some days, The Kernel Memory become more and more…

I think there is some memory leak in my code, but I check it many times. I coundn’t find it.

Can somebody help me…, I have little experience on windows driver development, this is my first windows system driver programe. thx …


#include <ntifs.h>
#include <ntddk.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

typedef struct _SDT
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
PUCHAR ParamTableBase;
}SDT, *PSDT;

extern PSDT KeServiceDescriptorTable; //ntoskrnl.exe???
#define NT_PROCNAMELEN 128
#define NT_FILENAMELEN 2048
#define FILTER_LEN 10240
#define LOGINF_LEN 102400

#define MUTEX_INIT(v) KeInitializeMutex( &v, 0 )
#define MUTEX_ACQUIRE(v) KeWaitForMutexObject( &v, Executive, KernelMode, FALSE, NULL )
#define MUTEX_RELEASE(v) KeReleaseMutex( &v, FALSE )

#define FILE_DEVICE_MON 0x00008405

#define IOCTL_FILEM_HOOK (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x00, METHOD_BUFFERED, FILE_WRITE_ACCESS )
#define IOCTL_FILEM_UNHOOK (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x01, METHOD_BUFFERED, FILE_WRITE_ACCESS )
#define IOCTL_FILEM_GETLOG (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x03, METHOD_NEITHER, FILE_WRITE_ACCESS )
#define IOCTL_FILEM_SETFILTER (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x04, METHOD_BUFFERED, FILE_WRITE_ACCESS )
#define IOCTL_FILEM_SETEXCLUDE (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x05, METHOD_BUFFERED, FILE_WRITE_ACCESS )
#define IOCTL_FILEM_SETPROCESS (ULONG) CTL_CODE( FILE_DEVICE_MON, 0x06, METHOD_BUFFERED, FILE_WRITE_ACCESS )

#define IOCTL_TRANSFER_TYPE( _iocontrol) (_iocontrol & 0x3)

//ZwSetInformationFile
//-------------------------------------------------------------------------
typedef NTSTATUS (__stdcall ZWSETINFORMATIONFILE)(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
NTSTATUS NewZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);

PULONG pZwSetInformationFileSDT; //???SSDT???
ZWSETINFORMATIONFILE OldZwSetInformationFile; //???
VOID HookZwSetInformationFile();
VOID UnHookZwSetInformationFile();
//-------------------------------------------------------------------------

//ZwWriteFile
//-------------------------------------------------------------------------
typedef NTSTATUS (__stdcall ZWWRITEFILE)(IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL);
NTSTATUS NewZwWriteFile(IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL);

PULONG pZwWriteFileSDT; //???SSDT???
ZWWRITEFILE OldZwWriteFile; //???
VOID HookZwWriteFile();
VOID UnHookZwWriteFile();
//-------------------------------------------------------------------------

//ZwQuerySystemInformation
//-------------------------------------------------------------------------
struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientIs;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
ULONG ThreadState;
KWAIT_REASON WaitReason;
};

struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
struct _SYSTEM_THREADS Threads[1];
};

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);

typedef NTSTATUS (ZWQUERYSYSTEMINFORMATION)(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);

NTSTATUS NewZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);

unsigned long OldCr0;
PULONG pZwQuerySystemInformationSDT;
ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
VOID HookZwQuerySystemInformation();
VOID UnHookZwQuerySystemInformation();

//------------------------------------------------------------------------

//ZwCreateFile
//-------------------------------------------------------------------------
typedef NTSTATUS (__stdcall ZWCREATEFILE)(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer,
IN ULONG EaLength);

NTSTATUS NewZwCreateFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer,
IN ULONG EaLength);

PULONG pZwCreateFileSDT; //???SSDT???
ZWCREATEFILE OldZwCreateFile; //???
VOID HookZwCreateFile();
VOID UnHookZwCreateFile();
//-------------------------------------------------------------------------

NTSTATUS DriverControlDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
BOOLEAN DeviceControlDipatch(IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);
VOID HookAll();
VOID UnHookAll();
ULONG GetProcessNameOffset();
PCHAR GetProcess(PCHAR Name);
NTSTATUS AccessFilter(PUNICODE_STRING FileName);
PCHAR LowStr(PCHAR str);
VOID LogRecord(const PCHAR format,…);
ULONG GetLogTxt(IN PCHAR LogTxt);

PDRIVER_OBJECT pGDriverObject;
PDEVICE_OBJECT pGControlDevice;

ULONG ProcessNameOffset;

BOOLEAN bProtect=TRUE;
BOOLEAN bHooked=FALSE;

CHAR ProtectPath[FILTER_LEN]={0};
CHAR ExcludePath[FILTER_LEN]={0};
CHAR ExcludeProcess[FILTER_LEN]={0};
CHAR LogInf[LOGINF_LEN]={0};

PCHAR pLogInfStart=LogInf;
PCHAR pLogInfEnd=LogInf;

KMUTEX ProtectPathMutex;
KMUTEX ExcludePathMutex;
KMUTEX ExcludeProcessMutex;
KMUTEX LogInfMutex;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegPath)
{
//__asm int 3
NTSTATUS status;
UNICODE_STRING DeviceName, LinkName;
int i=0;

ProcessNameOffset=GetProcessNameOffset();

//init filter
MUTEX_INIT(ProtectPathMutex);
MUTEX_INIT(ExcludePathMutex);
MUTEX_INIT(ExcludeProcessMutex);
MUTEX_INIT(LogInfMutex);

pGDriverObject=pDriverObject;

#if DBG
pDriverObject->DriverUnload = DriverUnload;
strcpy(ProtectPath,“;c:\1;”);
#endif

pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =DriverControlDispatch;
pDriverObject->MajorFunction[IRP_MJ_CREATE]=DriverControlDispatch;
pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DriverControlDispatch;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DriverControlDispatch;

RtlInitUnicodeString(&DeviceName, L"\Device\FileM");
status = IoCreateDevice( pDriverObject,0,&DeviceName,0,0,TRUE,&pGControlDevice); // exclusive! only one control app!

if ( !NT_SUCCESS(status) )
{
KdPrint((“DriverEntry: IoCreateDevice(control) failure\n”));
DriverUnload(pDriverObject);
return status;
}

RtlInitUnicodeString(&LinkName, L"\DosDevices\FileM");
status = IoCreateSymbolicLink(&LinkName, &DeviceName);
if ( !NT_SUCCESS(status) )
{
KdPrint((“DriverEntry: IoCreateSymbolicLink failure\n”));
DriverUnload(pDriverObject);
return status;
}

HookAll();

return STATUS_SUCCESS;
}

NTSTATUS DriverControlDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status=STATUS_SUCCESS;

PIO_STACK_LOCATION irpStack;
PVOID inputBuffer;
PVOID outputBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
WORK_QUEUE_ITEM workItem;

//
// Go ahead and set the request up as successful
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;

//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);

//have a test
//LogRecord(“CurrentStackLocation Offset: %d”,(UCHAR
)&(Irp->Tail.Overlay.CurrentStackLocation)-(UCHAR
)Irp);
//LogRecord(“DeviceObject Offset: %d”,(UCHAR
)&(irpStack->FileObject)-(UCHAR
)irpStack);

//

//
// Get the pointer to the input/output buffer and its length
//
inputBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = Irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
break;

case IRP_MJ_SHUTDOWN:
break;

case IRP_MJ_CLOSE:
break;

case IRP_MJ_DEVICE_CONTROL:

KdPrint ((“[FileM]: IRP_MJ_DEVICE_CONTROL\n”));

//
// See if the output buffer is really a user buffer that we
// can just dump data into.
//
if( IOCTL_TRANSFER_TYPE(ioControlCode) == METHOD_NEITHER )
{
outputBuffer = Irp->UserBuffer;
}

//
// Its a request from the GUI
//
DeviceControlDipatch( irpStack->FileObject, TRUE,
inputBuffer, inputBufferLength,
outputBuffer, outputBufferLength,
ioControlCode, &Irp->IoStatus, DeviceObject );
break;
}
IoCompleteRequest( Irp, IO_NO_INCREMENT );

return status;
}

BOOLEAN DeviceControlDipatch(IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
IoStatus->Status = STATUS_SUCCESS; // Assume success
IoStatus->Information = 0; // Assume nothing returned
switch ( IoControlCode )
{

case IOCTL_FILEM_HOOK:
KdPrint ((“[FileM]: hook\n”));
HookAll();
break;

case IOCTL_FILEM_UNHOOK:
KdPrint((“[FileM]: unhook\n”));
UnHookAll();
break;

case IOCTL_FILEM_GETLOG:
KdPrint((“[FileM]: getlog\n”));
if (OutputBufferLength==LOGINF_LEN && OutputBuffer!=NULL)
{
IoStatus->Information=GetLogTxt(OutputBuffer);
}
else
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
}

break;

case IOCTL_FILEM_SETFILTER:
KdPrint((“[FileM]: SetProtectPath\n”));

if( InputBufferLength>FILTER_LEN || InputBuffer == NULL )
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}

MUTEX_ACQUIRE(ProtectPathMutex);

RtlFillMemory(ProtectPath,FILTER_LEN,0);
RtlCopyMemory(ProtectPath,InputBuffer,InputBufferLength);
LowStr(ProtectPath);

MUTEX_RELEASE(ProtectPathMutex);

break;
case IOCTL_FILEM_SETEXCLUDE:
KdPrint((“[FileM]: SetExcludePath\n”));

if( InputBufferLength>FILTER_LEN || InputBuffer == NULL )
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}

MUTEX_ACQUIRE(ExcludePathMutex);

RtlFillMemory(ExcludePath,FILTER_LEN,0);
RtlCopyMemory(ExcludePath,InputBuffer,InputBufferLength);
LowStr(ExcludePath);

MUTEX_RELEASE(ExcludePathMutex);

break;
case IOCTL_FILEM_SETPROCESS:
KdPrint((“[FileM]: SetExcludePath\n”));

if( InputBufferLength>FILTER_LEN || InputBuffer == NULL )
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
break;
}

MUTEX_ACQUIRE(ExcludeProcessMutex);

RtlFillMemory(ExcludeProcess,FILTER_LEN,0);
RtlCopyMemory(ExcludeProcess,InputBuffer,InputBufferLength);
LowStr(ExcludeProcess);

MUTEX_RELEASE(ExcludeProcessMutex);

break;

default:
KdPrint((“Regmon: invalid request\n”));
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return TRUE;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
if (bHooked)
{
UnHookAll();
}
if (pGControlDevice!=NULL)
{
UNICODE_STRING LinkName;
RtlInitUnicodeString(&LinkName, L"\??\FileM");
IoDeleteSymbolicLink(&LinkName);
IoDeleteDevice(pGControlDevice);
}

}

VOID HookAll()
{
if (!bHooked)
{
HookZwSetInformationFile();
HookZwWriteFile();
HookZwCreateFile();

#if DBG
#else
HookZwQuerySystemInformation();
#endif

bHooked=TRUE;
LogRecord(“[FileM]: ???\r\n”);
}

}

VOID UnHookAll()
{
if (bHooked)
{
UnHookZwSetInformationFile();
UnHookZwWriteFile();
UnHookZwCreateFile();
#if DBG
#else
UnHookZwQuerySystemInformation();
#endif
bHooked=FALSE;
LogRecord(“[FileM]: ???\r\n”);
}

}

VOID HookZwSetInformationFile()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwSetInformationFile");
pZwSetInformationFileSDT = KeServiceDescriptorTable->ServiceTableBase + *(PULONG)((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OldZwSetInformationFile = (ZWSETINFORMATIONFILE)pZwSetInformationFileSDT;

__asm
{
cli
mov eax,cr0
and eax,not 10000h //??cr0?WP?
mov cr0,eax
}
*pZwSetInformationFileSDT = (ULONG)NewZwSetInformationFile;

__asm
{
mov eax,cr0
or eax,10000h //??cr0?WP?
mov cr0,eax
sti
}
}

VOID HookZwWriteFile()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwWriteFile");
pZwWriteFileSDT = KeServiceDescriptorTable->ServiceTableBase + *(PULONG)((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OldZwWriteFile = (ZWWRITEFILE)pZwWriteFileSDT;

__asm
{
cli
mov eax,cr0
and eax,not 10000h //??cr0?WP?
mov cr0,eax
}
*pZwWriteFileSDT = (ULONG)NewZwWriteFile;

__asm
{
mov eax,cr0
or eax,10000h //??cr0?WP?
mov cr0,eax
sti
}
}

VOID HookZwCreateFile()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwCreateFile");
pZwCreateFileSDT = KeServiceDescriptorTable->ServiceTableBase + *(PULONG)((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OldZwCreateFile = (ZWCREATEFILE)pZwCreateFileSDT;

__asm
{
cli
mov eax,cr0
and eax,not 10000h //??cr0?WP?
mov cr0,eax
}
*pZwCreateFileSDT = (ULONG)NewZwCreateFile;

__asm
{
mov eax,cr0
or eax,10000h //??cr0?WP?
mov cr0,eax
sti
}
}

VOID HookZwQuerySystemInformation()
{
UNICODE_STRING strFuncName;
RtlInitUnicodeString(&strFuncName, L"ZwQuerySystemInformation");
pZwQuerySystemInformationSDT = KeServiceDescriptorTable->ServiceTableBase + (PULONG)((PUCHAR)MmGetSystemRoutineAddress(&strFuncName) + 1);
OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)pZwQuerySystemInformationSDT;

__asm
{
cli
mov eax,cr0
and eax,not 10000h //??cr0?WP?
mov cr0,eax
}
pZwQuerySystemInformationSDT = (ULONG)NewZwQuerySystemInformation;

__asm
{
mov eax,cr0
or eax,10000h //??cr0?WP?
mov cr0,eax
sti
}
}

VOID HookZwQuerySystemInformation_org()
{
_asm{
cli;
mov eax,cr0
mov OldCr0,eax
and eax,0fffeffffh
mov cr0,eax
}
_asm{

mov ecx, dword ptr [ZwQuerySystemInformation];
mov edx, [ecx+1];
mov eax, dword ptr [KeServiceDescriptorTable];
mov esi, [eax];
mov edx, [esi+edx
4];
mov dword ptr [OldZwQuerySystemInformation], edx
mov ecx, [ecx+1]
mov eax, [eax]
mov dword ptr [eax+ecx
4], offset NewZwQuerySystemInformation;

}
_asm
{
mov eax,OldCr0
mov cr0,eax
sti;
}

}

VOID UnHookZwSetInformationFile()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*pZwSetInformationFileSDT = (ULONG)OldZwSetInformationFile;

__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}

VOID UnHookZwWriteFile()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*pZwWriteFileSDT = (ULONG)OldZwWriteFile;

__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}

VOID UnHookZwCreateFile()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
pZwCreateFileSDT = (ULONG)OldZwCreateFile;

__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}

VOID UnHookZwQuerySystemInformation()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
pZwQuerySystemInformationSDT = (ULONG)OldZwQuerySystemInformation;

__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}

VOID UnHookZwQuerySystemInformation_org()
{
_asm{
cli;
mov eax,cr0
mov OldCr0,eax
and eax,0fffeffffh
mov cr0,eax
}

_asm{

mov ecx, dword ptr [ZwQuerySystemInformation];
mov edx, [ecx+1];
mov eax, dword ptr [KeServiceDescriptorTable];
mov esi, [eax];
mov ebx, dword ptr [OldZwQuerySystemInformation];
mov [esi+edx
4],ebx;
}

_asm
{
mov eax,OldCr0
mov cr0,eax
sti;
}

}

NTSTATUS NewZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT pFileObject=NULL;
UNICODE_STRING uDosName;
NTSTATUS ret = STATUS_SUCCESS;
UNICODE_STRING PreNameFtdisk;
UNICODE_STRING PreNameVolmgr;
CHAR ProcName[NT_PROCNAMELEN]={0};

ret=ObReferenceObjectByHandle(FileHandle, GENERIC_READ, IoFileObjectType, KernelMode, (PVOID)&pFileObject, 0);

if (NT_SUCCESS(ret) && pFileObject!=NULL)
{
RtlInitUnicodeString(&PreNameFtdisk,L"\Driver\Ftdisk");
RtlInitUnicodeString(&PreNameVolmgr,L"\Driver\Volmgr");

if (pFileObject->Type==IO_TYPE_FILE && pFileObject->DeviceObject!=NULL && pFileObject->DeviceObject->DriverObject!=NULL && pFileObject->FileName.Buffer!=NULL && <br> (RtlCompareUnicodeString(&(pFileObject->DeviceObject->DriverObject->DriverName),&PreNameFtdisk,TRUE)==0 || <br> RtlCompareUnicodeString(&(pFileObject->DeviceObject->DriverObject->DriverName),&PreNameVolmgr,TRUE)==0))
{
uDosName.Buffer=NULL;
ret = IoVolumeDeviceToDosName(pFileObject->DeviceObject, &uDosName);
if (NT_SUCCESS(ret) && uDosName.Buffer!=NULL)
{
UNICODE_STRING FileName;
CHAR szFileName[NT_FILENAMELEN]={0};

FileName.Length=0;
FileName.MaximumLength=NT_FILENAMELEN;
FileName.Buffer=(PWCHAR)szFileName;

RtlCopyUnicodeString(&FileName,&uDosName);
RtlAppendUnicodeStringToString(&FileName,&(pFileObject->FileName));

if ((FileInformationClass==FileDispositionInformation && ((PFILE_DISPOSITION_INFORMATION)FileInformation)->DeleteFile) || <br> FileInformationClass==FileRenameInformation)
{
if (!NT_SUCCESS((AccessFilter(&FileName))))
{
ANSI_STRING as;
RtlUnicodeStringToAnsiString(&as, &FileName, TRUE);

if (FileInformationClass==FileRenameInformation)
{
KdPrint((“[%s] ReName File: %Z\r\n”,GetProcess(ProcName),&as));
LogRecord(“<modify_alarm>[%s]\tReName\t%Z\r\n”,GetProcess(ProcName),&as);
}
else
{
KdPrint((“[%s] Delete File: %Z\r\n”,GetProcess(ProcName),&as));
LogRecord(“<modify_alarm>[%s]\tDelete\t%Z\r\n”,GetProcess(ProcName),&as);
}

RtlFreeAnsiString(&as);
ExFreePool(uDosName.Buffer);
ObDereferenceObject(pFileObject);
return STATUS_ACCESS_DENIED;
}

}

}

if (uDosName.Buffer!=NULL)
{
ExFreePool(uDosName.Buffer);
}
}

ObDereferenceObject(pFileObject);
}

return OldZwSetInformationFile(FileHandle, IoStatusBlock, FileInformation,Length, FileInformationClass);

}

NTSTATUS NewZwWriteFile(IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL)
{
PFILE_OBJECT pFileObject=NULL;
UNICODE_STRING uDosName;
NTSTATUS ret = STATUS_SUCCESS;
UNICODE_STRING PreNameFtdisk;
UNICODE_STRING PreNameVolmgr;
CHAR ProcName[NT_PROCNAMELEN]={0};

ret=ObReferenceObjectByHandle(FileHandle, GENERIC_READ, IoFileObjectType, KernelMode, (PVOID)&pFileObject, 0);

if (NT_SUCCESS(ret) && pFileObject!=NULL)
{
RtlInitUnicodeString(&PreNameFtdisk,L"\Driver\Ftdisk");
RtlInitUnicodeString(&PreNameVolmgr,L"\Driver\Volmgr");

if (pFileObject->Type==IO_TYPE_FILE && pFileObject->DeviceObject!=NULL && pFileObject->DeviceObject->DriverObject!=NULL && pFileObject->FileName.Buffer!=NULL && <br> (RtlCompareUnicodeString(&(pFileObject->DeviceObject->DriverObject->DriverName),&PreNameFtdisk,TRUE)==0 || <br> RtlCompareUnicodeString(&(pFileObject->DeviceObject->DriverObject->DriverName),&PreNameVolmgr,TRUE)==0))
{
uDosName.Buffer=NULL;
ret = IoVolumeDeviceToDosName(pFileObject->DeviceObject, &uDosName);
if (NT_SUCCESS(ret) && uDosName.Buffer!=NULL)
{
UNICODE_STRING FileName;
CHAR szFileName[NT_FILENAMELEN]={0};

FileName.Length=0;
FileName.MaximumLength=NT_FILENAMELEN;
FileName.Buffer=(PWCHAR)szFileName;

RtlCopyUnicodeString(&FileName,&uDosName);
RtlAppendUnicodeStringToString(&FileName,&(pFileObject->FileName));

if (!NT_SUCCESS((AccessFilter(&FileName))))
{
ANSI_STRING as;
RtlUnicodeStringToAnsiString(&as, &FileName, TRUE);

KdPrint((“[%s] Write File: %Z\r\n”,GetProcess(ProcName),&as));
LogRecord(“<modify_alarm>[%s]\tWrite\t%Z\r\n”,GetProcess(ProcName),&as);

RtlFreeAnsiString(&as);

ExFreePool(uDosName.Buffer);
ObDereferenceObject(pFileObject);
return STATUS_ACCESS_DENIED;
}

}

if (uDosName.Buffer!=NULL)
{
ExFreePool(uDosName.Buffer);
}
}

ObDereferenceObject(pFileObject);
}

return OldZwWriteFile(FileHandle, Event,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);

}

NTSTATUS NewZwCreateFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer,
IN ULONG EaLength)

{
CHAR ProcName[NT_PROCNAMELEN]={0};
KdPrint((“[NewZwCreateFile] Enter–%wZ CreateDisposition: %d ShareAccess: %d CreateOptions: %d DesiredAccess: %d\n “,ObjectAttributes->ObjectName,CreateDisposition,ShareAccess,CreateOptions,DesiredAccess));

if (ObjectAttributes->ObjectName->Length>4 && _wcsnicmp(ObjectAttributes->ObjectName->Buffer,L”\??\”,4)==0)
{
UNICODE_STRING FileName;

RtlInitUnicodeString(&FileName,ObjectAttributes->ObjectName->Buffer+4);

/

KdPrint((“[%s] Create File: %wZ DeiredAccess: 0x%08X ShareAccess: 0x%08X CreateDisposition: 0x%08X CreateOptions: 0x%08X\r\n”,
GetProcess(ProcName),&FileName,DesiredAccess,ShareAccess,CreateDisposition,CreateOptions));
*/

if (CreateDisposition == FILE_CREATE || CreateDisposition == FILE_SUPERSEDE || CreateDisposition == FILE_OVERWRITE || CreateDisposition == FILE_OVERWRITE_IF || (DesiredAccess &(GENERIC_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA))!=0)
{
if (!NT_SUCCESS((AccessFilter(&FileName))))
{
ANSI_STRING as;
RtlUnicodeStringToAnsiString(&as, &FileName, TRUE);
KdPrint((“[%s] Create File: %Z DeiredAccess: 0x%08X ShareAccess: 0x%08X CreateDisposition: 0x%08X CreateOptions: 0x%08X\r\n”,
GetProcess(ProcName),&as,DesiredAccess,ShareAccess,CreateDisposition,CreateOptions));
LogRecord(“<modify_alarm>[%s]\tCreate\t%Z\r\n”,GetProcess(ProcName),&as);

RtlFreeAnsiString(&as);

return STATUS_ACCESS_DENIED;
}
}

}

return OldZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,
FileAttributes,ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);

}

NTSTATUS NewZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength)
{
NTSTATUS rc;

UNICODE_STRING process_name;

//KdPrint((“[NewZwQuerySystemInformation] Enter\n”));
RtlInitUnicodeString(&process_name, L"WPAgent.exe");

rc = (OldZwQuerySystemInformation) (
SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength);

if(NT_SUCCESS(rc))
{
if(5 == SystemInformationClass)
{
struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
struct _SYSTEM_PROCESSES *prev = NULL;
if(curr->NextEntryDelta)((char *)curr += curr->NextEntryDelta);

while(curr)
{

if (RtlEqualUnicodeString(&process_name, &curr->ProcessName, 1))

{

if(prev)
{
if(curr->NextEntryDelta)
{
prev->NextEntryDelta += curr->NextEntryDelta;
}
else
{
prev->NextEntryDelta = 0;
}
}
else
{
if(curr->NextEntryDelta)
{
(char *)SystemInformation += curr->NextEntryDelta;
}
else
{
SystemInformation = NULL;
}
}

if(curr->NextEntryDelta)((char *)curr += curr->NextEntryDelta);
else
{
curr = NULL;
break;
}
}

if(curr != NULL)
{
prev = curr;
if(curr->NextEntryDelta)((char )curr += curr->NextEntryDelta);
else curr = NULL;
}

}
}
}

return rc;

}

VOID LogRecord(const PCHAR format,…)
{
ULONG len;
va_list arg_ptr;
CHAR LogTxt[2048]={0};

/

#define A (&format)
KdPrint(( (char )format, A[1], A[2], A[3], A[4], A[5], A[6] ));
KdPrint(( “\n” ));
#undef A
/

va_start( arg_ptr, format);
len = vsprintf(LogTxt,format,arg_ptr);
va_end( arg_ptr );

MUTEX_ACQUIRE(LogInfMutex);

if (pLogInfEnd+len>=LogInf+LOGINF_LEN)
{
RtlCopyMemory(pLogInfEnd,LogTxt,LogInf+LOGINF_LEN-pLogInfEnd);
RtlCopyMemory(LogInf,LogTxt+(LogInf+LOGINF_LEN-pLogInfEnd),len-(LogInf+LOGINF_LEN-pLogInfEnd));
pLogInfEnd=pLogInfEnd+len-LOGINF_LEN;
*pLogInfEnd=0;
pLogInfEnd++;

}
else
{
RtlCopyMemory(pLogInfEnd,LogTxt,len);
pLogInfEnd+=len;
*pLogInfEnd=0;
pLogInfEnd++;
}

MUTEX_RELEASE(LogInfMutex);

}

ULONG GetLogTxt(IN PCHAR LogTxt)
{
ULONG TotalLen=0;

MUTEX_ACQUIRE(LogInfMutex);

if (pLogInfEnd>pLogInfStart)
{
TotalLen=pLogInfEnd-pLogInfStart;
memcpy(LogTxt,pLogInfStart,pLogInfEnd-pLogInfStart);
pLogInfStart=pLogInfEnd;
*pLogInfEnd=0;
}
else if (pLogInfEnd {
TotalLen=pLogInfEnd+LOGINF_LEN-pLogInfStart;
memcpy(LogTxt,pLogInfStart,LogInf+LOGINF_LEN-pLogInfStart);
memcpy(LogTxt+(LogInf+LOGINF_LEN-pLogInfStart),LogInf,pLogInfEnd-LogInf);
pLogInfStart=pLogInfEnd;
*pLogInfEnd=0;
}

MUTEX_RELEASE(LogInfMutex);

return TotalLen;
}

PCHAR LowStr(PCHAR str)
{
int len=strlen(str);
int i=0;
for (i=0;i {
if(str[i]>=‘A’ && str[i]<=‘Z’)
{
str[i]=str[i]-‘A’+‘a’;
}
}
return str;
}

NTSTATUS InExcludeProcess()
{
CHAR ProcName[NT_PROCNAMELEN]={0};
CHAR PatterStr[1024]={0};

GetProcess(ProcName);
LowStr(ProcName);
strcpy(PatterStr,“;”);
strcat(PatterStr,ProcName);
strcat(PatterStr,“;”);

if (strstr(ExcludeProcess,PatterStr)==NULL)
{
return STATUS_ACCESS_DENIED;
}

return STATUS_SUCCESS;
}

NTSTATUS AccessFilter(PUNICODE_STRING FileName)
{
ANSI_STRING FileNameAnsi;
CHAR DirectoryName[1024]={0};
CHAR PatterStr[1024]={0};
CHAR ExcludePatterStr[1024]={0};
CHAR ExtendPatterStr[32]={0};
PCHAR c=NULL;
int i=0;

KdPrint((“AccessFilter: %wZ”,FileName));

if (!bProtect)
{
return STATUS_SUCCESS;
}

if (NT_SUCCESS(InExcludeProcess()))
{
return STATUS_SUCCESS;
}

RtlUnicodeStringToAnsiString(&FileNameAnsi,FileName,TRUE);

if (FileNameAnsi.Buffer==NULL)
{
return STATUS_SUCCESS;
}

//if (strstr(FileNameAnsi.Buffer,“:\”)==NULL)
if (FileNameAnsi.Length<3 || FileNameAnsi.Buffer[1]!=‘:’ || FileNameAnsi.Buffer[2]!=‘\’)
{
RtlFreeAnsiString(&FileNameAnsi);
return STATUS_SUCCESS;
}

strncpy(DirectoryName,FileNameAnsi.Buffer,1000<filenameansi.length> LowStr(DirectoryName);

RtlFreeAnsiString(&FileNameAnsi);

c=strrchr(DirectoryName,‘.’);
if (c!=NULL)
{
if (strlen(c)<30)
{
strcpy(ExtendPatterStr,“;”);
strcat(ExtendPatterStr,c);
strcat(ExtendPatterStr,“;”);

if (strstr(ExcludePath,ExtendPatterStr)!=NULL)
{
return STATUS_SUCCESS;
}

}

}

strcpy(PatterStr,“;”);
strcat(PatterStr,DirectoryName);

if (PatterStr[strlen(PatterStr)-1]==‘\’)
{
PatterStr[strlen(PatterStr)-1]=‘;’;
}
else
{
strcat(PatterStr,“;”);
}

strcpy(ExcludePatterStr,PatterStr);

if (strstr(ExcludePath,ExcludePatterStr)!=NULL)
{
return STATUS_SUCCESS;
}
while ((c=strrchr(ExcludePatterStr,‘\’))!=NULL)
{
*(c)=‘;’;
*(c+1)=0;

if (strstr(ExcludePath,ExcludePatterStr)!=NULL)
{
return STATUS_SUCCESS;
}
*c=0;

}

if (strstr(ProtectPath,PatterStr)!=NULL)
{
return STATUS_ACCESS_DENIED;
}

while ((c=strrchr(PatterStr,‘\’))!=NULL)
{
*(c)=‘;’;
*(c+1)=0;

if (strstr(ProtectPath,PatterStr)!=NULL)
{
return STATUS_ACCESS_DENIED;
}
c=0;

}

return STATUS_SUCCESS;

}

ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;

curproc = PsGetCurrentProcess();

//
// Scan for 12KB, hopping the KPEB never grows that big!
//
for( i = 0; i < 3
PAGE_SIZE; i++ )
{

if( !strncmp( “System”, (PCHAR) curproc + i, strlen(“System”) ))
{

return i;
}
}

//
// Name not found - oh, well
//
return 0;
}

//----------------------------------------------------------------------
//
// GetProcess
//
// Uses undocumented data structure offsets to obtain the name of the
// currently executing process.
//
//----------------------------------------------------------------------
PCHAR GetProcess(PCHAR Name)
{
PEPROCESS curproc;
char *nameptr;
ULONG i;

//
// We only try and get the name if we located the name offset
//
if( ProcessNameOffset)
{

//
// Get a pointer to the current process block
//
curproc = PsGetCurrentProcess();

//
// Dig into it to extract the name. Make sure to leave enough room
// in the buffer for the appended process ID.
//
nameptr = (PCHAR) curproc + ProcessNameOffset;
strncpy( Name, nameptr, NT_PROCNAMELEN-1 );

Name[NT_PROCNAMELEN-1] = 0;
//LogRecord(Name);

}
else
{
strcpy( Name, “???”);
}
return Name;
}</filenameansi.length></modify_alarm></modify_alarm></modify_alarm></modify_alarm></string.h></stdlib.h></stdarg.h></stdio.h></ntddk.h></ntifs.h>

Unrelated to the memory leaks in your code (I suggest compiling with
prefast), I suggest you read the following article:
http://www.matousec.com/info/articles/khobe-8.0-earthquake-for-windows-desktop-security-software.php

There are much better ways to accomplish this goal via supported
kernel infrastructure.

thanks first.

but the kernel memory in the windows task manager become to more and more, isn’t it because of memory leaks?

Hi!

I`m not reading the whole list, so sorry if my advice will be inconvinient.

When i`m got a memory leak, i tried to find it with driver verifer - it
can show all memory at the moment allocated with tag, an then show place where it
was allocated.

So in my driver i found a lot of memory pieces from one place in code and find out that
somewhere i return from function w/o memory cleaning, or another bug
was that some of ctors was cleaning member variables with allocated
memory.

Try tag your memory using ExAllocatePoolWithTag and check it with verifier and then see using !verifier 3 your
allocated memory.

Also you can use
!vm
!poolused
!verifier 3
!pool
!poolfind

and utils

pooltag
poolview

but for me - !verifier 3 was the most useful


Dmitry

Ohhh mannn wtf is that dump … :expressionless:
I see a lot lot lot of stuff that you should not do in this driver, from to
obvious hooking to

//----------------------------------------------------------------------
//
// GetProcess
//
// Uses undocumented data structure offsets to obtain the name of the
// currently executing process.
//
//----------------------------------------------------------------------
PCHAR GetProcess(PCHAR Name);

You might think its smart, ohh yeah I am getting the process base name from
an UNDOCUMENTED PEPROCESS structure woow, but it is actually one of the
worst things you can do in windows kernel accessing members of undocumented
structures. Did you test on x64 to see what happens ?
I suggest going back and rethinking what you want to do and consider
writting a minifilter, not copy pasting some open source rootkit’s code. And
by the way you do not protect a directory like that. Plus ZwWriteFile …
??? Wtf if you don’t have a handle to a file how can you write (as you
hooked ZwCreateFile). Anyway, there is no way you can succeed with hooking.
Think about file mapping.

Anyway,
Good luck.

> This is my first windows driver, I want to protect some directory. so I hook the ZwCreateFile,

ZwSetInformationFile and ZwWriteFile functions in the SDT table.

Do you want to be flagged as malware by antivirus/security products?

Write a minifilter instead. Much simpler and less error-prone.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>When i`m got a memory leak, i tried to find it with driver verifer - it

can show all memory at the moment allocated with tag, an then show place where it
as allocated.

Correct.

The user-mode POOLMON tool (executed on the target machine) is also useful.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> PCHAR GetProcess(PCHAR Name);

You might think its smart, ohh yeah I am getting the process base name from
an UNDOCUMENTED PEPROCESS structure woow, but it is actually one of the
worst things you can do in windows kernel accessing members of undocumented

Well, this is not the worst thing in this code.

Getting the “process name” in Windows is a known pain, especially if you will consider that there are 2 such names - one ANSI converted to 8.3, as shown by the Task Manager, another Unicode full EXE pathname. The trick he is using (cloned from some old code by Mark Russinovich) is only giving him the 8.3 shortened name :slight_smile:

As about the full EXE pathname of the process - I think that Windows older then some version (w2k? XP?) just do not keep it anywhere in the kernel. For instance, psapi!GetModuleFileNameEx on XP was using the RTL_USER_PROCESS_PARAMETERS structure in the user part of the target process and ReadProcessMemory to read it, it was not using any syscall.

Probably SSDT hooking (NtCreateSection) is even justfied on some Windows versions due to lack of other ways of getting the full EXE pathname, but surely not the file syscall hooking.

Using strxxx functions (instead of RtlStringXxx) is probably even worse then GetProcess :slight_smile:

Poor man’s upcase of the string with per-char analyzis - is too.

Also, why CHAR? Why not WCHAR as must be in the kernel?

And the worst thing about all this code - it tries to unhook and unload. This cannot be done reliably. There are no mechanisms in the whole OS to prevent such a driver from being unloaded while being executed.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim, this is a common thing in people who start writing the first driver as there is nothing for them to do and they need to make it look and feel like the user mode applications. The beginner driver writers do not actually read documentation at first and try to code after, they just go ahead and copy paste what they find on google and hack the s***t out of each driver and later they ask themselves why they cannot extend their design or make it work on different versions of windows.

Very possibly, because most likely your hooks ain’t working. With very rare
exception this is NOT the list to walk in bragging about how your “hooking”
software is working but the task manager has memory leaks.

Gary G. Little
H (952) 223-1349
C (952) 454-4629
xxxxx@comcast.net

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of anti_decoy@126.com
Sent: Wednesday, July 28, 2010 11:13 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] about memory leak in my driver…somebody help me?

thanks first.

but the kernel memory in the windows task manager become to more and more,
isn’t it because of memory leaks?


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars (including our new fs
mini-filter seminar) visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer