<script type="text/javascript">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
作 者: 老Y
時 間: 2007-05-25,16:59
鏈 接: http://bbs.pediy.com/showthread.php?t=45233
先聲明一下,本文的代碼其實也是從別人的工具裏A出來的(A=逆向+還原),所以也不敢稱是原創,有同好的朋友自然知道是哪個工具裏的:),另外,由於本人不太會寫文章,看不明白的地方還請大家多多諒解。
回到正題,通過分析得知,刪除正在運行的程序文件的關鍵在於hook MmFlushImageSection這個函數,該函數原型BOOLEAN MmFlushImageSection(
PSECTION_OBJECT_POINTERS SectionObjectPointer,
MMFLUSH_TYPE FlushType),其流程大概如下:
1.打開要刪除的文件,如:調用IoCreateFile
2.把要刪除的文件屬性設爲Normal
3.Hook ntfs和fatfast內的引入函數MmFlushImageSection
4.發送刪除IRP
大概代碼如下(比較簡單的一個Demo):
void ForceDeleteFile(PVOID ThreadContext)
{
int krResult = FALSE;
int krRetCode = FALSE;
//NTSTATUS rc;
HANDLE hFile = NULL, hFileSystem = NULL, SectionHandle = NULL;
CHAR *FileName = (CHAR*)ThreadContext;
CHAR szFileSystem[MAX_PATH_LEN];
PUCHAR pMap = NULL;
ULONG uMapSize = 0;
PVOID OrgFunc = NULL, OrgFunc_Ptr = NULL;
KFile ntfs, fastfat, del;
//UNICODE_STRING usFileName;
//PFILE_OBJECT pFileObject = NULL;
//OBJECT_ATTRIBUTES ob;
DEBUG_BREAK;
krRetCode = del.OpenFile(FileName, GENERIC_READ);
PROCESS_ERROR(krRetCode);
dprintf("Open %s successful./n", FileName);
krResult = del.SetFileAttributeToNormal();
PROCESS_ERROR(krResult);
strcpy(szFileSystem, DRIVERS_PATH);
strcat(szFileSystem, "ntfs.sys");
krRetCode = ntfs.OpenFile(szFileSystem, GENERIC_READ);
PROCESS_ERROR(krRetCode);
g_Deleted = TRUE;
krRetCode = ntfs.MapFile(&pMap, &uMapSize);
PROCESS_ERROR(krRetCode);
krRetCode = HookIAT(
"MmFlushImageSection",
"ntfs.sys",
pMap,
uMapSize,
(PVOID)MmFlushImageSection_New,
(PVOID*)&_MmFlushImageSection,
&OrgFunc_Ptr
);
PROCESS_ERROR(krRetCode);
krRetCode = ntfs.UnMapFile();
PROCESS_ERROR(krRetCode);
strcpy(szFileSystem, DRIVERS_PATH);
strcat(szFileSystem, "fastfat.sys");
krRetCode = fastfat.OpenFile(szFileSystem, GENERIC_READ);
PROCESS_ERROR(hFileSystem);
krRetCode = fastfat.MapFile( &pMap, &uMapSize);
PROCESS_ERROR(krRetCode);
krRetCode = HookIAT(
"MmFlushImageSection",
"fastfat.sys",
pMap,
uMapSize,
(PVOID)MmFlushImageSection_New,
(PVOID*)&_MmFlushImageSection,
&OrgFunc_Ptr
);
PROCESS_ERROR(krRetCode);
krRetCode = ntfs.UnMapFile();
PROCESS_ERROR(krRetCode);
krResult = Rd_DeleteFile(del.GetFileHandle());
PROCESS_ERROR(krResult);
krResult = TRUE;
Exit0:
g_Deleted = FALSE;
if (OrgFunc && OrgFunc_Ptr)
{
UnHookIAT(_MmFlushImageSection, OrgFunc_Ptr);
}
ntfs.Close();
fastfat.Close();
del.Close();
return;
}
Rd_DeleteFile代碼如下:
int Rd_DeleteFile(HANDLE hFile)
{
int krResult = FALSE;
DEVICE_OBJECT *pRealObject = NULL;
DEVICE_OBJECT *pDeviceObject = NULL;
PIRP irp;
NTSTATUS rc;
KEVENT event;
PIO_STACK_LOCATION irpSp;
IO_STATUS_BLOCK localIoStatus;
PFILE_OBJECT pFileObject = NULL;
FILE_DISPOSITION_INFORMATION disp;
ULONG Length = sizeof(FILE_DISPOSITION_INFORMATION);
disp.DeleteFile = TRUE;
rc = ObReferenceObjectByHandle(
hFile,
0,
*IoFileObjectType,
0,
(PVOID*)&pFileObject,
0);
PROCESS_DDK_ERROR(rc);
pDeviceObject = GetRealDeviceObject(pFileObject, &pRealObject);
PROCESS_ERROR(pDeviceObject);
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
irp = IoAllocateIrp(pDeviceObject->StackSize, 0);
if (!irp)
{
goto Exit0;
}
irp->UserEvent = &event;
irp->UserIosb = &localIoStatus;
irp->Overlay.AsynchronousParameters.UserApcRoutine= (PIO_APC_ROUTINE) NULL;
irp->RequestorMode = 0;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject = pFileObject;
irp->Flags = IRP_BUFFERED_IO;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
irpSp->FileObject = pFileObject;
irpSp->DeviceObject = pDeviceObject;
irp->UserBuffer = NULL;
irp->AssociatedIrp.SystemBuffer = NULL;
irp->MdlAddress = (PMDL) NULL;
__try {
irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuota( NonPagedPool,
Length );
RtlCopyMemory( irp->AssociatedIrp.SystemBuffer,
&disp,
Length );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//
// An exception was incurred while allocating the intermediary
// system buffer or while copying the caller's data into the
// buffer. Cleanup and return an appropriate error status code.
//
IopExceptionCleanup( pFileObject,
irp,
(PKEVENT) NULL,
&event );
return GetExceptionCode();
}
irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_DEFER_IO_COMPLETION;
irpSp->Parameters.SetFile.DeleteHandle = hFile;
irpSp->Parameters.SetFile.Length = Length;
irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
irpSp->Control = 0xE0;
irpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)Io_Completion_Routine;
if (rc == STATUS_PENDING)
{
rc = KeWaitForSingleObject(
&event,
Executive,
0,
1,
0);
}
krResult = TRUE;
Exit0:
return krResult;
}
原理:
該IRP最後會調用Ntfs內的NtfsSetDispositionInfo函數或Fastfat內的 FatSetPositionInfo函數(這區別於你的硬盤分區是什麼文件系統),而這兩個函數都會調用Ntoskrnl內的 MmFlushImageSection函數,由於我們 hook了這兩驅動內的MmFlushImageSection調用,所以當它自己發送IRP 時,Hook_MmFlushImageSection就能截獲請求,然後在該函數內判斷SectionObjectPointer參數是否等於需要刪除 文件的SectionObjectPointer,如果相等則調用原來的MmFlushImageSection並返回True(返回True表示正在被 操作的FileObject的Section不存在或沒有被Map進內存),如果不相等,則返回原來的MmFlushImageSection的調用結 果。
後記:
自己構造IRP直接與FSD通信已經是老生常談的話題了,有興趣的朋友可以網上找找。