// // Note: This code has bugs. Please don't actually try this at home! // NTSTATUS NTAPI BuggyDriverNtCreateSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PLARGE_INTEGER SectionSize OPTIONAL, IN ULONG Protect, IN ULONG Attributes, IN HANDLE FileHandle ) { NTSTATUS Status; HANDLE Section; SECTION_IMAGE_INFORMATION ImageInfo; ULONG ReturnLength; PVOID SectionObject; PVOID FileObject; BOOLEAN SavedSectionObject; HANDLE SectionKernelHandle; LARGE_INTEGER LocalSectionSize; SavedSectionObject = FALSE; // // Let's call the original NtCreateSection, as we only care about successful // calls with valid parameters. // Status = RealNtCreateSection( SectionHandle, DesiredAccess, ObjectAttributes, SectionSize, Protect, Attributes, FileHandle ); // // Failed? We'll bail out now. // if (!NT_SUCCESS( Status )) return Status; // // Okay, we've got a successful call made, let's do our work. // First, capture the returned section handle. Note that we do not need to // do a probe as that was already done by NtCreateSection, but we still do // need to use SEH. // __try { Section = *SectionHandle; } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = (NTSTATUS)GetExceptionCode(); } // // The user unmapped our buffer, let's bail out. // if (!NT_SUCCESS( Status )) return Status; // // We need a pointer to the section object for our work. Let's grab it now. // Status = ObReferenceObjectByHandle( Section, 0, NULL, KernelMode, &SectionObject, NULL ); if (!NT_SUCCESS( Status )) return Status; // // Just for fun, let's check if the section was an image section, and if so, // we'll do special work there. // Status = ZwQuerySection( Section, SectionImageInformation, &ImageInfo, sizeof( SECTION_IMAGE_INFORMATION ), &ReturnLength ); // // If we are an image section, then let's save away a pointer to to the // section object for our own use later. // if (NT_SUCCESS(Status)) { // // Save pointer away for something that we might do with it later. We might // want to care about the section image information for some unspecified // reason, so we will copy that and save it in our tracking list. For // example, maybe we want to map a view of the section into the initial // system process from a worker thread. // Status = SaveImageSectionObjectInList( SectionObject, &ImageInfo ); if (!NT_SUCCESS( Status )) { ObDereferenceObject( SectionObject ); return Status; } SavedSectionObject = TRUE; } // // Let's also grab a kernel handle for the file object so that we can do some // sort of work with it later on. // Status = ObReferenceObjectByHandle( Section, 0, NULL, KernelMode, &FileObject, NULL ); if (!NT_SUCCESS( Status )) { if (SavedSectionObject) DeleteImageSectionObjectInList( SectionObject ); ObDereferenceObject( SectionObject ); return Status; } // // Save the file object away, as well as maximum size of the section object. // We need the size of the section object for a length check when accessing // the section later. // if (SectionSize) { __try { LocalSectionSize = *SectionSize; } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = (NTSTATUS)GetExceptionCode(); ObDereferenceObject( FileObject ); if (SavedSectionObject) DeleteImageSectionObjectInList( SectionObject ); ObDereferenceObject( SectionObject ); return Status; } } else { // // Ask the file object for it's length, this could be done by any of the // usual means to do that. // Status = QueryAllocationLengthFromFileObject( FileObject, &LocalSectionSize ); if (!NT_SUCCESS( Status )) { ObDereferenceObject( FileObject ); if (SavedSectionObject) DeleteImageSectionObjectInList( SectionObject ); ObDereferenceObject( SectionObject ); return Status; } } // // Save the file object + section object + section length away for future // reference. // Status = SaveSectionFileInfoInList( FileObject, SectionObject, &LocalSectionSize ); if (!NT_SUCCESS( Status )) { ObDereferenceObject( FileObject ); if (SavedSectionObject) DeleteImageSectionObjectInList( SectionObject ); ObDereferenceObject( SectionObject ); return Status; } // // All done. Lose our references now. Assume that the Save*InList routines // took their own references on the objects in question. Return to the caller // successfully. // ObDereferenceObject( FileObject ); ObDereferenceObject( SectionObject ); return STATUS_SUCCESS; }