说明下,技术比较古老,适合我等小菜...
中秋的时候看了关于内核对象的内容, 为了加深理解, 就想试下文件的强制删除,只要把文件对象的引用计数改为0就可以了嘛... 不过郁闷的是根本就找不到那个文件对象
, 那个囧啊,然后就去网上找资料,怎么才能实现文件的强制删除呢?MJ说有两种方法
1.你可以使用自己给fsd发送irp请求来删除文件,或者用HOOK MmFlushImageSection等方法,详细见xikug等人逆向的360FileKill的驱动代码
2.使用DeviceIoControl调用驱动文件,或使用事件、共享内存等方法亦可
然后就去看文件过滤驱动,也就是想给文件系统发IRP实现,看那个寒江独钓,好不容易看懂了,不过纠结的是他没有提供读写的源码
,郁闷ing... 接下来就是HOOK MmFlushImageSection函数了,终于找到了一篇代码了
,使用hook MmFlushImageSection实现文件保护... 作者liuke_blue,非常感谢,O(∩_∩)O哈哈~
于是开始编写自己的文件强制删除机...
//自己的处理函数
BOOLEAN NTAPI Fake_MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,IN MMFLUSH_TYPE FlushType)
{
PFILE_OBJECT pfile;
WCHAR *pwsz=NULL;
if (FlushType == MmFlushForDelete)
{
if(SectionObjectPointer->DataSectionObject!=NULL)
{
//这里取得文件对象
pfile=(PFILE_OBJECT)( *(ULONG*)((ULONG)SectionObjectPointer->DataSectionObject + 0x24) );
__try
{
pwsz=wcsrchr(pfile->FileName.Buffer,L'\\');
if (pwsz!=NULL)
{
pwsz++;
}
//比较文件名是否相同,如果是,则删除
if (strcmp(outBuf.Buffer, pwsz) == 0)
{
DbgPrint("FileName=%ws",pwsz);
return TRUE;
}
}
except(1)
{
return FALSE;
}
}
}
return MmFlushImageSection(SectionObjectPointer,FlushType);
}
不过还是遇到那么些问题, 当文件在运行时将其删除,用常规的方法
BOOLEAN _DeleteFileNormal(PUNICODE_STRING filename)
{
HANDLE hfile;
NTSTATUS ntstatus;
ACCESS_MASK acmask;
OBJECT_ATTRIBUTES oa;
IO_STATUS_BLOCK iostatus;
ULONG shareAccess;
ULONG openOptions;
FILE_STANDARD_INFORMATION filestandardinfo;
FILE_DISPOSITION_INFORMATION filedisposition;
InitializeObjectAttributes(&oa, filename, OBJ_CASE_INSENSITIVE , NULL, NULL);
//方法1:调用ZwDeleteFile函数删除
ZwDeleteFile(&oa);
/*
//方法2:根据DeleteFile函数逆向出来的, 如果文件没在使用中可以删除,如果在使用中则ZwOpenFile函数失败,自然也不会调用MmFlushImageSection函数了,所以文件删除失败
ntstatus = ZwOpenFile(&hfile, GENERIC_READ | GENERIC_WRITE, &oa, &iostatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(ntstatus))
{
KdPrint(("ZwOpenFile failed\n"));
return FALSE;
}
ntstatus = ZwQueryInformationFile(hfile, &iostatus, &filestandardinfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
if (!NT_SUCCESS(ntstatus))
{
KdPrint(("Query FileStandardInformation failed..\n"));
return FALSE;
}
if (filestandardinfo.DeletePending == FALSE)
{
filedisposition.DeleteFile = TRUE;
ntstatus = ZwSetInformationFile(hfile, &iostatus, &filedisposition, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
if (!NT_SUCCESS(ntstatus))
{
KdPrint(("ZwSetInformationFile failed\n"));
return FALSE;
}
}
ZwClose(hfile);
*/
return TRUE;
}
不过这里删除失败以后,去那个目录下直接删除,是可以删除成功的
,所以强制删除应该还是成功的吧,只是有那么个bug, 作为小菜的我是非常纠结丫...没找到原因
,所以哪位大侠知道的,劳烦告知下... 不胜感激... 具体的代码见附件.
[课程]Linux pwn 探索篇!