相关文章推荐

文件操作,以及强删文件.

一丶文件操作

1.文件操作的几种方式

内核层的两个??其实是符号链接.代表的是是
\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

    欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能.
     
    推荐文章