标 题:
【原创】从内核层保护文件不被删除
作 者: 老Y
时 间: 2007-05-27,17:20:00
链 接: http://bbs.pediy.com/showthread.php?t=45346
前几天发了一篇删除正在运行的程序文件的代码片,其实都平常写demo留下的东西,如果大家有兴趣,我会找时间慢慢整理一些出来和大家分享。同样是块demo代码,前面有兄弟问为什么不整完整一些,在这里解释一下:
1. 因为要分享是一种思路或技巧,不想被一些有心人不劳而获的A走(虽然我也是A别人的,呵呵)
2. 关键的,如果发完整的领导就该找我喝茶了,希望能理解
好了,回到正题是来,保护文件不被删除的方法有很多,例如:FSD Dispatch Hook、文件过滤驱动、在内核层打开文件占用等等,这里要介绍的是另一种方法,Inline Hook IofCallDriver大法,用这个方法来保护文件确实有点大材小用(它可以做的事情实在太多了,充分发挥想像力吧),并且在性能上可能会有点问题,但它有个优势是可以躲过一些工具的查杀。
2.判断sp->MajorFunction == IRP_MJ_SET_INFORMATION 如果不相等,则跳出
3.判断sp->Parameters.SetFile.FileInformationClass == FileDispositionInformation,如果不相等,则跳出。
4.判断DeviceObject->DriverObject.DriverName是否为\FileSystem\ntfs或\FileSystem\fastfat,因为我们要拦截的是发往ntfs和fastfat驱动的Irp请求,所以如果不相等,则跳出。
5.判断sp->FileObject.FileName是否是我们要保护的文件(注意:这里取到的不是全路径,需要全路径要另作处理),如果不相等,则跳出
6.上面所有条件都符合时,设置Irp->IoStatus.Information = 0;Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;并调用IoCompleteRequest完成Irp,Irp不再往下传了。
IofCallDriver函数的原型
NTSTATUS
__fastcall
IofCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
这是一个fastcall函数,取参数的时候要注意一下。
下面是代码片段:
#define PROLOG __asm { pushad } __asm { pushfd }
#define RETURN __asm { popfd } __asm { popad } __asm { pop eax } __asm{ mov eax, 0xC000000D } __asm{ ret }
#define EPILOG __asm { popfd } __asm { popad } __asm { ret }
_declspec( naked )
NTSTATUS
__fastcall
IofCallDriver_Hook(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
PROLOG
__asm
{
push ecx
pop dword ptr g_HookParam.DeviceObject
push edx
pop dword ptr g_HookParam.Irp
}
if (IsNeedProtect(g_HookParam.DeviceObject, g_HookParam.Irp))
{
dprintf("Protect start...\n");
RETURN
}
Exit0:
EPILOG
}
int IsNeedProtect(DEVICE_OBJECT *DeviceObject, PIRP Irp)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
int nResult = FALSE;
DRIVER_OBJECT *DriverObject = DeviceObject->DriverObject;
WCHAR *pwsz = NULL;
IO_STACK_LOCATION *sp;
FILE_OBJECT *FileObject = NULL;
sp = IoGetNextIrpStackLocation(Irp);
PROCESS_ERROR(sp);
if (sp->MajorFunction != IRP_MJ_SET_INFORMATION)
{
goto Exit0;
}
if (sp->Parameters.SetFile.FileInformationClass != FileDispositionInformation)
{
goto Exit0;
}
FileObject = sp->FileObject;
__try
{
pwsz = wcsrchr(DriverObject->DriverName.Buffer, L'\\');
PROCESS_ERROR(pwsz);
pwsz ++;
if (_wcsnicmp(pwsz, L"ntfs", 4) &&
_wcsnicmp(pwsz, L"fastfat", 7))
{
goto Exit0;
}
dprintf("IofCallDriver: Delete file %ws\n", FileObject->FileName.Buffer);
pwsz = wcsrchr(FileObject->FileName.Buffer, L'\\');
if (pwsz)
{
pwsz ++;
}
else
{
pwsz = FileObject->FileName.Buffer;
}
if (!_wcsnicmp(pwsz, L"test.exe", 8))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
nResult = TRUE;
goto Exit0;
}
}
__except(1)
{
goto Exit0;
}
Exit0:
return nResult;
}
结束。
作 者: 老Y
时 间: 2007-05-27,17:20:00
链 接: http://bbs.pediy.com/showthread.php?t=45346
前几天发了一篇删除正在运行的程序文件的代码片,其实都平常写demo留下的东西,如果大家有兴趣,我会找时间慢慢整理一些出来和大家分享。同样是块demo代码,前面有兄弟问为什么不整完整一些,在这里解释一下:
1. 因为要分享是一种思路或技巧,不想被一些有心人不劳而获的A走(虽然我也是A别人的,呵呵)
2. 关键的,如果发完整的领导就该找我喝茶了,希望能理解
好了,回到正题是来,保护文件不被删除的方法有很多,例如:FSD Dispatch Hook、文件过滤驱动、在内核层打开文件占用等等,这里要介绍的是另一种方法,Inline Hook IofCallDriver大法,用这个方法来保护文件确实有点大材小用(它可以做的事情实在太多了,充分发挥想像力吧),并且在性能上可能会有点问题,但它有个优势是可以躲过一些工具的查杀。
它保护文件的基本原理是:
当系统要删除一个文件时,它会向ntfs或fastfat驱动发送一个MajorFunction为IRP_MJ_SET_INFORMATION的IRP,而用来传递Irp的函数是IoCallDriver,该函数是一个宏,它再调用IofCallDriver,所以我们只要Inline Hook IofCallDriver函数就可以拦截删除文件请求。
大概步骤如下:
1.Inline Hook IofCallDriver函数2.判断sp->MajorFunction == IRP_MJ_SET_INFORMATION 如果不相等,则跳出
3.判断sp->Parameters.SetFile.FileInformationClass == FileDispositionInformation,如果不相等,则跳出。
4.判断DeviceObject->DriverObject.DriverName是否为\FileSystem\ntfs或\FileSystem\fastfat,因为我们要拦截的是发往ntfs和fastfat驱动的Irp请求,所以如果不相等,则跳出。
5.判断sp->FileObject.FileName是否是我们要保护的文件(注意:这里取到的不是全路径,需要全路径要另作处理),如果不相等,则跳出
6.上面所有条件都符合时,设置Irp->IoStatus.Information = 0;Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;并调用IoCompleteRequest完成Irp,Irp不再往下传了。
IofCallDriver函数的原型
NTSTATUS
__fastcall
IofCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
这是一个fastcall函数,取参数的时候要注意一下。
下面是代码片段:
#define PROLOG __asm { pushad } __asm { pushfd }
#define RETURN __asm { popfd } __asm { popad } __asm { pop eax } __asm{ mov eax, 0xC000000D } __asm{ ret }
#define EPILOG __asm { popfd } __asm { popad } __asm { ret }
_declspec( naked )
NTSTATUS
__fastcall
IofCallDriver_Hook(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
PROLOG
__asm
{
push ecx
pop dword ptr g_HookParam.DeviceObject
push edx
pop dword ptr g_HookParam.Irp
}
if (IsNeedProtect(g_HookParam.DeviceObject, g_HookParam.Irp))
{
dprintf("Protect start...\n");
RETURN
}
Exit0:
EPILOG
}
int IsNeedProtect(DEVICE_OBJECT *DeviceObject, PIRP Irp)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
int nResult = FALSE;
DRIVER_OBJECT *DriverObject = DeviceObject->DriverObject;
WCHAR *pwsz = NULL;
IO_STACK_LOCATION *sp;
FILE_OBJECT *FileObject = NULL;
sp = IoGetNextIrpStackLocation(Irp);
PROCESS_ERROR(sp);
if (sp->MajorFunction != IRP_MJ_SET_INFORMATION)
{
goto Exit0;
}
if (sp->Parameters.SetFile.FileInformationClass != FileDispositionInformation)
{
goto Exit0;
}
FileObject = sp->FileObject;
__try
{
pwsz = wcsrchr(DriverObject->DriverName.Buffer, L'\\');
PROCESS_ERROR(pwsz);
pwsz ++;
if (_wcsnicmp(pwsz, L"ntfs", 4) &&
_wcsnicmp(pwsz, L"fastfat", 7))
{
goto Exit0;
}
dprintf("IofCallDriver: Delete file %ws\n", FileObject->FileName.Buffer);
pwsz = wcsrchr(FileObject->FileName.Buffer, L'\\');
if (pwsz)
{
pwsz ++;
}
else
{
pwsz = FileObject->FileName.Buffer;
}
if (!_wcsnicmp(pwsz, L"test.exe", 8))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
nResult = TRUE;
goto Exit0;
}
}
__except(1)
{
goto Exit0;
}
Exit0:
return nResult;
}
结束。
![124.gif](http://bbs.pediy.com/images/smilies/124.gif)
![狂笑](http://bbs.pediy.com/images/smilies/biggrin.gif)