学习内核近一个月的时间了,利用自己学到的那点知识做了个小玩意儿。
简单说就是使用内核API函数ZwCreateFile ZwReadFile ZwWriteFile ZwClose 对文件进行操作。
功能如下():
1.打开文件(调用方法->需输入:\??\文件路径。打开后的文件会被驱动占用,占用时其他任何程序都无法查看,移动,复制)
2.查看文件
3.修改文件
4.关闭文件(关闭文件后结束占用)
0.退出系统
占用效果图:
驱动代码:
#include<ntddk.h>
#define _DeviceName L"\\Device\\MyDeviceName"
#define _DeviceSybLink L"\\??\\MyDeviceLink"
#define USER_FILE_CREATE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x810,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_SET (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x811,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_GET (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x812,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_CLOSE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x813,METHOD_BUFFERED,FILE_READ_DATA)
PUNICODE_STRING DeviceObject = { 0 };
UNICODE_STRING DeviceName = { 0 };
UNICODE_STRING DeviceSybLink = { 0 };
HANDLE FileHandle = { 0 };
NTSTATUS MyCallBack(PDEVICE_OBJECT _DeviceObject, PIRP Pirp) {
ULONG Len = 4;
NTSTATUS CallBackStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION Irp = IoGetCurrentIrpStackLocation(Pirp);
NTSTATUS IoCreateFileStatus_ = { 0 };
if (_DeviceObject == DeviceObject) {
if (Irp->MajorFunction == IRP_MJ_CREATE) DbgPrint("驱动被调用了Create\n");
if (Irp->MajorFunction == IRP_MJ_CLOSE) DbgPrint("驱动被调用了Close\n");
if (Irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
PVOID Buffer = Pirp->AssociatedIrp.SystemBuffer;
ULONG InputLen = Irp->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLen = Irp->Parameters.DeviceIoControl.OutputBufferLength;
switch (Irp->Parameters.DeviceIoControl.IoControlCode) {
case USER_FILE_CREATE: {
UNICODE_STRING FileName = { 0 };
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS IoCreateFileStatus = NULL;
RtlInitUnicodeString(&FileName, Buffer);
DbgPrint("Buffer:%wZ\n", &FileName);
InitializeObjectAttributes(
&ObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
NTSTATUS IoCreateFileStatus_ = ZwCreateFile(
&FileHandle,
GENERIC_ALL,
&ObjectAttributes,
&IoCreateFileStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (IoCreateFileStatus_ == STATUS_SUCCESS) {
char str[] = "执行成功打开文件";
Len = sizeof(str);
RtlCopyMemory(
Buffer,
&str,
Len
);
DbgPrint("成功打开文件\n");
}
else {
char str[] = "执行失败打开文件";
Len = sizeof(str);
RtlCopyMemory(
Buffer,
&str,
Len
);
DbgPrint("失败打开文件,错误原因:0x%x\n",IoCreateFileStatus);
}
break;
}
case USER_FILE_GET: {
NTSTATUS IoReadFileStatus = STATUS_SUCCESS;
NTSTATUS IoReadFileStatus_ = STATUS_SUCCESS;
char RetReadValue[128] = { 0 };
LARGE_INTEGER FileStart = { 0 };
FileStart.QuadPart = 0;
IoReadFileStatus_ = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoReadFileStatus,
&RetReadValue,
sizeof(RetReadValue),
&FileStart,
NULL
);
if (IoReadFileStatus_ == STATUS_SUCCESS) {
Len = sizeof(RetReadValue);
RtlCopyMemory(Buffer, &RetReadValue, Len);
}
else DbgPrint("读取失败,错误码:0x%x\n", IoReadFileStatus);
break;
}
case USER_FILE_SET: {
NTSTATUS IoWriteFileStatus_ = { 0 };
NTSTATUS IoWriteFileStatus = { 0 };
LARGE_INTEGER ByteOffset = { 0 };
ByteOffset.QuadPart = 0;
IoWriteFileStatus_ = ZwWriteFile(
FileHandle,
NULL,
NULL,
NULL,
&IoWriteFileStatus,
Buffer,
strlen(Buffer), //因为取回的是字符串,Buffer又是个指针,必须用strlen取指针字符串长度
&ByteOffset,
NULL
);
if (IoWriteFileStatus_ == STATUS_SUCCESS) {
Len = sizeof("文件修改成功");
RtlCopyMemory(Buffer, "文件修改成功", Len);
}
else {
Len = sizeof("文件修改失败");
RtlCopyMemory(
Buffer,
"文件修改失败",
Len
);
}
break;
}
case USER_FILE_CLOSE: {
if (FileHandle!=STATUS_SUCCESS) {
ZwClose(FileHandle);
FileHandle = NULL;
RtlCopyMemory(Buffer, "文件已关闭", sizeof("文件已关闭"));
Len = sizeof("文件已关闭");
}
else {
RtlCopyMemory(Buffer, "没有文件开启", sizeof("没有文件开启"));
Len = sizeof("没有文件开启");
}
break;
}
}
}
}
else {
DbgPrint("设备错误\n");
CallBackStatus = STATUS_ACCESS_DENIED;
}
Pirp->IoStatus.Status = CallBackStatus;
Pirp->IoStatus.Information = Len;
IoCompleteRequest(Pirp, IO_NO_INCREMENT);
return CallBackStatus;
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
IoDeleteSymbolicLink(&DeviceSybLink);
IoDeleteDevice(DeviceObject);
DbgPrint("驱动卸载\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Reg) {
RtlInitUnicodeString(&DeviceName, _DeviceName);
RtlInitUnicodeString(&DeviceSybLink, _DeviceSybLink);
NTSTATUS IoCreateStatus=IoCreateDevice(
DriverObject,
0,
&DeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DeviceObject
);
if (IoCreateStatus == STATUS_SUCCESS) {
DbgPrint("设备创建成功,设备对象:%p\n", DriverObject);
NTSTATUS IoCreateSybStatus = IoCreateSymbolicLink(&DeviceSybLink, &DeviceName);
if (IoCreateSybStatus == STATUS_SUCCESS) {
DbgPrint("符号链接创建成功,链接名:%wZ\n", &DeviceSybLink);
}
}
else DbgPrint("设备创建失败\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCallBack;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyCallBack;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyCallBack;
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
可执行程序代码:
#include <iostream>
#include<windows.h>
#define _DeviceSybLink L"\\\\.\\MyDeviceLink"
#define USER_FILE_CREATE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x810,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_SET (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x811,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_GET (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x812,METHOD_BUFFERED,FILE_READ_DATA)
#define USER_FILE_CLOSE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0x813,METHOD_BUFFERED,FILE_READ_DATA)
HANDLE DeviceHandle = { 0 };
int main();
void createFile() {
DWORD Ret = { 0 };
WCHAR FileName[128] = { 0 };
char retValue[128] = { 0 };
//打开设备
DeviceHandle = CreateFileW(
_DeviceSybLink,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM,
0
);
printf("请输入文件名:");
//传入字符串使用scanf_s时需传入第三个参数,也就是内存字节长度
scanf_s("%ws", &FileName,sizeof(FileName));
//使用控制码通信
BOOL IoStatus = DeviceIoControl(
DeviceHandle,
USER_FILE_CREATE,
&FileName,
sizeof(FileName),
&retValue,
sizeof(retValue),
&Ret,
0
);
if (IoStatus == TRUE)printf("成功发送文件名\n");
else printf("失败发送文件名\n");
//内核向应用层传输字符串时,使用char类型吧,因为WCHAR宽字符类型的内核向应用传输还未掌握。
printf("%s\n", &retValue);
system("pause");
main();
}
void readFile() {
char RetFileValue[128] = { 0 };
DWORD RetNum = { 0 };
BOOL IoStatus = DeviceIoControl(
DeviceHandle,
USER_FILE_GET,
NULL,
0,
&RetFileValue,
sizeof(RetFileValue),
&RetNum,
0
);
if (IoStatus == TRUE) printf("成功,文件内容:%s\n",&RetFileValue);
else printf("失败\n");
system("pause");
main();
}
void setFile() {
char inputValue[128] = { 0 };
char retValue[128] = { 0 };
DWORD Ret = { 0 };
printf("请输入要修改的值:");
//如果应用层传入到内核层要修改的值是char类型的,
//那么内核层传回修改后的内容也要是char类型的,
//否则会显示错误
scanf_s("%s", &inputValue, sizeof(inputValue));
BOOL IoStatus = DeviceIoControl(
DeviceHandle,
USER_FILE_SET,
&inputValue,
sizeof(inputValue),
&retValue,
sizeof(retValue),
&Ret,
0
);
if (IoStatus == TRUE) printf("%s\n", &retValue);
else printf("Io通信失败\n");
system("pause");
main();
}
void closeFile() {
DWORD RetNum = { 0 };
char retValue[128] = { 0 };
BOOL IoStatus = DeviceIoControl(
DeviceHandle,
USER_FILE_CLOSE,
NULL,
0,
&retValue,
sizeof(retValue),
&RetNum,
0
);
printf("%s\n", &retValue);
system("pause");
main();
}
int main(){
int ctl_code = -1;
//while (1) {
printf("1.打开文件\n");
printf("2.查看文件\n");
printf("3.修改文件\n");
printf("4.关闭文件\n");
printf("0.退出系统\n");
scanf_s("%d", &ctl_code);
switch (ctl_code) {
case 1: {
createFile();
break;
}
case 2: {
readFile();
break;
}
case 3: {
setFile();
break;
}
case 4: {
closeFile();
break;
}
case 0:
exit(0);
break;
}
//}
}