您的位置:首页 > 编程语言

编写驱动拦截NT的API实现隐藏文件目录(代码)

2013-08-08 14:14 573 查看
转载地址:http://www.cnblogs.com/qiuyi21/articles/1151923.html

 

pudn上的这个源代码可以使用:http://www.pudn.com/downloads79/sourcecode/windows/vxd/detail305108.html

驱动已经使用WDK编译好了,直接安装就可以,安装好后,用VS2010,或者VS2008编译Test项目,就可以隐藏文件了,不需要改动,代码也很规范,可以好好学习。

 

网上流传的一篇文章《编写驱动拦截NT的API实现隐藏文件目录》,当时我在网上搜索内核级Hook资料时搜索到的,因为自己对驱动程序还是初初接触,所有想按照这篇文章自己弄个简单的驱动出来,测试测试~~~但由于网上流传的这篇文章都丢失了原作者和原出处,有些代码似乎是错的,但自己又不熟悉,难免弄错。参考了其它使用驱动程序Hook的例子(都是Windows 2000 DDK的),最终编译了一个驱动出来,马上安装进自己的系统里(Windows XP Professional SP2),执行[net start "驱动名"],噢,系统立即蓝屏挂掉了!!经过一段时间的驱动程序编写研究,终于写成功拦截NT的API实现隐藏文件目录了,也知道了一点就是Windows
XP之后的操作系统的SSDT都已经写保护,Hook SSDT时不可以直接改写SSDT。我的代码如下,由于水平有限,难免会有错误,请多多指教。

 

C 语言代码,用WDK编译

 

#include <ntddk.h>

#define FILE_DEVICE_NTHIDEFILES    0x8000
#define NTHIDEFILES_IOCTL_BASE    0x800

#define CTL_CODE_NTHIDEFILES(i) CTL_CODE(FILE_DEVICE_NTHIDEFILES, NTHIDEFILES_IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_NTHIDEFILES_HELLO    CTL_CODE_NTHIDEFILES(0)

#define NTHIDEFILES_DEVICE_NAME     L"\\Device\\NtHideFiles"
#define NTHIDEFILES_DOS_DEVICE_NAME L"\\DosDevices\\NtHideFiles"

#define dprintf if (DBG) DbgPrint
#define nprintf DbgPrint

typedef struct _DEVICE_EXTENSION
{
ULONG StateVariable;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef struct _FILE_BOTH_DIR_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
WCHAR ShortName[12];
WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;

#pragma pack(1)
typedef struct _SERVICE_DESCRIPTOR_ENTRY
{
unsigned int * ServiceTableBase;
unsigned int * ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char * ParamTableBase;
} SERVICE_DESCRIPTOR_ENTRY, *PSERVICE_DESCRIPTOR_ENTRY;
#pragma pack()

// ZwQueryDirectoryFile 的原型
typedef NTSTATUS (NTAPI *PFN_ZwQueryDirectoryFile)(
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);

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryDirectoryFile(
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 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);

__declspec(dllimport) SERVICE_DESCRIPTOR_ENTRY KeServiceDescriptorTable;

// 保存原 ZwQueryDirectoryFile 函数指针
PFN_ZwQueryDirectoryFile OriginalZwQueryDirectoryFile = NULL;

PMDL g_pmdlSystemCall = NULL;
PVOID *MappedSystemCallTable = NULL;
BOOLEAN g_bHooked = FALSE;

#define SYSCALL_INDEX(_Function)              *(PULONG)((PUCHAR)_Function + 1)
#define SYSTEMSERVICE(_Function)              KeServiceDescriptorTable.ServiceTableBase[SYSCALL_INDEX(_Function)]
#define HOOK_SYSCALL(_Function, _Hook, _Orig) _Orig = (PVOID)InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG)_Hook)
#define UNHOOK_SYSCALL(_Function, _Orig)      InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG)_Orig)

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
PCWSTR GetProcessFullName();

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DispatchCreate)
#pragma alloc_text(PAGE, DispatchClose)
#pragma alloc_text(PAGE, DispatchDeviceControl)
#pragma alloc_text(PAGE, DriverUnload)
#endif // ALLOC_PRAGMA

#define BASE_PROCESS_PEB_OFFSET                   0x1B0
#define BASE_PEB_PROCESS_PARAMETER_OFFSET         0x010
#define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME    0x03C
#define W2003_BASE_PROCESS_PEB_OFFSET             0x190
#define W2003_BASE_PROCESS_PEB_OFFSET_SP1         0x1A0
#define W2003_BASE_PROCESS_PEB_OFFSET_SP2         W2003_BASE_PROCESS_PEB_OFFSET_SP1
#define VISTA_BASE_PROCESS_PEB_OFFSET             0x188

