📄 regsys.c
字号:
//======================================================================
//
// Regsys.c
//
// Copyright (C) 1996-1998 Mark Russinovich and Bryce Cogswell
//
// Hooks the registry by replacing registry related calls in the system
// service table with pointers to our own hook routines. Very simple
// yet very effective.
//
//======================================================================
#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
#include "..\gui\ioctlcmd.h"
#include "regsys.h"
//----------------------------------------------------------------------
// DEFINES
//----------------------------------------------------------------------
// print macro that only turns on when debugging is on
#if DBG
#define DbgPrint(arg) DbgPrint arg
#else
#define DbgPrint(arg)
#endif
//
// Macro for easy hook/unhook. On X86 implementations of Zw* functions, the DWORD
// following the first byte is the system call number, so we reach into the Zw function
// passed as a parameter, and pull the number out. This makes system call hooking
// dependent ONLY on the Zw* function implementation not changing.
//
#if defined(_ALPHA_)
#define SYSCALL(_function) ServiceTable->ServiceTable[ (*(PULONG)_function) & 0x0000FFFF ]
#else
#define SYSCALL(_function) ServiceTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]
#endif
//
// Number of predefined rootkeys
//
#define NUMROOTKEYS 4
//
// The name of the System process, in which context we're called in our DriverEntry
//
#define SYSNAME "System"
//
// A unicode string constant for the "default" value
//
#define DEFAULTNAMELEN (9*sizeof(WCHAR))
WCHAR DefaultValueString[] = L"(Default)";
UNICODE_STRING DefaultValue = {
DEFAULTNAMELEN,
DEFAULTNAMELEN,
DefaultValueString
};
//
// A filter to use if we're monitoring boot activity
//
FILTER BootFilter = {
"*", "", "*", "",
TRUE, TRUE, TRUE, TRUE
};
//----------------------------------------------------------------------
// FORWARD DEFINES
//----------------------------------------------------------------------
NTSTATUS RegmonDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID RegmonUnload( IN PDRIVER_OBJECT DriverObject );
//----------------------------------------------------------------------
// GLOBALS
//----------------------------------------------------------------------
// our user-inteface device object
PDEVICE_OBJECT GUIDevice;
//
// Is a GUI talking to us?
//
BOOLEAN GUIActive = FALSE;
//
// Are we logging a boot sequence?
//
BOOLEAN BootLogging = FALSE;
KEVENT LoggingEvent;
HANDLE LogFile = INVALID_HANDLE_VALUE;
PSTORE_BUF BootSavedStoreList = NULL;
PSTORE_BUF BootSavedStoreTail;
//
// Is registry hooked?
//
BOOLEAN RegHooked = FALSE;
//
// Global error string
//
CHAR errstring[256];
//
// Global filter (sent to us by the GUI)
//
FILTER FilterDef;
//
// Lock to protect filter arrays
//
KMUTEX FilterMutex;
//
// Array of process and path filters
//
ULONG NumProcessFilters = 0;
PCHAR ProcessFilters[MAXFILTERS];
ULONG NumProcessExcludeFilters = 0;
PCHAR ProcessExcludeFilters[MAXFILTERS];
ULONG NumPathIncludeFilters = 0;
PCHAR PathIncludeFilters[MAXFILTERS];
ULONG NumPathExcludeFilters = 0;
PCHAR PathExcludeFilters[MAXFILTERS];
//
// Pointer to system global service table
//
PSRVTABLE ServiceTable;
//
// This is the offset into a KPEB of the current process name. This is determined
// dynamically by scanning the process block belonging to the GUI for its name.
//
ULONG ProcessNameOffset;
//
// We save off pointers to the actual Registry functions in these variables
//
NTSTATUS (*RealRegOpenKey)( IN PHANDLE, IN OUT ACCESS_MASK, IN POBJECT_ATTRIBUTES );
NTSTATUS (*RealRegQueryKey)( IN HANDLE, IN KEY_INFORMATION_CLASS,
OUT PVOID, IN ULONG, OUT PULONG );
NTSTATUS (*RealRegQueryValueKey)( IN HANDLE, IN PUNICODE_STRING,
IN KEY_VALUE_INFORMATION_CLASS,
OUT PVOID, IN ULONG, OUT PULONG );
NTSTATUS (*RealRegEnumerateValueKey)( IN HANDLE, IN ULONG,
IN KEY_VALUE_INFORMATION_CLASS,
OUT PVOID, IN ULONG, OUT PULONG );
NTSTATUS (*RealRegEnumerateKey)( IN HANDLE, IN ULONG,
IN KEY_INFORMATION_CLASS,
OUT PVOID, IN ULONG, OUT PULONG );
NTSTATUS (*RealRegSetValueKey)( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex, IN ULONG Type,
IN PVOID Data, IN ULONG DataSize );
NTSTATUS (*RealRegCreateKey)( OUT PHANDLE, IN ACCESS_MASK,
IN POBJECT_ATTRIBUTES , IN ULONG,
IN PUNICODE_STRING, IN ULONG, OUT PULONG );
NTSTATUS (*RealRegDeleteValueKey)( IN HANDLE, IN PUNICODE_STRING );
NTSTATUS (*RealRegCloseKey)( IN HANDLE );
NTSTATUS (*RealRegDeleteKey)( IN HANDLE );
NTSTATUS (*RealRegFlushKey)( IN HANDLE );
//
// Lenghs of rootkeys (filled in at init). This table allows us to translate
// path names into better-known forms. Current user is treated specially since
// its not a full match.
//
ROOTKEY CurrentUser[2] = {
{ "\\\\REGISTRY\\USER\\S", "HKCU", 0 },
{ "HKU\\S", "HKCU", 0 }
};
ROOTKEY RootKey[NUMROOTKEYS] = {
{ "\\\\REGISTRY\\USER", "HKU", 0 },
{ "\\\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT",
"HKCC", 0 },
{ "\\\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES", "HKCR", 0 },
{ "\\\\REGISTRY\\MACHINE", "HKLM", 0 }
};
//
// This is a hash table for keeping names around for quick lookup.
//
PHASH_ENTRY HashTable[NUMHASH];
//
// Mutex for hash table accesses
//
KMUTEX HashMutex;
//
// Data structure for storing messages we generate
//
PSTORE_BUF Store = NULL;
ULONG Sequence = 0;
KMUTEX StoreMutex;
//
// Maximum amount of data we will grab for buffered unread data
//
ULONG NumStore = 0;
ULONG MaxStore = MAXMEM/MAX_STORE;
//
// Free hash list. Note: we don't use lookaside lists since
// we want to be able to run on NT 3.51 - lookasides were
// introduced in NT 4.0
//
PHASH_ENTRY FreeHashList = NULL;
//======================================================================
// P A T T E R N M A T C H I N G R O U T I N E S
//======================================================================
//----------------------------------------------------------------------
//
// MatchOkay
//
// Only thing left after compare is more mask. This routine makes
// sure that its a valid wild card ending so that its really a match.
//
//----------------------------------------------------------------------
BOOLEAN MatchOkay( PCHAR Pattern )
{
//
// If pattern isn't empty, it must be a wildcard
//
if( *Pattern && *Pattern != '*' ) {
return FALSE;
}
//
// Matched
//
return TRUE;
}
//----------------------------------------------------------------------
//
// MatchWithPattern
//
// Performs nifty wildcard comparison.
//
//----------------------------------------------------------------------
BOOLEAN MatchWithPattern( PCHAR Pattern, PCHAR Name )
{
CHAR upcase;
//
// End of pattern?
//
if( !*Pattern ) {
return FALSE;
}
//
// If we hit a wild card, do recursion
//
if( *Pattern == '*' ) {
Pattern++;
while( *Name && *Pattern ) {
if( *Name >= 'a' && *Name <= 'z' )
upcase = *Name - 'a' + 'A';
else
upcase = *Name;
//
// See if this substring matches
//
if( *Pattern == upcase || *Name == '*' ) {
if( MatchWithPattern( Pattern+1, Name+1 )) {
return TRUE;
}
}
//
// Try the next substring
//
Name++;
}
//
// See if match condition was met
//
return MatchOkay( Pattern );
}
//
// Do straight compare until we hit a wild card
//
while( *Name && *Pattern != '*' ) {
if( *Name >= 'a' && *Name <= 'z' )
upcase = *Name - 'a' + 'A';
else
upcase = *Name;
if( *Pattern == upcase ) {
Pattern++;
Name++;
} else {
return FALSE;
}
}
//
// If not done, recurse
//
if( *Name ) {
return MatchWithPattern( Pattern, Name );
}
//
// Make sure its a match
//
return MatchOkay( Pattern );
}
//======================================================================
// B O O T L O G G I N G W O R K R O U T I N E S
//======================================================================
//----------------------------------------------------------------------
//
// RegmonOpenBootLog
//
// Open a log file.
//
//----------------------------------------------------------------------
NTSTATUS RegmonOpenBootLog()
{
WCHAR logFileNameBuffer[] = L"\\SystemRoot\\REGMON.LOG";
UNICODE_STRING logFileUnicodeString;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatus;
NTSTATUS ntStatus;
RtlInitUnicodeString( &logFileUnicodeString, logFileNameBuffer );
InitializeObjectAttributes( &objectAttributes, &logFileUnicodeString,
OBJ_CASE_INSENSITIVE, NULL, NULL );
ntStatus = ZwCreateFile( &LogFile, FILE_WRITE_DATA|SYNCHRONIZE,
&objectAttributes, &ioStatus, NULL,
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
return ntStatus;
}
//----------------------------------------------------------------------
//
// RegmonCloseBootLog - worker thread routine
//
// Close the boot log file.
//
//----------------------------------------------------------------------
VOID RegmonCloseBootLog( PVOID Context )
{
ZwClose( LogFile );
KeSetEvent( &LoggingEvent, 0, FALSE );
LogFile = INVALID_HANDLE_VALUE;
}
//----------------------------------------------------------------------
//
// RegmonWriteBuffer
//
// Dumps a buffer to the log file.
//
//----------------------------------------------------------------------
VOID RegmonWriteBuffer( PSTORE_BUF LogStore )
{
ULONG len;
ULONG itemcnt;
UCHAR seqtext[64];
static CHAR diskFullError[] = "Not enough disk space for log file\n";
PCHAR textptr, items[10];
PENTRY entry;
FILE_END_OF_FILE_INFORMATION zeroLengthFile;
IO_STATUS_BLOCK ioStatus;
//
// Process the buffer
//
for( entry = (PENTRY) LogStore->Data; entry < (PENTRY) ((PCHAR) LogStore + LogStore->Len); ) {
len = strlen( entry->text );
len += 4; len &= 0xFFFFFFFC;
//
// Write out the entry.
//
sprintf( seqtext, "%d: ", entry->seq );
ZwWriteFile( LogFile, NULL, NULL, NULL, &ioStatus,
seqtext, strlen(seqtext), NULL, NULL );
ZwWriteFile( LogFile, NULL, NULL, NULL, &ioStatus,
entry->text, strlen(entry->text), NULL, NULL );
ZwWriteFile( LogFile, NULL, NULL, NULL, &ioStatus,
"\n\r", strlen("\n\r"), NULL, NULL );
//
// If the disk is full, delete the log file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -