Author: sinister
Email: sinister@whitecell.org
Homepage:http://www.whitecell.org
Date: 2006-01-10
/*****************************************************************
文件名 : WssFilterDrv.c
描述 : 跟踪记录现有设备驱动
作者 : sinister
最后修改日期 : 2006.1.09
*****************************************************************/
#include "ntddk.h"
#include "string.h"
#include "stdio.h"
//
// 输入标志
//
#define IN_BUFFER_FLAG 0x925
//
// 输出标志
//
#define OUT_BUFFER_FLAG 0x926
////////////////////////////////////////////////////////////////
// 结构作用 :设备对象扩展结构,用于保存过滤设备信息
// 注意 : 需设备对象 DEVICE_OBJECT 有效情况下使用
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject; // 过滤设备对象
PDEVICE_OBJECT TargetDevice; // 附加后的设备对象
PFILE_OBJECT FileObject; // 原设备的文件对象
ULONG DeviceExtensionFlags; // 预留的扩展标志
}DEVICE_EXTENSION, * PDEVICE_EXTENSION;
VOID DriverUnload( IN PDRIVER_OBJECT DriverObject );
NTSTATUS DispatchPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS CompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context );
NTSTATUS WriteLog( PVOID lpBuffer, ULONG uSize );
NTSTATUS GetSystemBuffer( PIRP Irp, PVOID pBuffer, SIZE_T Length, LONG* pMode );
NTSTATUS FormatMessage( ULONG IoControl,
PUCHAR pBuf,
ULONG uSize,
ULONG dwStatus,
ULONG uMode );
NTSTATUS ReadIOCtrlBuffer( PIRP Irp,
PIO_STACK_LOCATION pIrpStack,
ULONG dwStatus );
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 :创建过滤设备将其附加到需要跟踪的设备上,保存设备相关
// 信息,返回附加后的驱动对象
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
AttachFilterDevice( IN UNICODE_STRING* DeviceName, // 需要跟踪的设备名
IN PDRIVER_OBJECT DriverObject, // 过滤驱动也就是本驱动的驱动对象
OUT PDRIVER_OBJECT* FilterDriverObject ) // 返回附加后的驱动对象
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT FilterDeviceObject;
PDEVICE_OBJECT TargetDevice;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DevExt;
NTSTATUS ntStatus;
//
// 根据设备名称找到需要附加的设备对象
//
ntStatus = IoGetDeviceObjectPointer( DeviceName,
FILE_ALL_ACCESS,
&FileObject,
&DeviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrint( "IoGetDeviceObjectPointer() %d\n", ntStatus );
return ntStatus;
}
//
// 创建过滤设备对象
//
ntStatus = IoCreateDevice( DriverObject,
sizeof( DEVICE_EXTENSION ),
NULL,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&FilterDeviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
ObDereferenceObject( FileObject );
DbgPrint( "IoCreateDevice() %d!\n", ntStatus );
return ntStatus;
}
//
// 得到设备扩展结构,以便下面保存过滤设备信息
//
DevExt = ( PDEVICE_EXTENSION ) FilterDeviceObject->DeviceExtension;
//
// 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象
//
TargetDevice = IoAttachDeviceToDeviceStack( FilterDeviceObject,
DeviceObject );
if ( !TargetDevice )
{
ObDereferenceObject( FileObject );
IoDeleteDevice( FilterDeviceObject );
DbgPrint( "IoAttachDeviceToDeviceStack() %d!\n", ntStatus );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 保存过滤设备信息
//
DevExt->DeviceObject = FilterDeviceObject;
DevExt->TargetDevice = TargetDevice;
DevExt->FileObject = FileObject;
//
// 设置过滤设备相关信息与标志
//
FilterDeviceObject->DeviceType = TargetDevice->DeviceType;
FilterDeviceObject->Characteristics = TargetDevice->Characteristics;
FilterDeviceObject->Flags |= ( TargetDevice->Flags & ( DO_DIRECT_IO |
DO_BUFFERED_IO ) );
//
// 返回附加后的驱动对象
//
*FilterDriverObject = TargetDevice->DriverObject;
ObDereferenceObject( FileObject );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 得到内核/用户模式 I/O 缓冲区数据,并返回当前数据所
// 在模式
// 注意 : 在 "过滤模块" 中此函数是为了配合 ReadIOCtrlBuffer
// 函数得到数据
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
GetSystemBuffer( PIRP Irp, PVOID pBuffer, SIZE_T Length, LONG* pMode )
{
PUCHAR pSysBuffer = NULL;
if ( pBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 判断当前 I/O 模式与数据存放的位置
//
switch ( Irp->RequestorMode )
{
case KernelMode:
*pMode = 0; // 内核模式 I/O
if ( Irp->UserBuffer )
{
pSysBuffer = Irp->UserBuffer;
}
else if ( Irp->MdlAddress )
{
pSysBuffer = ( PUCHAR )
MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
NormalPagePriority );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
break;
case UserMode:
*pMode = 1; // 用户模式 I/O
if ( Irp->UserBuffer )
{
pSysBuffer = Irp->UserBuffer;
}
else if ( Irp->MdlAddress )
{
pSysBuffer = ( PUCHAR )
MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
NormalPagePriority );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
break;
default:
break;
}
//
// 输出得到的缓冲区
//
RtlCopyMemory( pBuffer, pSysBuffer, Length );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 格式化缓冲区数据,并记录日志
// 注意 : 在 "过滤模块" 中此函数作用是格式化 GetSystemBuffer
函数得到的数据。因为此函数调用了日志函数,所以此函数
// 仅能在 IRQL == PASSVIE_LEVEL 级别运行。
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 : sinister
// 修改日期 : 2006.01.03
// 修改内容 : 在函数中增加了记录日志函数
/////////////////////////////////////////////////////////////////
NTSTATUS
FormatMessage( ULONG IoControl,
PUCHAR pBuf,
ULONG uSize,
ULONG dwStatus,
ULONG uMode )
{
ULONG uLen;
ULONG uCount = 0;
PVOID pBuffer = NULL;
UCHAR uTitle[100];
UCHAR uTemp[3];
if ( pBuf == NULL || uSize < 0 )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 低层驱动返回数据后,设置此标志
//
if ( dwStatus == OUT_BUFFER_FLAG )
{
if ( uMode == 0 )
{
sprintf( uTitle, "KERNEL MODE: IoControl=%x, OUTBUFFER:\n", IoControl );
}
else
{
sprintf( uTitle, "USER MODE: IoControl=%x, OUTBUFFER:\n", IoControl );
}
}
//
// 上层向低层驱动发送数据,设置此标志
//
else if ( dwStatus == IN_BUFFER_FLAG )
{
if ( uMode == 0 )
{
sprintf( uTitle, "KERNEL MODE: IoControl=%x, INBUFFER:\n", IoControl );
}
else
{
sprintf( uTitle, "USER MODE: IoControl=%x, INBUFFER:\n", IoControl );
}
}
//
// 记录日志,目的是记录分析,所以没有考虑效率。
//
WriteLog( uTitle, strlen( uTitle ) );
for ( uLen = 0; uLen < uSize; uLen++ )
{
sprintf( uTemp, "%.2X ", pBuf[uLen] );
WriteLog( uTemp, sizeof( uTemp ) );
if ( uLen % 16 == 0 )
{
WriteLog( "\n", 1 );
}
}
WriteLog( "\n", 1 );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 得到 IRP_MJ_DEVICE_CONTROL 的 I/O 数据
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
ReadIOCtrlBuffer( PIRP Irp, PIO_STACK_LOCATION pIrpStack, ULONG dwStatus )
{
ULONG InBufLen;
ULONG OutBufLen;
ULONG IoControl;
PUCHAR pSysBuffer = NULL;
KEVENT KrnlEvent;
NTSTATUS ntStatus;
ULONG uMode;
//
// 得到设备控制字与 I/O 缓冲区长度
//
InBufLen = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutBufLen = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
IoControl = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
if ( dwStatus == OUT_BUFFER_FLAG )
{
//
// 如果是低层驱动返回的数据,缓冲区长度则要这样获得
//
OutBufLen = Irp->IoStatus.Information;
pSysBuffer = ( PUCHAR ) ExAllocatePool( PagedPool,
OutBufLen + sizeof( PUCHAR ) );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
ntStatus = GetSystemBuffer( Irp, pSysBuffer, OutBufLen, &uMode );
if ( !NT_SUCCESS( ntStatus ) )
{
ExFreePool( pSysBuffer );
return STATUS_INSUFFICIENT_RESOURCES;
}
FormatMessage( IoControl, pSysBuffer, OutBufLen, dwStatus, uMode );
}
else
{
pSysBuffer = ( PUCHAR ) ExAllocatePool( PagedPool,
InBufLen + sizeof( PUCHAR ) );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
ntStatus = GetSystemBuffer( Irp, pSysBuffer, InBufLen, &uMode );
if ( !NT_SUCCESS( ntStatus ) )
{
ExFreePool( pSysBuffer );
return STATUS_INSUFFICIENT_RESOURCES;
}
FormatMessage( IoControl, pSysBuffer, InBufLen, dwStatus, uMode );
}
if ( pSysBuffer )
{
ExFreePool( pSysBuffer );
}
return Irp->IoStatus.Status;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 替换指定设备的驱动例程使其指向当前过滤驱动的派遣例程
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
PDRIVER_OBJECT FilterDrvObj;
UNICODE_STRING DeviceName;
PDRIVER_DISPATCH EmptyDispatch;
NTSTATUS ntStatus;
ULONG iCount;
EmptyDispatch = DriverObject->MajorFunction[IRP_MJ_CREATE];
RtlInitUnicodeString( &DeviceName, L"\\Device\\FNT0" );
FilterDrvObj = NULL;
DriverObject->DriverUnload = DriverUnload;
ntStatus = AttachFilterDevice( &DeviceName, DriverObject, &FilterDrvObj );
if ( !NT_SUCCESS( ntStatus ) || FilterDrvObj == NULL )
{
DbgPrint( "Attach Device to failed!\n" );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 只过滤目标驱动对象使用的例程
//
for ( iCount = 0; iCount < IRP_MJ_MAXIMUM_FUNCTION; iCount++ )
{
if ( FilterDrvObj->MajorFunction[iCount] != EmptyDispatch &&
DriverObject->MajorFunction[iCount] == EmptyDispatch )
{
DriverObject->MajorFunction[iCount] = DispatchPassThrough;
}
}
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 删除并卸载过滤设备
// 注意 : 卸载列程中并没有做过多的处理,在过滤驱动中如果当前所
// 附加的设备IRP 很多的情况下,这样做可能会导致 BSOD
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
VOID
DriverUnload( IN PDRIVER_OBJECT DriverObject )
{
PDEVICE_OBJECT FilterDevice;
PDEVICE_OBJECT TargetDevice;
PDEVICE_EXTENSION DevExt;
NTSTATUS ntStatus;
FilterDevice = DriverObject->DeviceObject;
DevExt = ( PDEVICE_EXTENSION ) FilterDevice->DeviceExtension;
TargetDevice = DevExt->TargetDevice;
//
// 从目标断开附加设备,并删除过滤设备
//
IoDetachDevice( TargetDevice );
IoDeleteDevice( FilterDevice );
return;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 过滤驱动的派遣例程
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
DispatchPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PIO_STACK_LOCATION pIrpStack;
PDEVICE_OBJECT pDeviceObject;
PDEVICE_EXTENSION DevExtension = ( PDEVICE_EXTENSION )
DeviceObject->DeviceExtension;
NTSTATUS ntStatus;
KEVENT KrnlEvent;
pIrpStack = IoGetCurrentIrpStackLocation( Irp );
//
// 这里只过滤了 IRP_MJ_DEVICE_CONTROL 需要过滤更多的控制字可以
// 在这里增加判断
//
if ( pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
{
//
// 上层发送数据,设置 IN_BUFFER_FLAG 标志记录。
//
ReadIOCtrlBuffer( Irp, pIrpStack, IN_BUFFER_FLAG );
//
// 因为是上层过滤驱动,所以必须向低层驱动请求返回数据
// 这里虽然没有对数据进行修改,但为了以后扩充方便
// 还是复制了 IRP 堆栈和安装完成列程
//
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, CompletionRoutine, NULL, TRUE, TRUE, TRUE );
( void ) IoCallDriver( DevExtension->TargetDevice, Irp );
//
// 当低层驱动返回数据后,设置 OUT_BUFFER_FLAG 标志,再次记录。
//
ntStatus = ReadIOCtrlBuffer( Irp, pIrpStack, OUT_BUFFER_FLAG );
return ntStatus;
}
//
// 对于其他控制字则直接传递到低层驱动,无须安装完成列程
//
else
{
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( DevExtension->TargetDevice, Irp );
}
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统回调函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 :
// 注意 : 这里没有对返回数据做操作
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
CompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
if ( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 记录日志到 C 盘的 WSSFILTER.LOG 中
// 注意 : 只能在 IRQL == PASSVIE_LEVEL 级别使用
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
WriteLog( PVOID lpBuffer, ULONG uSize )
{
NTSTATUS status;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_POSITION_INFORMATION FilePOTInfo;
FILE_STANDARD_INFORMATION FileSTDInfo;
ANSI_STRING ansiString;
UNICODE_STRING filenameString;
HANDLE hFile;
WCHAR LogFile[] = L"\\??\\C:\\WSSFILTER.LOG";
RtlInitUnicodeString( &filenameString, LogFile );
InitializeObjectAttributes( &ObjectAttributes,
&filenameString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile( &hFile,
GENERIC_WRITE | SYNCHRONIZE | GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if ( !NT_SUCCESS( status ) )
{
return status;
}
ZwQueryInformationFile( hFile,
&IoStatusBlock,
( void * ) &FileSTDInfo,
sizeof( FileSTDInfo ),
FileStandardInformation );
if ( !NT_SUCCESS( IoStatusBlock.Status ) )
{
return IoStatusBlock.Status;
}
FilePOTInfo.CurrentByteOffset = FileSTDInfo.EndOfFile;
ZwSetInformationFile( hFile,
&IoStatusBlock,
( void * ) &FilePOTInfo,
sizeof( FilePOTInfo ),
FilePositionInformation );
if ( !NT_SUCCESS( IoStatusBlock.Status ) )
{
return IoStatusBlock.Status;
}
ZwWriteFile( hFile, 0, 0, 0, &IoStatusBlock, lpBuffer, uSize, NULL, NULL );
ZwClose( hFile );
return IoStatusBlock.Status;
}
WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/
Email: sinister@whitecell.org
Homepage:http://www.whitecell.org
Date: 2006-01-10
/*****************************************************************
文件名 : WssFilterDrv.c
描述 : 跟踪记录现有设备驱动
作者 : sinister
最后修改日期 : 2006.1.09
*****************************************************************/
#include "ntddk.h"
#include "string.h"
#include "stdio.h"
//
// 输入标志
//
#define IN_BUFFER_FLAG 0x925
//
// 输出标志
//
#define OUT_BUFFER_FLAG 0x926
////////////////////////////////////////////////////////////////
// 结构作用 :设备对象扩展结构,用于保存过滤设备信息
// 注意 : 需设备对象 DEVICE_OBJECT 有效情况下使用
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject; // 过滤设备对象
PDEVICE_OBJECT TargetDevice; // 附加后的设备对象
PFILE_OBJECT FileObject; // 原设备的文件对象
ULONG DeviceExtensionFlags; // 预留的扩展标志
}DEVICE_EXTENSION, * PDEVICE_EXTENSION;
VOID DriverUnload( IN PDRIVER_OBJECT DriverObject );
NTSTATUS DispatchPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS CompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context );
NTSTATUS WriteLog( PVOID lpBuffer, ULONG uSize );
NTSTATUS GetSystemBuffer( PIRP Irp, PVOID pBuffer, SIZE_T Length, LONG* pMode );
NTSTATUS FormatMessage( ULONG IoControl,
PUCHAR pBuf,
ULONG uSize,
ULONG dwStatus,
ULONG uMode );
NTSTATUS ReadIOCtrlBuffer( PIRP Irp,
PIO_STACK_LOCATION pIrpStack,
ULONG dwStatus );
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 :创建过滤设备将其附加到需要跟踪的设备上,保存设备相关
// 信息,返回附加后的驱动对象
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
AttachFilterDevice( IN UNICODE_STRING* DeviceName, // 需要跟踪的设备名
IN PDRIVER_OBJECT DriverObject, // 过滤驱动也就是本驱动的驱动对象
OUT PDRIVER_OBJECT* FilterDriverObject ) // 返回附加后的驱动对象
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT FilterDeviceObject;
PDEVICE_OBJECT TargetDevice;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DevExt;
NTSTATUS ntStatus;
//
// 根据设备名称找到需要附加的设备对象
//
ntStatus = IoGetDeviceObjectPointer( DeviceName,
FILE_ALL_ACCESS,
&FileObject,
&DeviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrint( "IoGetDeviceObjectPointer() %d\n", ntStatus );
return ntStatus;
}
//
// 创建过滤设备对象
//
ntStatus = IoCreateDevice( DriverObject,
sizeof( DEVICE_EXTENSION ),
NULL,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&FilterDeviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
ObDereferenceObject( FileObject );
DbgPrint( "IoCreateDevice() %d!\n", ntStatus );
return ntStatus;
}
//
// 得到设备扩展结构,以便下面保存过滤设备信息
//
DevExt = ( PDEVICE_EXTENSION ) FilterDeviceObject->DeviceExtension;
//
// 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象
//
TargetDevice = IoAttachDeviceToDeviceStack( FilterDeviceObject,
DeviceObject );
if ( !TargetDevice )
{
ObDereferenceObject( FileObject );
IoDeleteDevice( FilterDeviceObject );
DbgPrint( "IoAttachDeviceToDeviceStack() %d!\n", ntStatus );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 保存过滤设备信息
//
DevExt->DeviceObject = FilterDeviceObject;
DevExt->TargetDevice = TargetDevice;
DevExt->FileObject = FileObject;
//
// 设置过滤设备相关信息与标志
//
FilterDeviceObject->DeviceType = TargetDevice->DeviceType;
FilterDeviceObject->Characteristics = TargetDevice->Characteristics;
FilterDeviceObject->Flags |= ( TargetDevice->Flags & ( DO_DIRECT_IO |
DO_BUFFERED_IO ) );
//
// 返回附加后的驱动对象
//
*FilterDriverObject = TargetDevice->DriverObject;
ObDereferenceObject( FileObject );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 得到内核/用户模式 I/O 缓冲区数据,并返回当前数据所
// 在模式
// 注意 : 在 "过滤模块" 中此函数是为了配合 ReadIOCtrlBuffer
// 函数得到数据
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
GetSystemBuffer( PIRP Irp, PVOID pBuffer, SIZE_T Length, LONG* pMode )
{
PUCHAR pSysBuffer = NULL;
if ( pBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 判断当前 I/O 模式与数据存放的位置
//
switch ( Irp->RequestorMode )
{
case KernelMode:
*pMode = 0; // 内核模式 I/O
if ( Irp->UserBuffer )
{
pSysBuffer = Irp->UserBuffer;
}
else if ( Irp->MdlAddress )
{
pSysBuffer = ( PUCHAR )
MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
NormalPagePriority );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
break;
case UserMode:
*pMode = 1; // 用户模式 I/O
if ( Irp->UserBuffer )
{
pSysBuffer = Irp->UserBuffer;
}
else if ( Irp->MdlAddress )
{
pSysBuffer = ( PUCHAR )
MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
NormalPagePriority );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
break;
default:
break;
}
//
// 输出得到的缓冲区
//
RtlCopyMemory( pBuffer, pSysBuffer, Length );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 格式化缓冲区数据,并记录日志
// 注意 : 在 "过滤模块" 中此函数作用是格式化 GetSystemBuffer
函数得到的数据。因为此函数调用了日志函数,所以此函数
// 仅能在 IRQL == PASSVIE_LEVEL 级别运行。
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 : sinister
// 修改日期 : 2006.01.03
// 修改内容 : 在函数中增加了记录日志函数
/////////////////////////////////////////////////////////////////
NTSTATUS
FormatMessage( ULONG IoControl,
PUCHAR pBuf,
ULONG uSize,
ULONG dwStatus,
ULONG uMode )
{
ULONG uLen;
ULONG uCount = 0;
PVOID pBuffer = NULL;
UCHAR uTitle[100];
UCHAR uTemp[3];
if ( pBuf == NULL || uSize < 0 )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 低层驱动返回数据后,设置此标志
//
if ( dwStatus == OUT_BUFFER_FLAG )
{
if ( uMode == 0 )
{
sprintf( uTitle, "KERNEL MODE: IoControl=%x, OUTBUFFER:\n", IoControl );
}
else
{
sprintf( uTitle, "USER MODE: IoControl=%x, OUTBUFFER:\n", IoControl );
}
}
//
// 上层向低层驱动发送数据,设置此标志
//
else if ( dwStatus == IN_BUFFER_FLAG )
{
if ( uMode == 0 )
{
sprintf( uTitle, "KERNEL MODE: IoControl=%x, INBUFFER:\n", IoControl );
}
else
{
sprintf( uTitle, "USER MODE: IoControl=%x, INBUFFER:\n", IoControl );
}
}
//
// 记录日志,目的是记录分析,所以没有考虑效率。
//
WriteLog( uTitle, strlen( uTitle ) );
for ( uLen = 0; uLen < uSize; uLen++ )
{
sprintf( uTemp, "%.2X ", pBuf[uLen] );
WriteLog( uTemp, sizeof( uTemp ) );
if ( uLen % 16 == 0 )
{
WriteLog( "\n", 1 );
}
}
WriteLog( "\n", 1 );
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 得到 IRP_MJ_DEVICE_CONTROL 的 I/O 数据
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
ReadIOCtrlBuffer( PIRP Irp, PIO_STACK_LOCATION pIrpStack, ULONG dwStatus )
{
ULONG InBufLen;
ULONG OutBufLen;
ULONG IoControl;
PUCHAR pSysBuffer = NULL;
KEVENT KrnlEvent;
NTSTATUS ntStatus;
ULONG uMode;
//
// 得到设备控制字与 I/O 缓冲区长度
//
InBufLen = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutBufLen = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
IoControl = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
if ( dwStatus == OUT_BUFFER_FLAG )
{
//
// 如果是低层驱动返回的数据,缓冲区长度则要这样获得
//
OutBufLen = Irp->IoStatus.Information;
pSysBuffer = ( PUCHAR ) ExAllocatePool( PagedPool,
OutBufLen + sizeof( PUCHAR ) );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
ntStatus = GetSystemBuffer( Irp, pSysBuffer, OutBufLen, &uMode );
if ( !NT_SUCCESS( ntStatus ) )
{
ExFreePool( pSysBuffer );
return STATUS_INSUFFICIENT_RESOURCES;
}
FormatMessage( IoControl, pSysBuffer, OutBufLen, dwStatus, uMode );
}
else
{
pSysBuffer = ( PUCHAR ) ExAllocatePool( PagedPool,
InBufLen + sizeof( PUCHAR ) );
if ( pSysBuffer == NULL )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
ntStatus = GetSystemBuffer( Irp, pSysBuffer, InBufLen, &uMode );
if ( !NT_SUCCESS( ntStatus ) )
{
ExFreePool( pSysBuffer );
return STATUS_INSUFFICIENT_RESOURCES;
}
FormatMessage( IoControl, pSysBuffer, InBufLen, dwStatus, uMode );
}
if ( pSysBuffer )
{
ExFreePool( pSysBuffer );
}
return Irp->IoStatus.Status;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 替换指定设备的驱动例程使其指向当前过滤驱动的派遣例程
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
PDRIVER_OBJECT FilterDrvObj;
UNICODE_STRING DeviceName;
PDRIVER_DISPATCH EmptyDispatch;
NTSTATUS ntStatus;
ULONG iCount;
EmptyDispatch = DriverObject->MajorFunction[IRP_MJ_CREATE];
RtlInitUnicodeString( &DeviceName, L"\\Device\\FNT0" );
FilterDrvObj = NULL;
DriverObject->DriverUnload = DriverUnload;
ntStatus = AttachFilterDevice( &DeviceName, DriverObject, &FilterDrvObj );
if ( !NT_SUCCESS( ntStatus ) || FilterDrvObj == NULL )
{
DbgPrint( "Attach Device to failed!\n" );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 只过滤目标驱动对象使用的例程
//
for ( iCount = 0; iCount < IRP_MJ_MAXIMUM_FUNCTION; iCount++ )
{
if ( FilterDrvObj->MajorFunction[iCount] != EmptyDispatch &&
DriverObject->MajorFunction[iCount] == EmptyDispatch )
{
DriverObject->MajorFunction[iCount] = DispatchPassThrough;
}
}
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 删除并卸载过滤设备
// 注意 : 卸载列程中并没有做过多的处理,在过滤驱动中如果当前所
// 附加的设备IRP 很多的情况下,这样做可能会导致 BSOD
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
VOID
DriverUnload( IN PDRIVER_OBJECT DriverObject )
{
PDEVICE_OBJECT FilterDevice;
PDEVICE_OBJECT TargetDevice;
PDEVICE_EXTENSION DevExt;
NTSTATUS ntStatus;
FilterDevice = DriverObject->DeviceObject;
DevExt = ( PDEVICE_EXTENSION ) FilterDevice->DeviceExtension;
TargetDevice = DevExt->TargetDevice;
//
// 从目标断开附加设备,并删除过滤设备
//
IoDetachDevice( TargetDevice );
IoDeleteDevice( FilterDevice );
return;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 过滤驱动的派遣例程
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
DispatchPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PIO_STACK_LOCATION pIrpStack;
PDEVICE_OBJECT pDeviceObject;
PDEVICE_EXTENSION DevExtension = ( PDEVICE_EXTENSION )
DeviceObject->DeviceExtension;
NTSTATUS ntStatus;
KEVENT KrnlEvent;
pIrpStack = IoGetCurrentIrpStackLocation( Irp );
//
// 这里只过滤了 IRP_MJ_DEVICE_CONTROL 需要过滤更多的控制字可以
// 在这里增加判断
//
if ( pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
{
//
// 上层发送数据,设置 IN_BUFFER_FLAG 标志记录。
//
ReadIOCtrlBuffer( Irp, pIrpStack, IN_BUFFER_FLAG );
//
// 因为是上层过滤驱动,所以必须向低层驱动请求返回数据
// 这里虽然没有对数据进行修改,但为了以后扩充方便
// 还是复制了 IRP 堆栈和安装完成列程
//
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, CompletionRoutine, NULL, TRUE, TRUE, TRUE );
( void ) IoCallDriver( DevExtension->TargetDevice, Irp );
//
// 当低层驱动返回数据后,设置 OUT_BUFFER_FLAG 标志,再次记录。
//
ntStatus = ReadIOCtrlBuffer( Irp, pIrpStack, OUT_BUFFER_FLAG );
return ntStatus;
}
//
// 对于其他控制字则直接传递到低层驱动,无须安装完成列程
//
else
{
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( DevExtension->TargetDevice, Irp );
}
}
/////////////////////////////////////////////////////////////////
// 函数类型 :系统回调函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 :
// 注意 : 这里没有对返回数据做操作
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
CompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
if ( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 : 过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 记录日志到 C 盘的 WSSFILTER.LOG 中
// 注意 : 只能在 IRQL == PASSVIE_LEVEL 级别使用
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重 大 修 改 历 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////
NTSTATUS
WriteLog( PVOID lpBuffer, ULONG uSize )
{
NTSTATUS status;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_POSITION_INFORMATION FilePOTInfo;
FILE_STANDARD_INFORMATION FileSTDInfo;
ANSI_STRING ansiString;
UNICODE_STRING filenameString;
HANDLE hFile;
WCHAR LogFile[] = L"\\??\\C:\\WSSFILTER.LOG";
RtlInitUnicodeString( &filenameString, LogFile );
InitializeObjectAttributes( &ObjectAttributes,
&filenameString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile( &hFile,
GENERIC_WRITE | SYNCHRONIZE | GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if ( !NT_SUCCESS( status ) )
{
return status;
}
ZwQueryInformationFile( hFile,
&IoStatusBlock,
( void * ) &FileSTDInfo,
sizeof( FileSTDInfo ),
FileStandardInformation );
if ( !NT_SUCCESS( IoStatusBlock.Status ) )
{
return IoStatusBlock.Status;
}
FilePOTInfo.CurrentByteOffset = FileSTDInfo.EndOfFile;
ZwSetInformationFile( hFile,
&IoStatusBlock,
( void * ) &FilePOTInfo,
sizeof( FilePOTInfo ),
FilePositionInformation );
if ( !NT_SUCCESS( IoStatusBlock.Status ) )
{
return IoStatusBlock.Status;
}
ZwWriteFile( hFile, 0, 0, 0, &IoStatusBlock, lpBuffer, uSize, NULL, NULL );
ZwClose( hFile );
return IoStatusBlock.Status;
}
WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/