阅读:4216回复:9
原来MmFlushImageSection函数居然如此简单!
今天看了RootKit上一篇vardyh的文章后,俺好奇地反汇编了一下MmFlushImageSection函数,发现这个函数居然出奇地简单,虽然绕过来绕过去,最终却只是检查了pSectionObjectPointer->ImageSectionObject和pSectionObjectPointer->DataSectionObject两变量值,如为零则返回TRUE,否则返回FALSE。这就意味着MJ的那个粉碎机只需要再多加几行代码,将这两个变量清零,就可以删除正在运行的文件,这可比HOOK这个函数简单方便多了。
(注:vardyt自己构造了一个三个变量值全为0的SectionObjectPointer结构来替换将被删除文件对象,效果一样,但是俺认为没有必要去动的数据就不要去动,这样心理上保险一些) BOOLEAN SKillDeleteFile( IN HANDLE FileHandle ) { NTSTATUS ntStatus = STATUS_SUCCESS; PFILE_OBJECT fileObject; PDEVICE_OBJECT DeviceObject; PIRP Irp; KEVENT event; FILE_DISPOSITION_INFORMATION FileInformation; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; PSECTION_OBJECT_POINTERS pSectionObjectPointer; ntStatus = ObReferenceObjectByHandle(FileHandle, DELETE, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(ntStatus)) { return FALSE; } DeviceObject = IoGetRelatedDeviceObject(fileObject); Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); if (Irp == NULL) { ObDereferenceObject(fileObject); return FALSE; } KeInitializeEvent(&event, SynchronizationEvent, FALSE); FileInformation.DeleteFile = TRUE; Irp->AssociatedIrp.SystemBuffer = &FileInformation; Irp->UserEvent = &event; Irp->UserIosb = &ioStatus; Irp->Tail.Overlay.OriginalFileObject = fileObject; Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); Irp->RequestorMode = KernelMode; irpSp = IoGetNextIrpStackLocation(Irp); irpSp->MajorFunction = IRP_MJ_SET_INFORMATION; irpSp->DeviceObject = DeviceObject; irpSp->FileObject = fileObject; irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION); irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation; irpSp->Parameters.SetFile.FileObject = fileObject; IoSetCompletionRoutine( Irp, SkillSetFileCompletion, &event, TRUE, TRUE, TRUE); //再加上下面这三行代码。 pSectionObjectPointer = fileObject->SectionObjectPointer; pSectionObjectPointer->ImageSectionObject = 0; pSectionObjectPointer->DataSectionObject = 0; IoCallDriver(DeviceObject, Irp); KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); ObDereferenceObject(fileObject); return TRUE; } |
|
最新喜欢:linshi... |
沙发#
发布于:2007-08-16 15:12
其实是没什么区别的
但是HOOK不用管那些内部结构怎么变,但是直接DKOM,万一结构一变,就挂了 :) 而且据说经Flower同学验证,这样的DKOM不一定成功 原因请见MmFlushImageSection的源代码: BOOLEAN MmFlushImageSection ( __in PSECTION_OBJECT_POINTERS SectionPointer, __in MMFLUSH_TYPE FlushType ) /*++ Routine Description: This function determines if any views of the specified image section are mapped, and if not, flushes valid pages (even modified ones) from the specified section and returns any used pages to the free list. This is accomplished by examining the prototype PTEs from the specified offset to the end of the section, and if any prototype PTEs are in the transition state, putting the prototype PTE back into its original state and putting the physical page on the free list. Arguments: SectionPointer - Supplies a pointer to a section object pointers within the FCB. FlushType - Supplies the type of flush to check for. One of MmFlushForDelete or MmFlushForWrite. Return Value: Returns TRUE if either no section exists for the file object or the section is not mapped and the purge was done, FALSE otherwise. --*/ { PLIST_ENTRY Next; PCONTROL_AREA ControlArea; PLARGE_CONTROL_AREA LargeControlArea; KIRQL OldIrql; LOGICAL state; if (FlushType == MmFlushForDelete) { // // Do a quick check to see if there are any mapped views for // the data section. If so, just return FALSE. // LOCK_PFN (OldIrql); ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject); if (ControlArea != NULL) { if ((ControlArea->NumberOfUserReferences != 0) || (ControlArea->u.Flags.BeingCreated)) { UNLOCK_PFN (OldIrql); return FALSE; } } UNLOCK_PFN (OldIrql); } // // Check the status of the control area. If the control area is in use // or the control area is being deleted, this operation cannot continue. // state = MiCheckControlAreaStatus (CheckImageSection, SectionPointer, FALSE, &ControlArea, &OldIrql); if (ControlArea == NULL) { return (BOOLEAN) state; } // // PFN LOCK IS NOW HELD! // // // Repeat until there are no more control areas - multiple control areas // for the same image section occur to support user global DLLs - these DLLs // require data that is shared within a session but not across sessions. // Note this can only happen for Hydra. // do { // // Set the being deleted flag and up the number of mapped views // for the segment. Upping the number of mapped views prevents // the segment from being deleted and passed to the deletion thread // while we are forcing a delete. // ControlArea->u.Flags.BeingDeleted = 1; ControlArea->NumberOfMappedViews = 1; LargeControlArea = NULL; if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { NOTHING; } else if (IsListEmpty(&((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList)) { ASSERT (ControlArea == (PCONTROL_AREA)SectionPointer->ImageSectionObject); } else { // // Check if there's only one image section in this control area, so // we don't reference the section object pointers as the // MiCleanSection call may result in its deletion. // // // There are multiple control areas, bump the reference count // on one of them (doesn't matter which one) so that it can't // go away. This ensures the section object pointers will stick // around even after the calls below so we can safely reloop to // flush any other remaining control areas. // ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 1); Next = ((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList.Flink; LargeControlArea = CONTAINING_RECORD (Next, LARGE_CONTROL_AREA, UserGlobalList); ASSERT (LargeControlArea->u.Flags.GlobalOnlyPerSession == 1); LargeControlArea->NumberOfSectionReferences += 1; } // // This is a page file backed or image segment. The segment is being // deleted, remove all references to the paging file and physical // memory. // UNLOCK_PFN (OldIrql); MiCleanSection (ControlArea, TRUE); // // Get the next Hydra control area. // if (LargeControlArea != NULL) { state = MiCheckControlAreaStatus (CheckImageSection, SectionPointer, FALSE, &ControlArea, &OldIrql); if (!ControlArea) { LOCK_PFN (OldIrql); LargeControlArea->NumberOfSectionReferences -= 1; MiCheckControlArea ((PCONTROL_AREA)LargeControlArea, OldIrql); } else { LargeControlArea->NumberOfSectionReferences -= 1; MiCheckControlArea ((PCONTROL_AREA)LargeControlArea, OldIrql); LOCK_PFN (OldIrql); } } else { state = TRUE; break; } } while (ControlArea); return (BOOLEAN) state; } |
|
|
驱动小牛
|
板凳#
发布于:2007-08-16 18:06
MJ从哪里整的这么多源代码???
|
地板#
发布于:2007-08-16 21:30
路过。。
|
|
|
地下室#
发布于:2007-08-17 09:18
明白了,是WRK里的吧?
|
|
5楼#
发布于:2007-08-17 09:20
呵呵,wowocock和楚狂人夜读天书哇,这下白读了哇。
|
|
6楼#
发布于:2007-08-17 16:23
现在流氓都不怕你删,你还没删完利他又生成了,所以不但要删除它,还得欺骗OS,让他认为自己还活着。
|
|
|
7楼#
发布于:2007-08-17 17:21
block住就可以了 见粉碎机
|
|
|
8楼#
发布于:2007-08-20 09:04
死锁加占坑的想法不错,不过对于那些重启后能再生成的保护,最好也加入,现在那些该死的病毒保护的地方太多了,手动很难清除。
|
|
|
9楼#
发布于:2007-08-20 09:55
如果已经把所有的流氓/病毒粉碎+占坑了,它哪还有重启再生成的机会?:P
|
|
|