PCWSTR GetProcessFullName()
{
NTSTATUS status    = -1;
ULONG    dwAddress = 0;
PCWSTR   lpszTemp  = NULL;
RTL_OSVERSIONINFOEXW osVerInfo;

dwAddress = (ULONG)PsGetCurrentProcess();
if (dwAddress == 0 || dwAddress == (ULONG)-1)
return NULL;

RtlZeroMemory(&osVerInfo, sizeof(RTL_OSVERSIONINFOEXW));
osVerInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);

status = RtlGetVersion((PRTL_OSVERSIONINFOW)&osVerInfo);
if (!NT_SUCCESS(status))
return NULL;

// 目前只支持 Windows 2000/XP/2003/Vista
if (osVerInfo.dwMajorVersion < 5 || osVerInfo.dwMinorVersion > 2)
return NULL;

// 取得PEB,不同平台的位置是不同的
if (osVerInfo.dwMajorVersion == 5)
{
if (osVerInfo.dwMinorVersion < 2)    // 2000   0X0500       XP 0X0501
{
dwAddress += BASE_PROCESS_PEB_OFFSET;
}
else if (osVerInfo.dwMinorVersion == 2)    // 2003   0X0502
{
if (osVerInfo.wServicePackMajor == 0)    // No Service Pack
dwAddress += W2003_BASE_PROCESS_PEB_OFFSET;
else if (osVerInfo.wServicePackMajor < 3)    // Service Pack 1 & 2
dwAddress += W2003_BASE_PROCESS_PEB_OFFSET_SP1;
}
}
else    // Vista   0X0600
{
dwAddress += VISTA_BASE_PROCESS_PEB_OFFSET;
}

if ((dwAddress = *(PULONG)dwAddress) == 0)
return NULL;

// 通过PEB取得RTL_USER_PROCESS_PARAMETERS
dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET;
if ((dwAddress = *(PULONG)dwAddress) == 0)
return NULL;

// 在RTL_USER_PROCESS_PARAMETERS->ImagePathName保存了路径,偏移为0x038
dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME;
if ((dwAddress = *(PULONG)dwAddress) == 0)
return NULL;

// [10/14/2006]
lpszTemp = (PCWSTR)dwAddress;
if (wcslen(lpszTemp) > 4)
{
if (lpszTemp[0] == L'\\' &&
(lpszTemp[1] == L'?' || lpszTemp[1] == L'\\') &&
lpszTemp[2] == L'?' &&
lpszTemp[3] == L'\\')
{
dwAddress += 4 * sizeof(WCHAR);
}
}

return (PCWSTR)dwAddress;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS       status = STATUS_SUCCESS;
UNICODE_STRING ntDeviceName;
UNICODE_STRING dosDeviceName;
PDEVICE_OBJECT deviceObject = NULL;
BOOLEAN        fSymbolicLink = FALSE;

dprintf("[NtHideFiles] DriverEntry: %wZ\n", RegistryPath);

RtlInitUnicodeString(&ntDeviceName, NTHIDEFILES_DEVICE_NAME);

status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),    // DeviceExtensionSize
&ntDeviceName,                // DeviceName
FILE_DEVICE_NTHIDEFILES,    // DeviceType
0,                            // DeviceCharacteristics
TRUE,                        // Exclusive
&deviceObject                // [OUT]
);

if (!NT_SUCCESS(status))
goto __failed;

RtlInitUnicodeString(&dosDeviceName, NTHIDEFILES_DOS_DEVICE_NAME);

status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);

if (!NT_SUCCESS(status))
goto __failed;

fSymbolicLink = TRUE;

DriverObject->MajorFunction[IRP_MJ_CREATE]         = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE]          = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload                         = DriverUnload;

// Map the memory into our domain to change the permissions on the MDL
g_pmdlSystemCall = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase,
KeServiceDescriptorTable.NumberOfServices * 4,
FALSE, FALSE, NULL);

if (g_pmdlSystemCall == NULL)
{
status = STATUS_UNSUCCESSFUL;
goto __failed;
}

MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
// Change the flags of the MDL
g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);

// HOOK ZwQueryDirectoryFile 并保存原 ZwQueryDirectoryFile 函数地址
HOOK_SYSCALL(ZwQueryDirectoryFile, HookZwQueryDirectoryFile, OriginalZwQueryDirectoryFile);
g_bHooked = TRUE;

if (NT_SUCCESS(status))
return status;

__failed:

if (fSymbolicLink)
IoDeleteSymbolicLink(&dosDeviceName);

