调用Zw函数 —> 检查参数,检查发起操作的模式 --> nt函数
驱动程序源代码:
#include<ntifs.h>
#include<windef.h>
#include<ntstrsafe.h>
#include<ntddk.h>
#define DEVICE_NAME L"\\Device\\MyFirstDevice"
#define SYM_NAME L"\\??\\MyFirstDevice"
#define IOCTL_MUL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x9888, METHOD_BUFFERED, FILE_ANY_ACCESS)
VOID nothing(HANDLE ppid, HANDLE mypid, BOOLEAN bcreate)
{
DbgPrint("ProcessNotify\n");
}
VOID DrvUnload(PDRIVER_OBJECT pdriver)
{
DbgPrint("Unload\n");
if (pdriver->DeviceObject)
{
IoDeleteDevice(pdriver->DeviceObject);
UNICODE_STRING symname = { 0 };
RtlInitUnicodeString(&symname, SYM_NAME);
IoDeleteSymbolicLink(&symname);
}
PsSetCreateProcessNotifyRoutine(nothing, TRUE);
}
NTSTATUS MyCreate(PDEVICE_OBJECT pdevice, PIRP pirp) //PDEVICE_OBJECT
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("My Device has be opened\n");
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = 0;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return 0;
}
NTSTATUS MyClose(PDEVICE_OBJECT pdevice, PIRP pirp) //PDEVICE_OBJECT
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("My Device has be MyClose\n");
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = 0;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return 0;
}
NTSTATUS MyCleanUp(PDEVICE_OBJECT pdevice, PIRP pirp) //PDEVICE_OBJECT
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("My Device has be MyCleanUp\n");
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = 0;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return 0;
}
NTSTATUS MyRead(PDEVICE_OBJECT pdevice, PIRP pirp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("My Device has be MyRead\n");
PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
ULONG readsize = pstack->Parameters.Read.Length;
PCHAR readbuffer = pirp->AssociatedIrp.SystemBuffer;
RtlCopyMemory(readbuffer, "This Message Come From Kernel.", strlen("This Message Come From Kernel."));
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = strlen("This Message Come From Kernel.");
DbgPrint("Really Read Info Len is %d\n", strlen("This Message Come From Kernel."));
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS MyWrite(PDEVICE_OBJECT pdevice, PIRP pirp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("My Device has be MyWrite\n");
PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
ULONG writesize = pstack->Parameters.Write.Length;
PCHAR writebuffer = pirp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(pdevice->DeviceExtension, 200);
RtlCopyMemory(pdevice->DeviceExtension, writebuffer, writesize);
DbgPrint("--%p--%s\n", writebuffer, (PCHAR)pdevice->DeviceExtension);
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = 13;
DbgPrint("Really Read Info Len is %d\n", strlen("This Message Come From Kernel."));
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS MyControl(PDEVICE_OBJECT pdevice, PIRP pirp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
ULONG iocode = pstack->Parameters.DeviceIoControl.IoControlCode;
ULONG inlen = pstack->Parameters.DeviceIoControl.InputBufferLength;
ULONG outlen = pstack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG ioinfo = 0;
DbgPrint("---------Device IO---------\n");
switch (iocode)
{
case IOCTL_MUL:
{
DWORD indata = *(PDWORD)pirp->AssociatedIrp.SystemBuffer;
DbgPrint("--Kernel Indata %d--\n", indata);
indata = indata * 5;
*(PDWORD)pirp->AssociatedIrp.SystemBuffer = indata;
ioinfo = 888;
break;
}
default:
status = STATUS_UNSUCCESSFUL;
ioinfo = 0;
break;
}
DbgPrint("My Device has be MyCleanUp\n");
pirp->IoStatus.Status = status;
pirp->IoStatus.Information = 0;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return 0;
}
//5.1 KernelDeleteFile() 局限性:只可删除未被占用的程序
NTSTATUS KernelDeleteFile(PWCHAR file_path)
{
UNICODE_STRING filepath = { 0 };
NTSTATUS status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES obja = { 0 };
RtlInitUnicodeString(&filepath, file_path);
InitializeObjectAttributes(&obja, &filepath, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwDeleteFile(&obja);
if (!NT_SUCCESS(status))
{
DbgPrint("Delete File Failed: %x\n", status);
}
return status;
}
//5.2 KernelCopyFile()
NTSTATUS KernelCopyFile(PWCHAR defile_path, PWCHAR sourcefile_path)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE hfile1 = NULL;
UNICODE_STRING sourcefilepath = { 0 };
IO_STATUS_BLOCK iostack1 = { 0 };
OBJECT_ATTRIBUTES obja1 = { 0 };
RtlInitUnicodeString(&sourcefilepath, sourcefile_path);
InitializeObjectAttributes(&obja1, &sourcefilepath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwOpenFile(&hfile1, GENERIC_ALL, &obja1, &iostack1, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(status))
{
DbgPrint("Open SourceFile Failed: %x\n", status);
return status;
}
FILE_STANDARD_INFORMATION fbi = { 0 };
status = ZwQueryInformationFile(hfile1, &iostack1, &fbi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
if (!NT_SUCCESS(status))
{
DbgPrint("QueryInformation SourceFile Failed: %x\n", status);
ZwClose(hfile1);
return status;
}
PVOID filebuffer = NULL;
filebuffer = ExAllocatePool(NonPagedPool, fbi.EndOfFile.QuadPart);
if (!filebuffer)
{
DbgPrint("AllocateBuffer Failed\n");
ZwClose(hfile1);
return status;
}
RtlZeroMemory(filebuffer, fbi.EndOfFile.QuadPart);
LARGE_INTEGER readoffset = { 0 };
readoffset.QuadPart = 0;
status = ZwReadFile(hfile1, NULL, NULL, NULL, &iostack1, filebuffer, fbi.EndOfFile.QuadPart, &readoffset, NULL);
if (!filebuffer)
{
DbgPrint("ReadFile Failed :%x\n", status);
ZwClose(hfile1);
ExFreePool(filebuffer);
return status;
}
DbgPrint("---IoInfo---%d\n", iostack1.Information);
ZwClose(hfile1);
//create new file
HANDLE hfile2 = NULL;
UNICODE_STRING defilepath = { 0 };
OBJECT_ATTRIBUTES obja2 = { 0 };
IO_STATUS_BLOCK iostack2 = { 0 };
RtlInitUnicodeString(&defilepath, defile_path);
InitializeObjectAttributes(&obja2, &defilepath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateFile(&hfile2, GENERIC_ALL, &obja2, &iostack2, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
{
DbgPrint("Create File Failed : %x\n", status);
ExFreePool(filebuffer);
return status;
}
LARGE_INTEGER writeoffset = { 0 };
writeoffset.QuadPart = 0;
status = ZwWriteFile(hfile2, NULL, NULL, NULL, &iostack2, filebuffer, fbi.EndOfFile.QuadPart, &writeoffset, NULL);
if (!NT_SUCCESS(status))
{
DbgPrint("Write File Failed : %x\n", status);
ExFreePool(filebuffer);
ZwClose(hfile2);
return status;
}
DbgPrint("---write---%d\n", iostack2.Information);
ExFreePool(filebuffer);
ZwClose(hfile2);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) //PDRIVER_OBJECT
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING devicename = { 0 }; //RTL_CONSTANT_STRING(DEVICE_NAME)
UNICODE_STRING targeunicode = { 0 };
PDEVICE_OBJECT pdevice = NULL;
driver->DriverUnload = DrvUnload;
//test1
/*
RtlInitUnicodeString(&devicename, DEVICE_NAME);
PWCHAR testbuffer = ExAllocatePool(NonPagedPool, 0x1000);
RtlZeroMemory(testbuffer, 0x1000);
RtlCopyMemory(testbuffer, L"FFFFFFF", sizeof(L"FFFFFFF"));
RtlInitUnicodeString(&devicename, testbuffer);
DbgPrint("--%wZ--\n", &devicename);
*/
//test2
PCHAR tempbuffer = "C:\\ABc\\fff\\dEF\\123.txt";
STRING str = { 0 };
RtlInitString(&str, tempbuffer);
RtlAnsiStringToUnicodeString(&devicename, &str, TRUE);
DbgPrint("--%wZ--\n", &devicename);
targeunicode.Buffer = ExAllocatePool(NonPagedPool, 0x1000);
targeunicode.MaximumLength = 0x1000;
RtlCopyUnicodeString(&targeunicode, &devicename);
DbgPrint("--%wZ--\n", &targeunicode);
RtlUpcaseUnicodeString(&devicename, &devicename, FALSE);
ExFreePool(targeunicode.Buffer);
RtlFreeUnicodeString(&devicename);
//test3
PWCHAR tempbuffer2 = ExAllocatePool(NonPagedPool, 0x1000);
RtlZeroMemory(tempbuffer2, 0x1000);
RtlStringCbCopyW(tempbuffer2, 0x1000, L"\\??\\");
RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\\ABc\\fff\\dEF\\123.txt");
UNICODE_STRING temp1 = { 0 }, temp2 = { 0 };
RtlInitUnicodeString(&temp1, tempbuffer2);
RtlInitUnicodeString(&temp2, L"\\??\\");
if (RtlPrefixUnicodeString(&temp2, &temp1, FALSE))
{
DbgPrint("OK , FINE\n");
}
UNICODE_STRING temp3 = { 0 }, temp4 = { 0 };
RtlInitUnicodeString(&temp3, L"D:\\ABc\\fcc\\ddd\\eee.txt");
RtlInitUnicodeString(&temp4, L"D:\\ABc\\fcc\\DDD\\eee.txt");
if (RtlEqualUnicodeString(&temp3, &temp4, TRUE))
{
DbgPrint("temp3 = temp4\n");
}
UNICODE_STRING temp5 = { 0 };
RtlInitUnicodeString(&temp5, L"*EEE.TXT"); //EEE.TXT 一定要大写
if (FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL))
{
DbgPrint("Searched\n");
}
DbgPrint("--%ws--\n", &tempbuffer2);
/*
status = IoCreateDevice((PDRIVER_OBJECT)driver, 200, &devicename, FILE_DEVICE_UNKNOWN, 0, TRUE, &pdevice);
if (!NT_SUCCESS(status)){
DbgPrint("Create Device Failed : %x\n", status);
return status;
}
pdevice->Flags |= DO_BUFFERED_IO;
创建符号链接
UNICODE_STRING symname = { 0 };
RtlInitUnicodeString(&symname, SYM_NAME);
status = IoCreateSymbolicLink(&symname, &devicename);
if (!NT_SUCCESS(status))
{
DbgPrint("Create SymbolicLink Failed : %x\n", status);
IoDeleteDevice(pdevice);
return status;
}
driver->MajorFunction[IRP_MJ_CREATE] = MyCreate;
driver->MajorFunction[IRP_MJ_CLOSE] = MyClose;
driver->MajorFunction[IRP_MJ_CLEANUP] = MyCleanUp;
driver->MajorFunction[IRP_MJ_READ] = MyRead;
driver->MajorFunction[IRP_MJ_WRITE] = MyWrite;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyControl;
*/
KernelDeleteFile(L"\\??\\C:\\123.exe");
KernelCopyFile(L"\\??\\C:\\888.exe", L"\\??\\C:\\567.exe");
return 0;
}
执行前状态:
执行后(删除123.exe,567.exe赋值到888.exe):