内核层的两个??其实是符号链接.代表的是是
\device\harddiskvolume3
内核中的文件路径完整表达是: L"\device\harddiskvolume3\HelloWorld.txt
Ring3跟Ring0的其它路径.如设备对象.(符号链接)
ZwSetInfomationFile 设置文件信息,设置文件大小,设置文件访问日期.设置属性隐藏文件.重命名.删除.对应IRP = Irp_mj_Set_Information. ZwClose 关闭文件句柄 ZwQueryDirectoryFile 枚举文件跟目录如ZwCreateFile
NTSTATUS
ZwCreateFile(
__out PHANDLE FileHandle, 文件句柄
__in ACCESS_MASK DesiredAccess, 创建权限
__in POBJECT_ATTRIBUTES ObjectAttributes,文件路径.这里放文件了解那个
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_opt PLARGE_INTEGER AllocationSize,
__in ULONG FileAttributes,
__in ULONG ShareAccess, 文件是创建还是打开
__in ULONG CreateDisposition,
__in ULONG CreateOptions,
__in_opt PVOID EaBuffer,
__in ULONG EaLength
NTSTATUS
ZwReadFile(
IN HANDLE FileHandle, 文件句柄
IN HANDLE Event OPTIONAL, 异步过程调用
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,异步过程
IN PVOID ApcContext OPTIONAL, 异步过程调用
OUT PIO_STATUS_BLOCK IoStatusBlock, 读写的IO状态
OUT PVOID Buffer, 读写的Buffer
IN ULONG Length, 读写的长度
IN PLARGE_INTEGER ByteOffset OPTIONAL, 读写的偏移
IN PULONG Key OPTIONAL
查询文件类型
NTSTATUS
ZwQueryInformationFile(
IN HANDLE FileHandle, 文件句柄
OUT PIO_STATUS_BLOCK IoStatusBlock, IO状态
OUT PVOID FileInformation, 根据参数四.传出的一个结构体乐行
IN ULONG Length, 查询文件类型的长度
IN FILE_INFORMATION_CLASS FileInformationClass 查询的文件的类型, 你查询的信息是个结构体.这里放什么上面就放这个信息结构体的大小.
上面这个函数简单来说就是 你参数4传入一个枚举类型.表示你想查询什么类型信息. 然后查询的信息通过参数3. FileInformation传出. 你参数4传入的是什么枚举.他就会返回查询的结构体给参数三.
ZwQueryInfomationFile(hfile,&Iostatus,&FileInformatin,sizeof(FileInforMation),FileBaseicInfoMation
具体信息查询WDK帮助文档即可.
设置文件信息
NTSTATUS
ZwSetInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass 文件的类型
跟查询文件相反.只不过需要我们传入信息.
比如: 下面就是删除文件
FILE_DISPOSITION_INFORMATION FileInformation;
ZwSetInformationFile(hfile,&ioStatus,&FileInformation,sizeof(FileInformation),FileDispositionInformation);
三丶内核中三种定义结构体的方式
为什么说这个.因为在上面文件操作.如果你查询Wdk文档的话.会看到不同的结构体定义.
typedef struct _FILE_RENAME_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
更改名字的结构体.
可以看到第三个参数 跟第四个参数. 为什么这样定义.
这样定义代表这个结构体利用数组可以溢出的原理.设计的一个边长结构体.
他这个数组的大小根据第三个参数决定.
其余的两种就很简单了
struct stack
int value
char szBuffer[100]
这种类型.我们的szBuffer就是占你给定的大小.
struct point
int value
char *pszBuffer
这种类型则是指针定义.pszBuffer指向一块地址.
3.1 驱动创建文件的完整代码示例
3.1.1 内核中创建一个文件
#include <ntddk.h>
#include <wdm.h>
#include <ntdef.h>
#include <ntstrsafe.h>
#define DEVICENAME L""
#define SYMBOLICLINKENAME L""
DRIVER_UNLOAD DriverUnload; //函数声明
NTSTATUS NtDeleteFile(const WCHAR *FileNmae);//删除文件的第一种方式.
NTSTATUS NtCreateFile(UNICODE_STRING ustr);
NTSTATUS NtCreateFile(UNICODE_STRING ustr)
//创建文件
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
NTSTATUS NtStatus = 0;
HANDLE hFile;
IO_STATUS_BLOCK io_Status = { 0 };
OBJECT_ATTRIBUTES ObjAttus = { 0 };
InitializeObjectAttributes(&ObjAttus, //初始化ObjAttus结构.
&ustr,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
NtStatus = ZwCreateFile(&hFile,
GENERIC_WRITE,
&ObjAttus,
&io_Status,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE,
NULL,
if (NT_SUCCESS(NtStatus))
//创建成功了
ZwClose(hFile);
return NtStatus;
void DriverUnload(DRIVER_OBJECT *DriverObject)
UNICODE_STRING ustr;
UNICODE_STRING uPathName = { 0 };
NTSTATUS NtStatus;
PdriverObject->DriverUnload = DriverUnload;
RtlUnicodeStringInit(&uPrintString, L"启动驱动安装");
DbgPrint("%wZ", &uPrintString);
RtlUnicodeStringInit(&uPathName, L"\\??\\c:\\1.txt");//初始化字符串路径
NtStatus = NtCreateFile(uPathName);
if (NT_SUCCESS(NtStatus))
DbgPrint("创建文件成功");
return STATUS_UNSUCCESSFUL;
创建完毕截图:
下面只提供核心接口代码.直接添加到DLL DriverEntry中即可.
3.1.2 内核中创建文件目录
传参的uPathName = L"\\??\\c:\\IBinary\\"
NTSTATUS IBinaryNtCreateDirectory(UNICODE_STRING uPathName)
NTSTATUS ntStatus;
HANDLE hFile;
OBJECT_ATTRIBUTES objAttus = { 0 };
IO_STATUS_BLOCK ioStatus = { 0 };
//初始化文件属性结构体
InitializeObjectAttributes(&objAttus,
&uPathName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
ntStatus = ZwCreateFile(&hFile,
GENERIC_READ | GENERIC_WRITE,
&objAttus,
&ioStatus,
NULL,
FILE_ATTRIBUTE_DIRECTORY, //注意这个属性.我们设置创建文件
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, //表示创建的是目录,并且是同步执行
NULL,
if (NT_SUCCESS(ntStatus))
ZwClose(hFile);
return ntStatus;
3.1.3内核中写文件
原理: 使用ZwCreateFile打开文件.获取文件句柄.然后使用ZwWriteFile写文件即可.
uPathName = "\\??\\C:\\1.txt"
NTSTATUS IBinaryNtWriteFile(UNICODE_STRING uPathName)
//首先打开文件,然后写入文件.
OBJECT_ATTRIBUTES objAttri = { 0 };
NTSTATUS ntStatus;
HANDLE hFile;
IO_STATUS_BLOCK ioStatus = { 0 };
PVOID pWriteBuffer = NULL;
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,//注意此标志,打开文件文件不存在则失败.
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
if (!NT_SUCCESS(ntStatus))
return ntStatus;
//开始写文件
pWriteBuffer = ExAllocatePoolWithTag(PagedPool, 0x20, "niBI");
if (pWriteBuffer == NULL)
DbgPrint("写文件分配内存出错");
ZwClose(hFile);
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(pWriteBuffer, 0x20);
RtlCopyMemory(pWriteBuffer, L"HelloIBinary", wcslen(L"HelloIBinary"));
ntStatus = ZwWriteFile(hFile,
NULL,
NULL,
NULL,
&ioStatus,
pWriteBuffer,
0x20,
NULL,
NULL);
if (!NT_SUCCESS(ntStatus))
ZwClose(hFile);
return STATUS_INSUFFICIENT_RESOURCES;
ZwClose(hFile);
ExFreePoolWithTag(pWriteBuffer, "niBI");
return ntStatus;
在拷贝字符串的时候我拷贝的是宽字符.所以显示如上图.在我们读文件之前.我稍微修改一下.这里就不在贴出代码了.
3.2 内核中读文件
内核中读写文件其实是一样的.打开一个文件.读取数据即可.
代码如下:
uPathName = L"\\??\\c:\\1.txt
传入了缓冲区.只需要往缓冲区中读取数据即可.
NTSTATUS IBinaryNtReadFile(PVOID pszBuffer, UNICODE_STRING uPathName)
OBJECT_ATTRIBUTES objAttri = { 0 };
NTSTATUS ntStaus;
HANDLE hFile;
IO_STATUS_BLOCK ioStatus = { 0 };
PVOID pReadBuffer = NULL;
if (NULL == pszBuffer)
return STATUS_INTEGER_DIVIDE_BY_ZERO;
//打开文件读取文件.
InitializeObjectAttributes(&objAttri,
&uPathName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
ntStaus = ZwCreateFile(&hFile,
GENERIC_READ | GENERIC_WRITE,
&objAttri,
&ioStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
NULL);
if (!NT_SUCCESS(ntStaus))
ZwClose(hFile);
if (NULL != pReadBuffer)
ExFreePoolWithTag(pReadBuffer, "niBI");
return STATUS_INTEGER_DIVIDE_BY_ZERO;
//读取文件
pReadBuffer = ExAllocatePoolWithTag(PagedPool, 100, "niBI");
if (NULL == pReadBuffer)
return STATUS_INTEGER_DIVIDE_BY_ZERO;
ntStaus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, pReadBuffer, 100, NULL, NULL);
if (!NT_SUCCESS(ntStaus))
ZwClose(hFile);
if (NULL != pReadBuffer)
ExFreePoolWithTag(pReadBuffer, "niBI");
return STATUS_INTEGER_DIVIDE_BY_ZERO;
//将读取的内容拷贝到传入的缓冲区.
RtlCopyMemory(pszBuffer, pReadBuffer, 100);
ZwClose(hFile);
if (NULL != pReadBuffer)
ExFreePoolWithTag(pReadBuffer, "niBI");
return ntStaus;
3.3 内核中删除文件的两种方式(常规)
内核中可以删除文件.有两种方式.第一种调用 ZwDeleteFile.
3.3.1 内核中删除文件第一种方式
uDeletePathName = L"\\??\\c:\\1.txt"
#include <ntddk.h>
#include <wdm.h>
#include <ntdef.h>
#include <ntstrsafe.h>
NTSTATUS ZwDeleteFile( IN POBJECT_ATTRIBUTES ObjectAttributes); //函数声明
NTSTATUS IBinaryNtZwDeleteFile(UNICODE_STRING uDeletePathName)
OBJECT_ATTRIBUTES obAttri = { 0 };
//初始化源文件路径并且打开
InitializeObjectAttributes(&obAttri,
&uDeletePathName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
return ZwDeleteFile(&obAttri);
这种方式删除文件.但是可能删除失败.比如文件被独占打开等等.我没有进行尝试.在虚拟机中我就算 打开 1.txt这个文件.当我要删除这个文件的时候一样删除成功.
3.3.2 内核中第二种删除文件方式
这种删除方式更加厉害. 比如上面我们说的文件可能因为各种因素删除失败.所以采用这种方法. 这种方法是使用 内核中的 ZwSetInformationFile设置文件信息从而进行删除的.
代码如下:
NTSTATUS IBinaryNtSetInformationFileDeleteFile(UNICODE_STRING uDeletePathName)
//删除文件的第二种方式
1.初始化文件路径
2.使用读写方式打开文件. 以共享模式打开.
3.如果是拒绝,则以另一种方式打开文件.并且设置这个文件的信息.
4.设置成功之后就可以删除了.
OBJECT_ATTRIBUTES objAttri;
NTSTATUS ntStatus;
HANDLE hFile;
IO_STATUS_BLOCK ioStatus;
FILE_DISPOSITION_INFORMATION IBdelPostion = { 0 }; //通过ZwSetInformationFile删除.需要这个结构体
__try
InitializeObjectAttributes(&objAttri,
&uDeletePathName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
ntStatus = ZwCreateFile(&hFile,
DELETE | FILE_WRITE_DATA | SYNCHRONIZE, //注意权限,以删除权限.写权限.
&objAttri,
&ioStatus,
NULL,
FILE_ATTRIBUTE_NORMAL, //文件的属性是默认
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,//文件的共享模式 删除 读写
FILE_OPEN, //文件的打开方式是 打开.如果不存在则返回失败.
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, //文件的应用选项,如果是FILE_DELETE_ON_CLOSE则使用ZwClose关闭文件句柄的时候删除这个文件
NULL,
if (!NT_SUCCESS(ntStatus))
//如果不成功,判断文件是否拒绝访问.是的话我们就设置为可以访问.并且进行删除.
if (STATUS_ACCESS_DENIED == ntStatus)
ntStatus = ZwCreateFile(&hFile,
SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,//删除权限失败就以读写模式
&objAttri,
&ioStatus,
NULL,
FILE_ATTRIBUTE_NORMAL, //文件的属性为默认
FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ,//文件的共享属性为 读写删除
FILE_OPEN, //文件的打开方式为 打开,不存在则失败
FILE_SYNCHRONOUS_IO_NONALERT, //文件的应用选项.
NULL,
//如果打开成功了.则设置这个文件的信息
if (NT_SUCCESS(ntStatus))
FILE_BASIC_INFORMATION IBFileBasic = { 0 };//
使用ZwQueryInformationfile遍历文件的信息.这里遍历的是文件的基本信息
ntStatus = ZwQueryInformationFile(
hFile,
&ioStatus,
&IBFileBasic,
sizeof(IBFileBasic),
FileBasicInformation
//遍历失败.输出打印信息
if (!NT_SUCCESS(ntStatus))
DbgPrint("删除文件失败,遍历文件信息出错 文件名= %wZ", &uDeletePathName);
//设置文件的基本信息
IBFileBasic.FileAttributes = FILE_ATTRIBUTE_NORMAL; //设置属性为默认属性
ntStatus = ZwSetInformationFile(
hFile,
&ioStatus,
&IBFileBasic,
sizeof(IBFileBasic),
FileBasicInformation); //将我的FileBasic基本属性设置到这个文件中
if (!NT_SUCCESS(ntStatus))
DbgPrint("删除文件失败,设置文件信息出错");
//如果成功关闭文件句柄.
ZwClose(hFile);
//重新打开这个设置信息后的文件.
ntStatus = ZwCreateFile(&hFile,
SYNCHRONIZE | FILE_WRITE_DATA | DELETE,
&objAttri,
&ioStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE,
NULL,
if (!NT_SUCCESS(ntStatus))
DbgPrint("打开文件失败,删除失败");
//进行强制删除文件 通过 ZwSetInformationFile
IBdelPostion.DeleteFile = TRUE; //此标志设置为TRUE即可删除
ntStatus = ZwSetInformationFile(hFile, &ioStatus, &IBdelPostion, sizeof(IBdelPostion), FileDispositionInformation);
if (!NT_SUCCESS(ntStatus))
ZwClose(hFile);
DbgPrint("删除文件失败,设置文件信息出错");
return ntStatus;
ZwClose(hFile);
__except (1)
DbgPrint("删除文件出现异常");
return ntStatus;
3.3.3 强删文件的实现,包括驱动加载后强制删除驱动。
链接参考另一篇:x64内核强删文件. - iBinary - 博客园
四丶 文件属性的设置与查询
4.1 ZwSetInformationFile 使用
ZwSetInformationFile 可以设置文件属性。
其中主要是第五个参数,需要你指定信息。 根据第五个参数指定的信息 来决定你第三个参数所需要的结构体是那种
基本的文件属性示例如下:
FILE_POSITION_INFORMATION poffset; //设置文件指针 相当于是c语言的fseek()
poffset.CurrentByteOffset.QuadPart = 100;
ntStatus = ZwSetInformationFile(hFile, &iosa, &poffset, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
if (!NT_SUCCESS(ntStatus))
goto RELEASE;
FILE_BASIC_INFORMATION fbi = {0}; //设置文件基础信息。设置为只读。
fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY;
ntStatus = ZwSetInformationFile(hFile, &iosa, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
if (!NT_SUCCESS(ntStatus))
goto RELEASE;
五丶FileObject中的路径转换与操作
通过Zw函数打开或者创建文件之后会返回句柄,有了句柄则可以通过 ObReferenceObjectByHandle来获取文件对象指针了
也就是获取FILE_OBJECT 通过FILE_OBJECT可以互相转换路径。
首先介绍一下路径的概念。 路径分为DOS路径与NT路径。
DOS路径: Dos路径则是我们常常看到的
C:\xxxx\xxxx路径
NT路径: Nt 路径则是我们系统中的常见的路径 例如:
L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\test.dat"
与之等价的则是
"\Device\HarddiskVolume4\Users\ibinary\Desktop\11\test.dat"
介绍两个函数
ObQueryNameString
通过Object查找名字
使用方式如下:
获取FileObject
ntStatus = ObReferenceObjectByHandle(hFile,
GENERIC_READ | GENERIC_WRITE,
*IoFileObjectType,
KernelMode,
(PVOID *)&pFileObject,
NULL);
if (!NT_SUCCESS(ntStatus))
goto RELEASE;
POBJECT_NAME_INFORMATION pObjBuffer = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, 1024, 'abcd');
if (pObjBuffer == NULL)
goto RELEASE;
RtlZeroMemory(pObjBuffer, 1024);
ntStatus = ObQueryNameString(pFileObject, pObjBuffer, 1024, &uRetLength);
if (!NT_SUCCESS(ntStatus))
goto RELEASE;
查询出来 pObjBuffer 值为:
"\Device\HarddiskVolume4\Users\ibinary\Desktop\11\test.dat"
ObQueryNameString 可以进行两次调用。第一次调用 Buffer以及Buffer大小都传递为NULL。 然后他会在uRetLength给返回你需要的大小
然后再次调用的时候你在根据uRetLength申请空间即可。
NT路径转Dos路径
RtlZeroMemory(pObjBuffer, 1024);
// IoVolumeDeviceToDosName()
IoQueryFileDosDeviceName(pFileObject, &pObjBuffer);
pObjBuffer = "C:\Users\ibinary\Desktop\11\test.dat"
六丶文件常用API封装
6.1 封装CopyFile
windows内核并没有为我们提供CopyFIle的功能.或者MoveFile的功能.所以需要我们自己去实现. 原理也很简单.使用 ZwReadFile和ZwWriteFile
来实现
代码如下:
// copy srcFile to DestFile
NTSTATUS ZwCopyFileW(PWCHAR pDestFileName, PWCHAR pSrcFileName)
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING ustrSrcFileName = {0};
UNICODE_STRING ustrDestFileName = {0};
HANDLE hSrcFileHandle = NULL;
HANDLE hDstFileHandle = NULL;
OBJECT_ATTRIBUTES objSrcAttr = {0};
OBJECT_ATTRIBUTES objDstAttr = {0};
IO_STATUS_BLOCK iosta = {0};
LARGE_INTEGER ullOffset = {0};
PCHAR pTempBuffer = NULL;
const ULONG BUFFER_SIZE = 0x1000;
ULONG uReadLength = 0;
if (pDestFileName == NULL || pSrcFileName == NULL)
status = STATUS_INVALID_PARAMETER;
goto END;
// open src and dest get handle
status = RtlUnicodeStringInit(&ustrSrcFileName, pSrcFileName);
if (NT_ERROR(status))
goto END;
status = RtlUnicodeStringInit(&ustrDestFileName, pDestFileName);
if (NT_ERROR(status))
goto END;
InitializeObjectAttributes(&objSrcAttr, &ustrSrcFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
InitializeObjectAttributes(&objDstAttr, &ustrDestFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
// open src
status = ZwCreateFile(
&hSrcFileHandle,
GENERIC_READ,
&objSrcAttr,
&iosta,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
if (NT_ERROR(status))
goto END;
// open dest
status = ZwCreateFile(
&hDstFileHandle,
GENERIC_WRITE,
&objDstAttr,
&iosta,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
if (NT_ERROR(status))
goto END;
// while readFile and write buffer to dstFile
pTempBuffer = (PCHAR)ExAllocatePool(NonPagedPool, BUFFER_SIZE);
while (TRUE)
if (pTempBuffer == NULL)
goto END;
RtlZeroMemory(pTempBuffer, BUFFER_SIZE);
status = ZwReadFile(
hSrcFileHandle,
NULL,
NULL,
NULL,
&iosta,
pTempBuffer,
BUFFER_SIZE,
&ullOffset, // out filepointer offset
NULL);
if (!NT_SUCCESS(status))
if (status == STATUS_END_OF_FILE)
status = STATUS_SUCCESS;
goto END;
goto END;
uReadLength = iosta.Information;
status = ZwWriteFile(
hDstFileHandle,
NULL,
NULL,
NULL,
&iosta,
pTempBuffer,
uReadLength,
&ullOffset,
NULL);
if (NT_ERROR(status))
goto END;
// mov filepointer
ullOffset.QuadPart += uReadLength;
status = STATUS_SUCCESS;
if (pTempBuffer != NULL)
ExFreePool(pTempBuffer);
pTempBuffer = NULL;
if (hDstFileHandle != NULL)
ZwClose(hDstFileHandle);
hDstFileHandle = NULL;
if (hSrcFileHandle != NULL)
ZwClose(hSrcFileHandle);
hSrcFileHandle = NULL;
return status;
调用例子:
PWCHAR pSrcFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\1.txt";
PWCHAR pDestFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\2.txt";
ZwCopyFileW(pDestFileName, pSrcFileName);
6.2 封装GetFileSize
获取文件大小我们也可以封装下 核心原理就是使用 ZwQueryInformationFile
FILE_STANDARD_INFORMATION 调用号来实现的.
代码如下:
BOOLEAN GetFileSizeEx(
IN HANDLE hFile,
OUT PLARGE_INTEGER lpFileSize)
BOOLEAN bRet = FALSE;
FILE_STANDARD_INFORMATION fsi = {0};
IO_STATUS_BLOCK iosta = {0};
NTSTATUS status = STATUS_UNSUCCESSFUL;
if (hFile == NULL)
goto END;
if (lpFileSize == NULL)
goto END;
status = ZwQueryInformationFile(
hFile,
&iosta,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (NT_ERROR(status))
bRet = FALSE;
goto END;
lpFileSize->QuadPart = fsi.EndOfFile.QuadPart;
bRet = TRUE;
return bRet;
NTSTATUS GetFileSizeExample(PWCHAR fileName)
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE hFile = NULL;
UNICODE_STRING uStrFileName = {0};
OBJECT_ATTRIBUTES objStrFileNameAttri = {0};
IO_STATUS_BLOCK iosta = {0};
LARGE_INTEGER laFileSize = {0};
status = RtlUnicodeStringInit(&uStrFileName, fileName);
if (NT_ERROR(status))
goto END;
InitializeObjectAttributes(&objStrFileNameAttri, &uStrFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 0, 0);
status = ZwCreateFile(
&hFile,
GENERIC_READ,
&objStrFileNameAttri,
&iosta,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
if (NT_ERROR(status))
goto END;
GetFileSizeEx(hFile, &laFileSize);
if (hFile != NULL)
ZwClose(hFile);
hFile = NULL;
return status;
调用例子:
PWCHAR pSrcFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\1.txt";
GetFileSizeExample(pSrcFileName);
6.3 封装创建目录以及隐藏目录
创建目录以及创建隐藏目录 本质还是调用ZwCreateFile
只不过创建的属性分别为无属性以及隐藏属性. 创建标志标志属性指明为 创建的是DIR即可.
6.3.1 创建无属性目录
NTSTATUS ZwCreateDirectoryW(PWCHAR pDirName)
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING ustrDirName = {0};
OBJECT_ATTRIBUTES objDirAttri = {0};
IO_STATUS_BLOCK iosta = {0};
HANDLE hFile = NULL;
if (pDirName == NULL)
status = STATUS_INVALID_PARAMETER;
goto END;
status = RtlUnicodeStringInit(&ustrDirName, pDirName);
if (NT_ERROR(status))
goto END;
InitializeObjectAttributes(&objDirAttri, &ustrDirName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
status = ZwCreateFile(
&hFile,
GENERIC_READ,
&objDirAttri,
&iosta,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_CREATE,
FILE_DIRECTORY_FILE,
NULL,
if (NT_ERROR(status))
goto END;
if (hFile != NULL)
ZwClose(hFile);
hFile = NULL;
return status;
6.3.2 创建隐藏目录
NTSTATUS ZwCreateHideDirectoryW(PWCHAR pDirName)
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING ustrDirName = {0};
OBJECT_ATTRIBUTES objDirAttri = {0};
IO_STATUS_BLOCK iosta = {0};
HANDLE hFile = NULL;
if (pDirName == NULL)
status = STATUS_INVALID_PARAMETER;
goto END;
status = RtlUnicodeStringInit(&ustrDirName, pDirName);
if (NT_ERROR(status))
goto END;
InitializeObjectAttributes(&objDirAttri, &ustrDirName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
status = ZwCreateFile(
&hFile,
GENERIC_READ,
&objDirAttri,
&iosta,
NULL,
FILE_ATTRIBUTE_HIDDEN, // Hide
FILE_CREATE,
FILE_DIRECTORY_FILE,
NULL,
if (NT_ERROR(status))
goto END;
if (hFile != NULL)
ZwClose(hFile);
hFile = NULL;
return status;
6.3.3 调用示例
extern "C" NTSTATUS DriverEntry(
PDRIVER_OBJECT pDriverObj,
PUNICODE_STRING pReg)
UNREFERENCED_PARAMETER(pReg);
NTSTATUS status = STATUS_UNSUCCESSFUL;
pDriverObj->DriverUnload = DriverUnLoad;
KdBreakPoint();
PWCHAR pSrcFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\1.txt";
PWCHAR pDestFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\2.txt";
PWCHAR pCreateDirName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\test";
PWCHAR pCreateDirName1 = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\test1";
ZwCopyFileW(pDestFileName, pSrcFileName);
GetFileSizeExample(pSrcFileName);
ZwCreateDirectoryW(pCreateDirName);
ZwCreateHideDirectoryW(pCreateDirName1);
return STATUS_SUCCESS;
6.4 删除文件与文件夹的封装
可以删除文件也可以删除隐藏文件夹(或者普通文件夹)
本质还是ZwDeleteFile
的封装 删除文件有两种方式,如果遇到普通文件夹删除不掉可以尝试修改文件(夹)属性为无属性
然后继续尝试删除.
代码如下:
NTSTATUS ZwRemoveDirectoryW(PWCHAR pName)
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING ustrName = {0};
OBJECT_ATTRIBUTES objName = {0};
if (pName == NULL)
status = STATUS_INVALID_PARAMETER;
goto END;
status = RtlUnicodeStringInit(&ustrName, pName);
if (NT_ERROR(status))
goto END;
InitializeObjectAttributes(&objName, &ustrName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
status = ZwDeleteFile(&objName);
return status;
extern "C" NTSTATUS DriverEntry(
PDRIVER_OBJECT pDriverObj,
PUNICODE_STRING pReg)
UNREFERENCED_PARAMETER(pReg);
NTSTATUS status = STATUS_UNSUCCESSFUL;
pDriverObj->DriverUnload = DriverUnLoad;
KdBreakPoint();
PWCHAR pSrcFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\1.txt";
PWCHAR pDestFileName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\2.txt";
PWCHAR pCreateDirName = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\test";
PWCHAR pCreateDirName1 = L"\\??\\C:\\Users\\ibinary\\Desktop\\11\\test1";
ZwCopyFileW(pDestFileName, pSrcFileName);
GetFileSizeExample(pSrcFileName);
ZwCreateDirectoryW(pCreateDirName);
ZwCreateHideDirectoryW(pCreateDirName1);
ZwRemoveDirectoryW(pCreateDirName);
ZwRemoveDirectoryW(pCreateDirName1);
ZwRemoveDirectoryW(pDestFileName);
return STATUS_SUCCESS;
作者:IBinary
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功.
想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客
https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/10990683.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能.