if (deviceObject)
IoDeleteDevice(deviceObject);

return status;
}

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

Irp->IoStatus.Information = 0;

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

return status;
}

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

Irp->IoStatus.Information = 0;

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

return status;
}

NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS           status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
PVOID              ioBuf;
ULONG              inBufLength, outBufLength;
ULONG              ioControlCode;

irpStack = IoGetCurrentIrpStackLocation(Irp);

Irp->IoStatus.Information = 0;

//
// Get the pointer to the input/output buffer and it's length
//

ioBuf = Irp->AssociatedIrp.SystemBuffer;
inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

switch (ioControlCode)
{
case IOCTL_NTHIDEFILES_HELLO:
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}

//
// DON'T get cute and try to use the status field of
// the irp in the return status.  That IRP IS GONE as
// soon as you call IoCompleteRequest.
//

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

//
// We never have pending operation so always return the status code.
//

return status;
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING dosDeviceName;

// UnHook ZwQueryDirectoryFile
if (g_bHooked && OriginalZwQueryDirectoryFile != NULL)
UNHOOK_SYSCALL(ZwQueryDirectoryFile, OriginalZwQueryDirectoryFile);

if (g_pmdlSystemCall != NULL)
{
MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
IoFreeMdl(g_pmdlSystemCall);
}

//
// Delete the symbolic link
//

RtlInitUnicodeString(&dosDeviceName, NTHIDEFILES_DOS_DEVICE_NAME);

IoDeleteSymbolicLink(&dosDeviceName);

//
// Delete the device object
//

IoDeleteDevice(DriverObject->DeviceObject);

dprintf("[NtHideFiles] unloaded\n");
}

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 = STATUS_SUCCESS;
ANSI_STRING ansiFileName, ansiDirName, HideDirFile;
UNICODE_STRING uniFileName;
PCWSTR pProcPath = NULL;

// 初始化要过虑的文件名,大写形式
RtlInitAnsiString(&HideDirFile, "WAR3.EXE");

pProcPath = GetProcessFullName();
DbgPrint("[NtHideFiles] GetProcessFullName: %ws\n", pProcPath == NULL ? L"<null>" : pProcPath);

// 执行真正的 ZwQueryDirectoryFile 函数
rc = OriginalZwQueryDirectoryFile(
hFile,
hEvent,
IoApcRoutine,
IoApcContext,
pIoStatusBlock,
FileInformationBuffer,
FileInformationBufferLength,
FileInfoClass,
bReturnOnlyOneEntry,
PathMask,
bRestartQuery);

// 如果执行成功,而且 FILE_INFORMATION_CLASS 的值为 FileBothDirectoryInformation,我们就进行处理,过滤
if (NT_SUCCESS(rc) && FileInfoClass == FileBothDirectoryInformation)
{
// 把执行结果赋给 pFileInfo
PFILE_BOTH_DIR_INFORMATION pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer;
PFILE_BOTH_DIR_INFORMATION pLastFileInfo = NULL;
BOOLEAN bLastOne = FALSE;

// 循环检查
do
{
bLastOne = !pFileInfo->NextEntryOffset;
RtlInitUnicodeString(&uniFileName, pFileInfo->FileName);
RtlUnicodeStringToAnsiString(&ansiFileName, &uniFileName, TRUE);
RtlUnicodeStringToAnsiString(&ansiDirName, &uniFileName, TRUE);
RtlUpperString(&ansiFileName, &ansiDirName);

// 打印结果,用 debugview 可以查看打印结果
//dprintf("ansiFileName :%s\n", ansiFileName.Buffer);
//dprintf("HideDirFile :%s\n", HideDirFile.Buffer);

// 开始进行比较,如果找到了就隐藏这个文件或者目录
if (RtlCompareMemory(ansiFileName.Buffer, HideDirFile.Buffer, HideDirFile.Length) == HideDirFile.Length)
{
dprintf("This is HideDirFile!\n");

if (bLastOne)
{
if (pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)
rc = STATUS_NO_MORE_FILES;    // 隐藏文件或者目录;
else
pLastFileInfo->NextEntryOffset = 0;

break;
}
else    // 指针往后移动
{
int iPos = (ULONG)pFileInfo - (ULONG)FileInformationBuffer;
int iLeft = (ULONG)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;
RtlCopyMemory((PVOID)pFileInfo, (PVOID)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset), (ULONG)iLeft);
continue;
}
}

pLastFileInfo = pFileInfo;
pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset);
} while (!bLastOne);

RtlFreeAnsiString(&ansiDirName);
RtlFreeAnsiString(&ansiFileName);
}

return rc;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