NTSTATUS
PsReferenceProcessFilePointer (
IN PEPROCESS Process,
OUT PVOID *OutFileObject
)
/*++
Routine Description:
This routine returns a referenced pointer to the FilePointer of Process.
This is a rundown protected wrapper around MmGetFileObjectForSection.
Arguments:
Process - Supplies the process to query.
OutFileObject - Returns the file object backing the requested section if
success is returned.
Return Value:
NTSTATUS.
Environment:
Kernel mode, PASSIVE_LEVEL.
--*/
{
PFILE_OBJECT FileObject;
PAGED_CODE();
if (!ExAcquireRundownProtection (&Process->RundownProtect)) {
return STATUS_UNSUCCESSFUL;
}
if (Process->SectionObject == NULL) {
ExReleaseRundownProtection (&Process->RundownProtect);
return STATUS_UNSUCCESSFUL;
}
FileObject = MmGetFileObjectForSection ((PVOID)Process->SectionObject);
*OutFileObject = FileObject;
ObReferenceObject (FileObject);
ExReleaseRundownProtection (&Process->RundownProtect);
return STATUS_SUCCESS;
}
NTSTATUS
SeInitializeProcessAuditName (
__in __typefix(PFILE_OBJECT) PVOID FileObject,
__in BOOLEAN bIgnoreAuditPolicy,
__deref_out POBJECT_NAME_INFORMATION *pAuditName
)
/*++
Routine Description:
This routine initializes the executable name for auditing purposes. It allocates memory for the
image file name. This memory is pointed to by pAuditName.
Arguments:
FileObject - Supplies a pointer to a file object for the image being
executed.
bIgnoreAuditPolicy - boolean that indicates that the call should proceed without
regard to the system's auditing policy.
pAuditName - Supplies a pointer to a pointer for the object name information.
Return value:
NTSTATUS.
Environment:
KeAttached to the target process so not all system services are available.
--*/
{
NTSTATUS Status;
OBJECT_NAME_INFORMATION TempNameInfo;
ULONG ObjectNameInformationLength;
POBJECT_NAME_INFORMATION pInternalAuditName;
PFILE_OBJECT FilePointer;
PAGED_CODE();
ASSERT (pAuditName != NULL);
*pAuditName = NULL;
//
// Check if the caller would like to get the process name, even if auditing does not
// require it.
//
if (FALSE == bIgnoreAuditPolicy) {
//
// At the time of process creation, this routine should only proceed when Object Access or
// Detailed Tracking auditing is enabled. In all other cases, the process name is acquired
// when it is requested.
//
if (!SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) &&
!SepAdtAuditThisEventWithContext( AuditCategoryDetailedTracking, TRUE, FALSE, NULL )) {
return STATUS_SUCCESS;
}
}
FilePointer = (PFILE_OBJECT) FileObject;
//
// Compute full path for imagefile.
// This first call to ObQueryNameString is guaranteed to fail.
// The ObjectNameInformationLength contains only a
// UNICODE_STRING, so if this call succeeded it would indicate
// an imagefile name of length 0. That is bad, so all return
// values except STATUS_BUFFER_OVERFLOW (from NTFS) and
// STATUS_BUFFER_TOO_SMALL (from DFS). This call gives
// me the buffer size that I need to store the image name.
//
pInternalAuditName = &TempNameInfo;
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
Status = ObQueryNameString (FilePointer,
pInternalAuditName,
ObjectNameInformationLength,
&ObjectNameInformationLength);
if ((Status == STATUS_BUFFER_OVERFLOW) ||
(Status == STATUS_BUFFER_TOO_SMALL)) {
//
// Sanity check ObQueryNameString. Different filesystems
// may be buggy, so make sure that the return length makes
// sense (that it has room for a non-NULL Buffer in the
// UNICODE_STRING).
//
if (ObjectNameInformationLength > sizeof(OBJECT_NAME_INFORMATION)) {
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
ObjectNameInformationLength,
'aPeS');
if (pInternalAuditName != NULL) {
Status = ObQueryNameString (FilePointer,
pInternalAuditName,
ObjectNameInformationLength,
&ObjectNameInformationLength);
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("/n** ObqueryNameString failed with 0x%x./n", Status);
#endif //DBG
//
// If the second call to ObQueryNameString did not succeed, then
// something is very wrong. Set the image name to NULL string.
//
// Free the memory that the first call to ObQueryNameString requested,
// and allocate enough space to store an empty UNICODE_STRING.
//
ExFreePool (pInternalAuditName);
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
ObjectNameInformationLength,
'aPeS');
if (pInternalAuditName != NULL) {
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
//
// Status = STATUS_SUCCESS to allow the process creation to continue.
//
Status = STATUS_SUCCESS;
} else {
Status = STATUS_NO_MEMORY;
}
}
} else {
Status = STATUS_NO_MEMORY;
}
} else {
//
// If this happens, then ObQueryNameString is broken for the FS on which
// it was called.
//
#if DBG
DbgPrint("/n** ObqueryNameString failed with 0x%x./n", Status);
#endif //DBG
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
ObjectNameInformationLength,
'aPeS');
if (pInternalAuditName != NULL) {
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
//
// Status = STATUS_SUCCESS to allow the process creation to continue.
//
Status = STATUS_SUCCESS;
} else {
Status = STATUS_NO_MEMORY;
}
}
} else {
//
// If ObQueryNameString returns some other error code, we cannot
// be certain of which action to take, or whether it has properly
// set the ReturnLength. For example, ObQueryNameString has slightly
// different semantics under DFS than NTFS. Additionally, 3rd
// party file systems may also behave unpredictably. For these reasons,
// in the case of an unexpected error code from ObQueryNameString
// we set AuditName to zero length unicode string and allow process
// creation to continue.
//
#if DBG
DbgPrint("/n** ObqueryNameString failed with 0x%x./n", Status);
#endif //DBG
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
pInternalAuditName = ExAllocatePoolWithTag(NonPagedPool, ObjectNameInformationLength, 'aPeS');
if (pInternalAuditName != NULL) {
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
//
// Status = STATUS_SUCCESS to allow the process creation to continue.
//
Status = STATUS_SUCCESS;
} else {
Status = STATUS_NO_MEMORY;
}
}
*pAuditName = pInternalAuditName;
return Status;
}
NTSTATUS
SeLocateProcessImageName(
__in PEPROCESS Process,
__deref_out PUNICODE_STRING *pImageFileName
)
/*++
Routine Description
This routine returns the ImageFileName information from the process, if available. This is a "lazy evaluation" wrapper
around SeInitializeProcessAuditName. If the image file name information has already been computed, then this call simply
allocates and returns a UNICODE_STRING with this information. Otherwise, the function determines the name, stores the name in the
EPROCESS structure, and then allocates and returns a UNICODE_STRING. Caller must free the memory returned in pImageFileName.
Arguments
Process - process for which to acquire the name
pImageFileName - output parameter to return name to caller
Return Value
NTSTATUS.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID FilePointer = NULL;
PVOID PreviousValue = NULL;
POBJECT_NAME_INFORMATION pProcessImageName = NULL;
PUNICODE_STRING pTempUS = NULL;
ULONG NameLength = 0;
PAGED_CODE();
*pImageFileName = NULL;
if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
//
// The name has not been predetermined. We must determine the process name. First, reference the
// PFILE_OBJECT and lookup the name. Then again check the process image name pointer against NULL.
// Finally, set the name.
//
Status = PsReferenceProcessFilePointer( Process, &FilePointer );
if (NT_SUCCESS(Status)) {
//
// Get the process name information.
//
Status = SeInitializeProcessAuditName(
FilePointer,
TRUE, // skip audit policy
&pProcessImageName // to be allocated in nonpaged pool
);
if (NT_SUCCESS(Status)) {
//
// Only use the pProcessImageName if the field in the process is currently NULL.
//
PreviousValue = InterlockedCompareExchangePointer(
(PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
(PVOID) pProcessImageName,
(PVOID) NULL
);
if (NULL != PreviousValue) {
ExFreePool(pProcessImageName); // free what we caused to be allocated.
}
}
ObDereferenceObject( FilePointer );
}
}
if (NT_SUCCESS(Status)) {
//
// Allocate space for a buffer to contain the name for returning to the caller.
//
NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
if (NULL != pTempUS) {
RtlCopyMemory(
pTempUS,
&Process->SeAuditProcessCreationInfo.ImageFileName->Name,
NameLength
);
pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
*pImageFileName = pTempUS;
} else {
Status = STATUS_NO_MEMORY;
}
}
return Status;
}
获得进程映像文件 (中)
最新推荐文章于 2023-06-23 17:07:34 发布