📄 filemon.c
字号:
// Look-up the entry
//
hashEntry = HashTable[ HASHOBJECT( fileObject ) ];
prevEntry = NULL;
while( hashEntry && hashEntry->FileObject != fileObject ) {
prevEntry = hashEntry;
hashEntry = hashEntry->Next;
}
//
// If we fall of the hash list without finding what we're looking
// for, just return.
//
if( !hashEntry ) {
KeReleaseSpinLock( &HashMutex, oldirql );
return;
}
//
// Got it! Remove it from the list
//
if( prevEntry ) {
prevEntry->Next = hashEntry->Next;
} else {
HashTable[ HASHOBJECT( fileObject )] = hashEntry->Next;
}
//
// Free the memory associated with the name of the free entry.
//
MemFreePool( hashEntry->FullPathName );
MemFreeToNPagedLookasideList( &HashLookaside, hashEntry );
KeReleaseSpinLock( &HashMutex, oldirql );
}
//----------------------------------------------------------------------
// P A T H A N D P R O C E S S N A M E R O U T I N E S
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// FilemonFreeFilters
//
// Fress storage we allocated for filter strings.
//
//----------------------------------------------------------------------
VOID FilemonFreeFilters()
{
ULONG i;
for( i = 0; i < NumProcessFilters; i++ ) {
MemFreePool( ProcessFilters[i] );
}
for( i = 0; i < NumProcessExcludeFilters; i++ ) {
MemFreePool( ProcessExcludeFilters[i] );
}
for( i = 0; i < NumPathIncludeFilters; i++ ) {
MemFreePool( PathIncludeFilters[i] );
}
for( i = 0; i < NumPathExcludeFilters; i++ ) {
MemFreePool( PathExcludeFilters[i] );
}
NumProcessFilters = 0;
NumProcessExcludeFilters = 0;
NumPathIncludeFilters = 0;
NumPathExcludeFilters = 0;
}
//----------------------------------------------------------------------
//
// MakeFilterArray
//
// Takes a filter string and splits into components (a component
// is seperated with a ';')
//
//----------------------------------------------------------------------
VOID MakeFilterArray( PCHAR FilterString,
PCHAR FilterArray[],
PULONG NumFilters )
{
PCHAR filterStart;
ULONG filterLength;
//
// Scan through the process filters
//
filterStart = FilterString;
while( *filterStart ) {
filterLength = 0;
while( filterStart[filterLength] &&
filterStart[filterLength] != ';' ) {
filterLength++;
}
//
// Ignore zero-length components
//
if( filterLength ) {
FilterArray[ *NumFilters ] =
MemAllocatePool( NonPagedPool, filterLength + 1 );
strncpy( FilterArray[ *NumFilters ],
filterStart, filterLength );
FilterArray[ *NumFilters ][filterLength] = 0;
(*NumFilters)++;
}
//
// Are we done?
//
if( !filterStart[filterLength] ) break;
//
// Move to the next component (skip over ';')
//
filterStart += filterLength + 1;
}
}
//----------------------------------------------------------------------
//
// FilemonUpdateFilters
//
// Takes a new filter specification and updates the filter
// arrays with them.
//
//----------------------------------------------------------------------
VOID FilemonUpdateFilters()
{
KIRQL oldirql;
//
// Free old filters (if any)
//
KeAcquireSpinLock( &FilterMutex, &oldirql );
FilemonFreeFilters();
//
// Create new filter arrays
//
MakeFilterArray( FilterDef.processfilter,
ProcessFilters, &NumProcessFilters );
MakeFilterArray( FilterDef.excludeprocess,
ProcessExcludeFilters, &NumProcessExcludeFilters );
MakeFilterArray( FilterDef.pathfilter,
PathIncludeFilters, &NumPathIncludeFilters );
MakeFilterArray( FilterDef.excludefilter,
PathExcludeFilters, &NumPathExcludeFilters );
KeReleaseSpinLock( &FilterMutex, oldirql );
}
//----------------------------------------------------------------------
//
// ApplyNameFilter
//
// If the name matches the exclusion mask, we do not log it. Else if
// it doesn't match the inclusion mask we do not log it.
//
//----------------------------------------------------------------------
BOOLEAN ApplyNameFilter( PCHAR fullname )
{
ULONG i;
KIRQL oldirql;
//
// If no GUI or no filename return FALSE
//
if ( !fullname ) return FALSE;
//
// If it matches the exclusion string, do not log it
//
KeAcquireSpinLock( &FilterMutex, &oldirql );
for( i = 0; i < NumPathExcludeFilters; i++ ) {
if( MatchWithPattern( PathExcludeFilters[i], fullname ) ) {
KeReleaseSpinLock( &FilterMutex, oldirql );
return FALSE;
}
}
//
// If it matches an include filter then log it
//
for( i = 0; i < NumPathIncludeFilters; i++ ) {
if( MatchWithPattern( PathIncludeFilters[i], fullname )) {
KeReleaseSpinLock( &FilterMutex, oldirql );
return TRUE;
}
}
//
// It didn't match any include filters so don't log
//
KeReleaseSpinLock( &FilterMutex, oldirql );
return FALSE;
}
//----------------------------------------------------------------------
//
// FilemonGetFullPath
//
// Takes a fileobject and filename and returns a canonical path,
// nicely formatted, in fullpathname.
//
//----------------------------------------------------------------------
VOID FilemonGetFullPath( PFILE_OBJECT fileObject, PHOOK_EXTENSION hookExt,
PCHAR fullPathName )
{
ULONG pathLen;
PCHAR pathOffset;
PFILE_OBJECT relatedFileObject;
PHASH_ENTRY hashEntry, newEntry;
ANSI_STRING componentName;
KIRQL oldirql;
//
// Only do this if a GUI is active and filtering is on
//
if( !FilterOn || !hookExt || !fullPathName) {
fullPathName[0] = 0;
return;
}
//
// First, lookup the object in the hash table to see if a name
// has already been generated for it
//
KeAcquireSpinLock( &HashMutex, &oldirql );
hashEntry = HashTable[ HASHOBJECT( fileObject ) ];
while( hashEntry && hashEntry->FileObject != fileObject ) {
hashEntry = hashEntry->Next;
}
//
// Did we find an entry?
//
if( hashEntry ) {
//
// Yes, so get the name from the entry.
//
strcpy( fullPathName, hashEntry->FullPathName );
KeReleaseSpinLock( &HashMutex, oldirql );
return;
}
KeReleaseSpinLock( &HashMutex, oldirql );
//
// We didn't find the name in the hash table, so we have to attempt
// to construct it from the file objects. Note that we won't always
// be able to successfully do this, because the file system may
// deallocate the name in the file object at its discretion.
//
//
// Is it DASD (Volume) I/O?
//
if( !fileObject || !fileObject->FileName.Length || fileObject->FileName.Length > 2*MAXPATHLEN ) {
sprintf( fullPathName, "%C: DASD", hookExt->LogicalDrive );
return;
}
//
// Do this in an exception handling block, in case of mangled names in the
// file object
//
try {
//
// Now, create the full path name. First, calculate the length taking into
// account space for seperators and the leading drive letter plus ':'
//
pathLen = fileObject->FileName.Length/2 + 2;
relatedFileObject = fileObject->RelatedFileObject;
//
// Only look at related file object if this is a relative name
//
if( fileObject->FileName.Buffer[0] != L'\\' ) {
while( relatedFileObject ) {
//
// If its too long, just stop.
//
if( pathLen + relatedFileObject->FileName.Length/2+1 >= MAXPATHLEN ) {
break;
}
pathLen += relatedFileObject->FileName.Length/2+1;
relatedFileObject = relatedFileObject->RelatedFileObject;
}
}
//
// Add the drive letter first at the front of the name
//
sprintf( fullPathName, "%C:", hookExt->LogicalDrive );
//
// Now, start at the end and work back to the beginning of the path
//
pathOffset = fullPathName + pathLen - fileObject->FileName.Length/2;
RtlUnicodeStringToAnsiString( &componentName, &fileObject->FileName, TRUE );
strncpy( pathOffset, componentName.Buffer, componentName.Length + 1 );
RtlFreeAnsiString( &componentName );
relatedFileObject = fileObject->RelatedFileObject;
if( fileObject->FileName.Buffer[0] != L'\\' ) {
while( relatedFileObject ) {
*(pathOffset - 1) = '\\';
pathOffset -= relatedFileObject->FileName.Length/2 + 1;
//
// Bail when we've maxed the string.
//
if( pathOffset <= fullPathName ) {
break;
}
RtlUnicodeStringToAnsiString( &componentName,
&relatedFileObject->FileName, TRUE );
strncpy( pathOffset, componentName.Buffer,
componentName.Length );
RtlFreeAnsiString( &componentName );
relatedFileObject = relatedFileObject->RelatedFileObject;
}
}
//
// If we added two '\' to the front because there was a relative file object
// that specified the root directory, remove one
//
if( pathLen > 3 && fullPathName[2] == '\\' && fullPathName[3] == '\\' ) {
strcpy( fullPathName + 2, fullPathName + 3 );
}
//
// If its a network drive, take off the first drive letter. This is because
// network drives share a common device objects and the names are fully formed to
// specify the network mounted drive letter already
//
if( pathLen > 5 && fullPathName[4] == ':' && fullPathName[5] == '\\') {
strcpy( fullPathName, fullPathName + 3 );
}
} except( EXCEPTION_EXECUTE_HANDLER ) {
//
// No name available - go with a dummy name
//
sprintf( fullPathName, "%C: ???", hookExt->LogicalDrive );
}
//
// Now that we have a name associated with the file object, put the
// association in a hash table
//
KeAcquireSpinLock( &HashMutex, &oldirql );
//
// Allocate a hash entry
//
newEntry = MemAllocateFromNPagedLookasideList( &HashLookaside );
//
// If no memory for a new entry, oh well.
//
if( newEntry ) {
//
// Fill in the new entry and put it in the hash table
//
newEntry->FileObject = fileObject;
newEntry->FullPathName = MemAllocatePool( NonPagedPool, strlen(fullPathName)+1);
//
// Make sure there was memory for the name
//
if( !newEntry->FullPathName ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -