⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regsys.c

📁 一个完整的注册表监视器
💻 C
📖 第 1 页 / 共 5 页
字号:
        // and tell the user there wasn't enough room for it.
        //
        if( ioStatus.Status == STATUS_DISK_FULL ) {

            zeroLengthFile.EndOfFile.QuadPart = 0;
            ZwSetInformationFile( LogFile, &ioStatus, 
                                  &zeroLengthFile, sizeof(zeroLengthFile), FileEndOfFileInformation );
            ZwWriteFile( LogFile, NULL, NULL, NULL, &ioStatus,
                         diskFullError, strlen(diskFullError), NULL, NULL );
            ZwClose( LogFile );
            LogFile = INVALID_HANDLE_VALUE;
            BootLogging = FALSE;
            break;
        }
        entry = (PVOID) (entry->text + len);
    }
}


//----------------------------------------------------------------------
//
// RegmonWriteBootLog - worker thread routine
//
// Writes a buffer out to the log file. We do this in a worker routine
// because the log file handle, which we opened in DriverEntry, is
// only valid in the System process, and worker threads execute in 
// the system process. We are protected by the Store mutex while
// in this procedure, since we are called from NewStore, which 
// is called after the Store mutex is acquired.
//
// NOTE: When Regmon is configured to log activity during a boot it
// is marked to start as the very first driver in the boot sequence.
// Because the SystemRoot symbolic link is not initialized until
// all boot drivers have finished initializing, Regmon is not able
// to open a boot log until some point later. In order that we can
// capture all registry activity we store away output buffers on a list
// until we try and succeed at opening the boot log. When we can we
// send out the accumulated data and then begin dumping buffers
// as they are generated.
//
//----------------------------------------------------------------------
VOID RegmonWriteBootLog( PVOID Context )
{
    PSTORE_BUF  currentStore = Context;
    PSTORE_BUF  saveStore, curSaveStore;
    NTSTATUS    ntStatus;

    //
    // If boot logging is still on, but the log file hasn't been opened,
    // try to open it
    //
    if( BootLogging && LogFile == INVALID_HANDLE_VALUE ) {

        ntStatus = RegmonOpenBootLog();
        
        if( NT_SUCCESS( ntStatus )) {

            //
            // Finally! Process all the buffers we've saved away
            //
            curSaveStore = BootSavedStoreList;
            while( curSaveStore ) {

                RegmonWriteBuffer( curSaveStore );
                BootSavedStoreList = curSaveStore->Next;
                ExFreePool( curSaveStore );
                curSaveStore = BootSavedStoreList;
            }
        }
    }
    
    //
    // Either write out the current buffer or save it away to
    // write out later
    //
    if( LogFile != INVALID_HANDLE_VALUE ) {

        RegmonWriteBuffer( currentStore );

    } else {

        //
        // Save this buffer away until we can successfully open
        // the log file and write it out to disk
        //
        saveStore = ExAllocatePool( PagedPool, sizeof(*saveStore));
        memcpy( saveStore, currentStore, sizeof(*saveStore) );
        saveStore->Next = NULL;
        if( BootSavedStoreList ) {

            BootSavedStoreTail->Next = saveStore;
            BootSavedStoreTail = saveStore;

        } else {
            
            BootSavedStoreList = saveStore;
            BootSavedStoreTail = saveStore;
        }
    }

    //
    // Signal the event
    //
    KeSetEvent( &LoggingEvent, 0, FALSE );
}


//======================================================================
//                   B U F F E R  R O U T I N E S 
//======================================================================

//----------------------------------------------------------------------
//
// RegmonFreeStore
//
// Frees all the data output buffers that we have currently allocated.
//
//----------------------------------------------------------------------
VOID RegmonFreeStore()
{
    PSTORE_BUF      next;
    
    while( Store ) {
        next = Store->Next;
        ExFreePool( Store );
        Store = next;
    }
}       


//----------------------------------------------------------------------
//
// RegmonNewStore
//
// Called when the current buffer has filled up. This moves us to the
// pre-allocated buffer and then allocates another buffer.
//
//----------------------------------------------------------------------
void RegmonNewStore( void )
{
    PSTORE_BUF prev = Store, newstore;
    WORK_QUEUE_ITEM  workItem;

    //
    // If we're boot logging, write the current store out to disk
    //
    if( BootLogging ) {

        ExInitializeWorkItem( &workItem, RegmonWriteBootLog, Store );
        ExQueueWorkItem( &workItem, CriticalWorkQueue );
        KeWaitForSingleObject( &LoggingEvent, Executive, KernelMode, FALSE, NULL );
    }

    //
    // If we have maxed out or haven't accessed the current store
    // just return
    //
    if( MaxStore == NumStore ) {
        Store->Len = 0;
        return; 
    }

    //
    // See if we can re-use a store
    //
    if( !Store->Len ) {

        return;
    }

    //
    // Move to the next buffer and allocate another one
    //
    newstore = ExAllocatePool( PagedPool, sizeof(*Store) );
    if( newstore ) { 

        Store   = newstore;
        Store->Len  = 0;
        Store->Next = prev;
        NumStore++;

    } else {

        Store->Len = 0;

    }
}


