In Windows NT, The 80386 protection mode is more robust than Windows 95, and this "gold-plated cage" is more robust and hard to break. In Windows 95, at least application I/O operations are unrestricted, while in Windows NT, our applications are deprived of this permission. In NT, it is almost impossible to enter the real ring0 layer.
In Windows NT, there are three device drivers:
1. "virtual device driver" (VDD ). Through VDD, 16-bit applications, such as DOS and Win16 applications, can access specific I/O Ports (note that access is not implemented directly, but through VDD ).
2. "GDI driver", which provides the required GDI functions for display and printing.
3. "kernel mode driver" is used to perform operations on specific hardware, such as createfile, closehandle (for file objects), readfile, writefile, and deviceiocontrol. "Kernel mode driver" is the only driver in Windows NT that can operate on hardware interruptions and DMA. Both the SCSI small port driver and the nic ndis driver are special forms of Kernel Mode driver.
Visual studio11 and Windows 8 Bring exceptionally different new experiences
1. Start vs11
2. See the full-purpose driver development Template
3. Select a driver mode. There are two drivers: Kernel Mode and user mode.
4. Create a driver, kmdf drivermvp
5. We chose the kernel-mode driver. The following is the created interface, namely the driver itself and the driver installation package.
6. Press F5 and select driver compilation,
Insert the following code to implement callback-based registry monitoring and filtering. For more information, see code analysis.
# Include "ntifs. H "# include" registrycallback. H "# include <ntstrsafe. h> ntstatus st; large_integer g_callbackcookie; ansi_string astr; void unloaddriver (pdriver_object driverobject); ntstatus callback (in pvoid callbackcontext, in pvoid argument1, in pvoid callback, punicode_string ppartialregistrypath, pvoid pregistryobject); NT Tatus DriverEntry (pdriver_object driverobject, punicode_string registrypath) {dbuplint ("[regroutine] loading! \ N "); driverobject-> driverunload = unloaddriver; ST = cmregistercallback (registrycallback, null, & g_callbackcookie); If (! Nt_success (ST) {dbuplint ("[regroutine] cmregistercallback failed! \ N "); Return st;} dbuplint (" [regroutine] registrycallback ADDR: 0x % 08x \ n ", registrycallback); dbuplint (" [regroutine] cookie. lowpart: 0x % 08x cookie. highpart: 0x % 08x \ n ", callback, callback); Return st;} void unloaddriver (pdriver_object driverobject) {cmunregistercallback (g_callbackcookie); dbuplint (" [regroutine] unloading! \ N ");} ntstatus registrycallback (in pvoid callbackcontext, in pvoid argument1, in pvoid argument2) {int type; Boolean exception = false; Boolean registryeventisvalid = false; unicode_string registrypath; uchar * registrydata = NULL; ulong registrydatalength = 0; ulong registrydatatype = 0; registrypath. length = 0; registrypath. maximumlength = ntstrsafe_unicode_string_max_cch * sizeof (wchar); registrypath. buf Fer = exallocatepoolwithtag (nonpagedpool, registrypath. maximumlength, 'cont'); If (registrypath. Buffer = NULL) {dbuplint ("[regroutine] allocate registrypath failed! \ N "); return STATUS_SUCCESS;} type = (reg_policy_class) argument1; try {Switch (type) {Case regntpostcreatekey: {preg_post_create_key_information createkey = (Signature) argument2; if (nt_success (createkey-> Status) | createkey-> Status = status_pending) // record the {pvoid * registryobject = createkey-> object; registryeventisvalid = getregistryobjectcompletename (istrypath, re Atekey-> completename, * registryobject); If (registryeventisvalid) {rtlunicodestringtoansistring (& astr, istrypath, true); dbuplint ("[regcreated] keyname: % s! \ N ", astr. buffer); // If a self-starting item is created, warn if (strstr (astr. buffer, "\ REGISTRY \ MACHINE \ Software \ Microsoft \ Windows \ CurrentVersion \ Run") {dbuplint ("[regcreated] forbin! \ N "); dbuplint (" [regcreated] forbinkeyname: % s! \ N ", astr. buffer); rtlfreeansistring (& astr);} elsedbuplint (" [regcreated] Get key name failed! \ N ") ;}} break; // using precreatekey can prevent key creation. However, only one key's completename can be used as the judgment basis, and Case regntprecreatekey cannot be obtained from the complete path: {export createkey = (bytes) argument2; rtlcopyunicodestring (istrypath, createkey-> completename); encrypt (& astr, istrypath, true); dbuplint ("[regroutine] precreate: % s! \ N ", astr. buffer); If (! Strcmp (astr. buffer, "new #1") {dbuplint ("[regroutine] forbin! \ N "); dbuplint (" [regroutine] forbinkeyname: % s! \ N ", astr. buffer); rtlfreeansistring (& astr); return response;} rtlfreeansistring (& astr);} break; Case regntdeletekey: {condition deletekey = (condition) argument2; condition = condition (istrypath, null, deletekey-> Object); If (registryeventisvalid) {rtlunicodestringtoansistring (& astr, istrypath, true); dbuplint ("[regdeletedkey] K Eyname: % s! \ N ", astr. buffer); If (! Strcmp (astr. buffer, "\ REGISTRY \ MACHINE \ Software \ Microsoft \ Windows \ CurrentVersion \ Run \ ljh00001") {dbuplint ("[regdeletedkey] forbin! \ N "); dbuplint (" [regdeletedkey] forbinkeyname: % s! \ N "); rtlfreeansistring (& astr); return response;} rtlfreeansistring (& astr) ;}} break; Case regntsetvaluekey: {preg_set_value_key_information setvalue = (optional) argument2; if (mmisaddressvalid (setvalue-> valuename) {registryeventisvalid = getregistryobjectcompletename (istrypath, null, setvalue-> Object); If (registryeventisvalid) {comment (& astr, ist Rypath, true); dbuplint ("[regsetvalue] valueparentpath: % s! \ N ", astr. buffer); rtlfreeansistring (& astr);} rtlunicodestringtoansistring (& astr, setvalue-> valuename, true); dbuplint (" [regsetvalue] valuename: % s! \ N ", astr. buffer); rtlfreeansistring (& astr); // output the data type and size of the set key value. If the type is REG_SZ, data is a unicode_string, the data size is the buffer length // plus the length of 4 bytes and the length of maxlength plus the length of 2 bytes ending at 00 dbuplint ("[regsetvalue] valuedatatype: % x, datasize: % x \ n ", setvalue-> type, setvalue-> datasize); If (setvalue-> type = 1) // type is REG_SZ, for other types of data, temporarily ignore {dbuplint ("[regsetvalue] data: % ws \ n", setvalue-> data) ;}} break; Case regntdeletevaluekey: {preg_delete_value_key _ Information deletevalue = (optional) argument2; If (mmisaddressvalid (deletevalue-> valuename) {registryeventisvalid = region (istrypath, null, deletevalue-> Object); If) {rtlunicodestringtoansistring (& astr, istrypath, true); dbuplint ("[regdelvalue] valueparentpath: % s! \ N ", astr. buffer); rtlfreeansistring (& astr);} rtlunicodestringtoansistring (& astr, deletevalue-> valuename, true); dbuplint (" [regdelvalue] valuename: % s! \ N ", astr. buffer); If (! Strcmp (astr. buffer, "ljh00001") {dbuplint ("[regdelvalue] forbin! \ N "); dbuplint (" [regdelvalue] forbinkeyname: % s! \ N "); rtlfreeansistring (& astr); return response;} rtlfreeansistring (& astr) ;}} break; Case regntrenamekey: {preg_rename_key_information renamevalue = (optional) argument2; if (mmisaddressvalid (renamevalue-> newname) {registryeventisvalid = random (istrypath, null, renamevalue-> Object); If (registryeventisvalid) {random (& astr, istr) Ypath, true); dbuplint ("[regrenamekey] keypath: % s! \ N ", astr. buffer); rtlfreeansistring (& astr);} rtlunicodestringtoansistring (& astr, renamevalue-> newname, true); dbuplint (" [regrenamekey] keyname: % s! \ N ", astr. buffer); rtlfreeansistring (& astr) ;}} break; default: Break ;}} couldn t (prediction_execute_handler) {dbuplint (" [regroutine] Catch a expection! \ N "); Exception = true; registryeventisvalid = false;} If (registrypath. buffer! = NULL) {exfreepoolwithtag (registrypath. buffer, 'cont');} return STATUS_SUCCESS;} Boolean evaluate (punicode_string pregistrypath, punicode_string delimiter, pvoid pregistryobject) {Boolean foundcompletename = false; Boolean partial = false; ntstatus status; ulong returnedlength; punicode_string pobjectname = NULL; // determine the object's validity if ((! Mmisaddressvalid (pregistryobject) | (pregistryobject = NULL) {dbuplint ("[regroutine] pregistryobject invalid! \ N "); Return false;} // use obquerynamestring to obtain the object name status = obquerynamestring (pregistryobject, (pobject_name_information) pobjectname, 0, & returnedlength ); if (status = success) // The buffer length transmitted for the first time is 0, and the result returned by obquerynamestring must be insufficient buffer size {pobjectname = exallocatepoolwithtag (nonpagedpool, returnedlength, 'cont '); // apply for memory if (pobjectname = NULL) // if the request for memory fails, false {dbuplint ("[regroutine] allo is returned. Catepool failed! \ N "); Return false;} // query name status = obquerynamestring (pregistryobject, (pobject_name_information) pobjectname, returnedlength, & returnedlength); If (nt_success (Status )) {rtlunicodestringcopy (pregistrypath, pobjectname); // copy the name foundcompletename = true;} exfreepoolwithtag (pobjectname, 'cont '); // whether the query is successful or not, the memory should be released} return foundcompletename ;}