Ring3 adopts two common methods: METHOD_BUFFERED and METHOD_IN_DIRECT to test the ring0-level interactive file reading,
To familiarize yourself with the interaction process between ring3 and ring0, I wrote a simple program to test it so as to deepen my impression.
This article reads fixed files on a disk by testing METHOD_BUFFERED and METHOD_IN_DIRECT. For details about the communication methods of ring0 and ring3, see the following link.
Http://book.51cto.com/art/201107/275240.htm
The Code is as follows:
Ring3:
# Include <Windows. h> # include <winioctl. h> # include <stdio. h> # define BUFFERSIZE 1024 // two read/write modes # define CTL_CODE (latency, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) # define IOCTL_IN_DIRECT CTL_CODE (latency, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS) //////////////////////////////////////// /// // void Usage (char * proc) {printf ("% s-B // buffer Io \ n "" % s-d // direct io \ n ", proc, proc);} int main (int argc, char * argv []) {if (argc! = 2) {Usage (argv [0]); return 0;} char OutBufer [BUFFERSIZE]; bool ret = true; DWORD dwLength = 0; // HANDLE hDevice = CreateFile ("\\\\. \ KeReadSL ", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); if (hDevice = INVALID_HANDLE_VALUE) {printf ("Failed to open device ---- errorcode = % d... \ n ", GetLastError (); return 0;} if (strcmp (argv [1],"-B ") = 0) {printf (" Read File by Buf Fer Io way... \ n "); ret = DeviceIoControl (hDevice, IOCTL_DO_BUFFER, NULL, 0, OutBufer, BUFFERSIZE, & dwLength, NULL);} else if (strcmp (argv [1], "-d") = 0) {printf ("Read File by Direct Io way... \ n "); ret = DeviceIoControl (hDevice, IOCTL_IN_DIRECT, NULL, 0, OutBufer, BUFFERSIZE, & dwLength, NULL);} else {Usage (argv [0]); ret = false;} if (ret) {OutBufer [dwLength] = '\ 0'; printf ("Congratulation !!! \ NReadData: % s \ n ", OutBufer);} CloseHandle (hDevice); return 0 ;}
Ring0
# Include <ntddk. h> # define CTL_CODE (latency, 0x800, latency, FILE_ANY_ACCESS) # define CTL_CODE (latency, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS) typedef struct _ DEVICE_EXTENSION {PDEVICE_OBJECT pDevice; UNICODE_STRING ustrDeviceName; // device name UNICODE_STRING ustrSymlinkName; // Symbolic Link name} DEVICE_EXTENSION, * PDEVICE_EXTENSION; /////////////////////// //////////////////////////////////////// /////////// Read the file (for convenience, the test reads a small test.txt file from the C drive) ULONG KeReadFileData (UCHAR * OutputBuffer, ULONG BufferSize, ULONG * ReadSize) {OBJECT_ATTRIBUTES metadata; ioiostatus; HANDLE hFile; // initialize the file path UNICODE_STRING ustrFilePath; encode (& ustrFilePath, L "\\?? \ C :\\ test.txt "); InitializeObjectAttributes (& objectAtrtributes, & ustrFilePath, expiration, NULL, NULL); // open the file NTSTATUS zwStatus = ZwCreateFile (& hFile, GENERIC_READ, & objectAtrtributes, & iostatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (! NT_SUCCESS (zwStatus) {KdPrint ("The file is not exist! \ N "); return 0;} // obtain the file length FILE_STANDARD_INFORMATION fsi; zwStatus = ZwQueryInformationFile (hFile, & iostatus, & fsi, sizeof (FILE_STANDARD_INFORMATION), FileStandardInformation ); if (! NT_SUCCESS (zwStatus) {KdPrint ("Failed to ZwQueryInformationFile... \ n "); ZwClose (hFile); return 0;} ULONG DataSizeReaded = BufferSize <fsi. endOfFile. quadPart? BufferSize: fsi. endOfFile. quadPart; // actual file size to be read // zwStatus = ZwReadFile (hFile, NULL, & iostatus, OutputBuffer, DataSizeReaded, NULL, NULL); if (! NT_SUCCESS (zwStatus) {KdPrint ("Failed to ZwReadFile... \ n "); ZwClose (hFile); return 0;} KdPrint (" The program really read % d byutes... \ n ", iostatus. information); * ReadSize = iostatus. information; ZwClose (hFile); return 1 ;} //////////////////////////////////////// /// // create a device NTSTATUS CreateDevice (PDRIVER_OBJECT pDriverObject, UNICODE_STRING devname, UNICODE_STRING symLinkName) {NTSTATUS status; PDEVICE_OBJECT p1_bj; PDEVICE_EXTENSION pDevExt; // create a device status = IoCreateDevice (pDriverObject, sizeof (DEVICE_EXTENSION), & devname, FILE_DEVICE_UNKNOWN, 0, TRUE, & p1_bj ); if (! NT_SUCCESS (status) return status; p1_bj-> Flags | = bytes; pDevExt = (PDEVICE_EXTENSION) p1_bj-> DeviceExtension; pDevExt-> pDevice = p1_bj; pDevExt-> ustrDeviceName = devname; pDevExt-> ustrSymlinkName = symLinkName; KdPrint ("devname = % wZ \ nsymbollink = % wZ \ n", & devname, & symLinkName )); // create the device link status = IoCreateSymbolicLink (& symLinkName, & devname); if (! NT_SUCCESS (status) {KdPrint ("Failed to IoCreateSymbolicLink and delete DeviceObject --- errorcode = % d... \ n ", status); IoDeleteDevice (pDevObj); return status ;}return status ;}// uninstall the driver VOID DriverUnload (PDRIVER_OBJECT pDriverObject) {PDEVICE_OBJECT pNextObj; kdPrint ("Enter DriverUnload... \ n "); pNextObj = pDriverObject-> DeviceObject; // cyclically traverses and deletes all devices on the driver while (pNextObj! = NULL) {// The device name and Link name are stored in the extended structure PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pNextObj-> DeviceExtension; // Delete the symbolic link UNICODE_STRING LinkName = pDevExt-> ustrSymlinkName; IoDeleteSymbolicLink (& LinkName); pNextObj = pNextObj-> NextDevice; IoDeleteDevice (pDevExt-> pDevice );}} // process the message NTSTATUS DeviceIoControlDispatch (PDEVICE_OBJECT p1_bj, PIRP pIrp) {NTSTATUS status = STATUS_SUCCESS; KdPrint ("Enter DeviceIoControlDis Patch... \ n "); // obtain the current stack PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation (pIrp); // obtain the buffer size such as ULONG cbin = stack-> Parameters. deviceIoControl. inputBufferLength; // output buffer size ULONG cbout = stack-> Parameters. deviceIoControl. outputBufferLength; // obtain the IOCTL code ULONG code = stack-> Parameters. deviceIoControl. ioControlCode; // the actual size of the Read File ULONG ReadSize = 0; // determine the file operation mode switch (code) {case IOCTL_DO_BUFFER: // The buffer operation only performs the Read File test ){ UCHAR * OutputBuffer = (UCHAR *) pIrp-> AssociatedIrp. SystemBuffer; if (! KeReadFileData (OutputBuffer, cbout, & ReadSize) status = STATUS_UNSUCCESSFUL; break;} case IOCTL_IN_DIRECT: // direct file operation {// map the buffer to the address UCHAR * OutputBuffer = (UCHAR *) MmGetSystemAddressForMdlSafe (pir-> MdlAddress, NormalPagePriority) in kernel mode; if (! KeReadFileData (OutputBuffer, cbout, & ReadSize) status = STATUS_UNSUCCESSFUL; break;} default: {status = STATUS_INVALID_VARIANT ;}// set the completion status of the IRP. status = status; pir-> IoStatus. information = ReadSize; IoCompleteRequest (pIrp, IO_NO_INCREMENT); KdPrint ("Leave DeviceIoControlDispatch... \ n "); return status;} // IRP request processing function NTSTATUS MyDispatchFunction (PDEVICE_OBJECT device, piririrp) {// obtain the stack space PI of the current irp call O_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (irp); NTSTATUS status = STATUS_INVALID_PARAMETER; // process various request switches (irpsp-> MajorFunction) {case IRP_MJ_CREATE: // This IRP requires simple processing, otherwise, an error occurred while opening the device link in CreateFile {// a simple error occurred while returning an IRP success trilogy irp-> IoStatus. information = 0; irp-> IoStatus. status = STATUS_SUCCESS; IoCompleteRequest (irp, IO_NO_INCREMENT); // At the application layer, print the string after the device is turned on. This string is only used to test dbgprs int ("congratulations gay, open device "); status = irp-> IoS Tatus. status; break;} case IRP_MJ_CLOSE: {irp-> IoStatus. information = 0; irp-> IoStatus. status = STATUS_SUCCESS; IoCompleteRequest (irp, IO_NO_INCREMENT); // At the application layer, print the string after the device is turned on. This string is only used to test dbgprs int ("congratulations gay, close device "); status = irp-> IoStatus. status; break;} case IRP_MJ_READ: {break;} default: {dbuplint ("unknow request !!! "); Break ;}} return status;} NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {dbuplint (" Enter DriverEntry \ n "); // KdPrint ("Enter DriverEntry \ n"); NTSTATUS status; // set the dispatch function for (int I = 0; I <IRP_MJ_MAXIMUM_FUNCTION; I ++) pDriverObject-> MajorFunction [I] = MyDispatchFunction; pDriverObject-> MajorFunction [IRP_MJ_DEVICE_CONTROL] = DeviceIoControlDispatch; pDriverObject-> DriverU Nload = DriverUnload; // create a Device and link UNICODE_STRING ustrDevName, ustrSymbolicName; RtlInitUnicodeString (& ustrDevName, L "\ Device \ KeRead"); RtlInitUnicodeString (& signature, L "\ DosDevices \ KeReadSL"); status = CreateDevice (pDriverObject, ustrDevName, ustrSymbolicName); if (! NT_SUCCESS (status) {KdPrint ("Failed to Create Device... \ n "); return STATUS_UNSUCCESSFUL;} KdPrint (" Exit DriverEntry \ n "); return STATUS_SUCCESS ;}