//----------------------------------------------------------------------
//
// RegmonOldestStore
//
// Goes through the linked list of storage buffers and returns the 
// oldest one.
//
//----------------------------------------------------------------------
PSTORE_BUF RegmonOldestStore( void )
{
    PSTORE_BUF  ptr = Store, prev = NULL;

    while ( ptr->Next ) {

        ptr = (prev = ptr)->Next;
    }
    if ( prev ) {

        prev->Next = NULL;    
    }
    NumStore--;
    return ptr;
}


//----------------------------------------------------------------------
//
// RegmonResetStore
//
// When a GUI is no longer communicating with us, but we can't unload,
// we reset the storage buffers.
//
//----------------------------------------------------------------------
VOID RegmonResetStore()
{
    PSTORE_BUF  current, next;

    MUTEX_WAIT( StoreMutex );

    //
    // Traverse the list of output buffers
    //
    current = Store->Next;
    while( current ) {

        //
        // Free the buffer
        //
        next = current->Next;
        ExFreePool( current );
        current = next;
    }

    // 
    // Move the output pointer in the buffer that's being kept
    // the start of the buffer.
    // 
    Store->Len = 0;
    Store->Next = NULL;

    MUTEX_RELEASE( StoreMutex );
}



//----------------------------------------------------------------------
//
// UpdateStore
//
// Add a new string to Store, if it fits. 
//
//----------------------------------------------------------------------
void UpdateStore( const char * format, ... )
{       
    PENTRY          Entry;
    ULONG           len;
    va_list         arg_ptr;
    static CHAR     text[MAXPATHLEN*2];

#define A (&format)
    DbgPrint(( (char *)format, A[1], A[2], A[3], A[4], A[5], A[6] ));
    DbgPrint(( "\n" ));
#undef A

    //
    // only do this if a GUI is active
    //
    if( !GUIActive ) return;

    //
    // Lock the buffer pool
    //
    MUTEX_WAIT( StoreMutex );

    //
    // Get a sequence numnber
    //
    InterlockedIncrement( &Sequence );

    //
    // Sprint the string to get the length
    //
    va_start( arg_ptr, format );
    len = vsprintf( text, format, arg_ptr );
    va_end( arg_ptr );    
	len += 4; len &=  0xFFFFFFFC; // +1 to include null terminator and +3 to allign on longword

    //
    // See if its time to switch to extra buffer
    //
    if ( Store->Len + len + sizeof(ENTRY) + 1 >= MAX_STORE ) {

        RegmonNewStore();
    }

    //
    // Store the sequence number so that 
    // a call's result can be paired with its
    // initial data collected when it was made.
    //
    Entry = (void *)(Store->Data+Store->Len);
    Entry->seq = Sequence;
    memcpy( Entry->text, text, len );
    Store->Len += sizeof(Entry->seq)+len;

    //
    // Release the buffer pool
    //
    MUTEX_RELEASE( StoreMutex );
}


//----------------------------------------------------------------------
// 
// strncatZ
//
// Appends a string to another and attaches a null. NT 3.51 ntoskrnl
// does not export this function so we have to make our own, and give
// it a name that won't conflict with the strncat that NT 4.0 exports.
//
//----------------------------------------------------------------------
PCHAR strncatZ( PCHAR dest, PCHAR source, int length )
{       
    int     origlen = strlen(dest);

    strncpy( dest+origlen, source, length );
    dest[ origlen+length ] = 0;
    return(dest);
}

//======================================================================
//                   H A S H  R O U T I N E S 
//======================================================================

//----------------------------------------------------------------------
//
// RegmonHashCleanup
//
// Called when we are unloading to free any memory that we have 
// in our possession.
//
//----------------------------------------------------------------------
VOID RegmonHashCleanup()
{
    PHASH_ENTRY             hashEntry, nextEntry;
    ULONG                   i;

    MUTEX_WAIT( HashMutex );    

    //
    // First free the hash table entries
    //       
    for( i = 0; i < NUMHASH; i++ ) {
        hashEntry = HashTable[i];
        while( hashEntry ) {
            nextEntry = hashEntry->Next;
            ExFreePool( hashEntry->FullPathName );
            ExFreePool( hashEntry );
            hashEntry = nextEntry;
        }
    }
    
    hashEntry = FreeHashList;
    while( hashEntry ) {
        nextEntry = hashEntry->Next;
        ExFreePool( hashEntry );
        hashEntry = nextEntry;
    }
    MUTEX_RELEASE( HashMutex );
}

//----------------------------------------------------------------------
//
// RegmonStoreHash
//
// Stores the key and associated fullpath in the hash table.
//
//----------------------------------------------------------------------
VOID RegmonStoreHash( POBJECT object, PCHAR fullname )
{
    PHASH_ENTRY     newEntry;

    MUTEX_WAIT( HashMutex );

    if( FreeHashList ) {

        newEntry = FreeHashList;
        FreeHashList = newEntry->Next;

    } else {

        newEntry = ExAllocatePool( PagedPool, sizeof(HASH_ENTRY));
    }

    newEntry->Object                = object;
    newEntry->FullPathName          = ExAllocatePool( PagedPool, strlen(fullname)+1 );
    newEntry->Next                  = HashTable[ HASHOBJECT( object) ];
    HashTable[ HASHOBJECT(object) ] = newEntry;     
    strcpy( newEntry->FullPathName, fullname );

    MUTEX_RELEASE( HashMutex );
}


//----------------------------------------------------------------------
//
// RegmonFreeHashEntry
//
// When we see a key close, we can free the string we had associated
// with the fileobject being closed since we know it won't be used

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -