获取加载后就自动删除的驱动SYS文件
2012-11-10 16:40
519 查看
最近闲得没事做,想逆几个驱动玩玩,于是就把目标投向了Xuetr,利用Xuetr查询它的驱动文件位置
发现DriverPath里面显示的是驱动的位置,但是驱动文件死活找不到,原来是因为它在加载完驱动之后,马上自删除了该文件,估计是考虑到不想被别有用心的人拿来逆向吧
今天我们的任务就是要来获取这个SYS文件,然后利用IDA来XX,以学习Xuetr里面的一些先进技术
一开始想到的方法是既然文件在这个位置出现过,那么我写一个死循环的函数来不断的CopyFile,这样不就可以获取到它的SYS文件么,于是就有了下面的代码
这样只要这个Console程序退出就知道已经拷贝成功了,注意文件的保存位置是在C盘的根目录下,所以WIN7的话要以管理员运行程序,不然CopyFile会出现Access Denied的错误,还有就是要在文件夹选项中去掉“隐藏系统保护的重要文件”选项才能看到
现在虽然能够获取到SYS文件,但是每次加载一个新的驱动的话就要把上面的SRC_PATH和DST_PATH做一番修改,有没有办法获取到驱动的ImagePath,从而做到一劳永逸呢?
自己写过加载驱动的程序的都知道,首先在HKLM\SYSTEM\CurrentControlSet\Services\键下创建一个名字为驱动名的子健,然后在这个子健中创建一些ValueKey,比如ImagePath,StartType等等,因此如果我们可以从这里入手
于是就想到了利用SSDT HOOK来钩住ZwLoadDriver,通过ZwLoadDriver传进来的第一个参数DriverServiceName来读取这个注册表键,然后再进一步的得到ImagePath的值,再利用这个ImagePath来构造我们的DestinationFileName,假设Xuetr的ImagePath为\??\C:\Users\stefanie\Desktop\XueTr.sys,那么我们最终存放的驱动位置就是C:\Xuetr.sys,这些都是在FilterZwLoadDriver中实现的
同样在这个函数里面也实现了拷贝文件的功能,由于WDK中并没有ZwCopyFile等函数,所以自己写了个ZwCopyFile通过打开文件,读取文件,和写入文件的方法来实现
(这种方法有个弊端,就是文件读取的时候,文件内容是读取在驱动的内部缓冲区里面,如果文件过大的话,怕分配不了那么大的空间,内核空间貌似挺宝贵的,当然可以比如每次4K这样子读写,网上有人利用自己生成和发送IRP来进行文件的操作,等我研究好了再回来补充一下~)
BTW:这个驱动并没有考虑到要过主防,如果你的机器装了360的话,那么这个方法将会失效,360的HOOKPORT.SYS框架钩住了KiFastCallEntry,同时它也保存了敏感函数比如ZwLoadDriver的原始地址在它的一个索引表里面,虽然你在这里SSDT HOOK了,但是系统调用的必经之路KiFastCallEntry被360给钩住了,当ZwLoadDriver的时候,不是通过读取SSDT来获得它的地址,而是通过查360自己的那张表。。。说的有点拗口。。。别的杀毒软件没有测试过,HIPS应该都会钩住这个函数,所以最好在虚拟机中使用而且是干净的操作系统
好了,废话不多说,贴代码了,这份代码同时也为那些不知道在内核中怎么操作注册表和操作文件的新手提供参考
ps:刚在路上突然想到,下面的开关中断是不是应该KeAquireSpinLock一下,因为如果是多核的话,其他的核在读取地址的时候,万一正在修改的话会不会出现BSOD?????
看了某驱动用的是InterLockedExChange来锁住CPU的地址线,应该要加吧。。。
发现DriverPath里面显示的是驱动的位置,但是驱动文件死活找不到,原来是因为它在加载完驱动之后,马上自删除了该文件,估计是考虑到不想被别有用心的人拿来逆向吧
今天我们的任务就是要来获取这个SYS文件,然后利用IDA来XX,以学习Xuetr里面的一些先进技术
一开始想到的方法是既然文件在这个位置出现过,那么我写一个死循环的函数来不断的CopyFile,这样不就可以获取到它的SYS文件么,于是就有了下面的代码
#include <windows.h> #include <stdio.h> #define SRC_PATH "C:\\Users\\stefanie\\Desktop\\XueTr.sys" #define DST_PATH "C:\\Xuetr.SYS" int main() { while (!CopyFileA(SRC_PATH,DST_PATH,FALSE)); printf("Copy File success!\n"); return 0; }
这样只要这个Console程序退出就知道已经拷贝成功了,注意文件的保存位置是在C盘的根目录下,所以WIN7的话要以管理员运行程序,不然CopyFile会出现Access Denied的错误,还有就是要在文件夹选项中去掉“隐藏系统保护的重要文件”选项才能看到
现在虽然能够获取到SYS文件,但是每次加载一个新的驱动的话就要把上面的SRC_PATH和DST_PATH做一番修改,有没有办法获取到驱动的ImagePath,从而做到一劳永逸呢?
自己写过加载驱动的程序的都知道,首先在HKLM\SYSTEM\CurrentControlSet\Services\键下创建一个名字为驱动名的子健,然后在这个子健中创建一些ValueKey,比如ImagePath,StartType等等,因此如果我们可以从这里入手
于是就想到了利用SSDT HOOK来钩住ZwLoadDriver,通过ZwLoadDriver传进来的第一个参数DriverServiceName来读取这个注册表键,然后再进一步的得到ImagePath的值,再利用这个ImagePath来构造我们的DestinationFileName,假设Xuetr的ImagePath为\??\C:\Users\stefanie\Desktop\XueTr.sys,那么我们最终存放的驱动位置就是C:\Xuetr.sys,这些都是在FilterZwLoadDriver中实现的
同样在这个函数里面也实现了拷贝文件的功能,由于WDK中并没有ZwCopyFile等函数,所以自己写了个ZwCopyFile通过打开文件,读取文件,和写入文件的方法来实现
(这种方法有个弊端,就是文件读取的时候,文件内容是读取在驱动的内部缓冲区里面,如果文件过大的话,怕分配不了那么大的空间,内核空间貌似挺宝贵的,当然可以比如每次4K这样子读写,网上有人利用自己生成和发送IRP来进行文件的操作,等我研究好了再回来补充一下~)
BTW:这个驱动并没有考虑到要过主防,如果你的机器装了360的话,那么这个方法将会失效,360的HOOKPORT.SYS框架钩住了KiFastCallEntry,同时它也保存了敏感函数比如ZwLoadDriver的原始地址在它的一个索引表里面,虽然你在这里SSDT HOOK了,但是系统调用的必经之路KiFastCallEntry被360给钩住了,当ZwLoadDriver的时候,不是通过读取SSDT来获得它的地址,而是通过查360自己的那张表。。。说的有点拗口。。。别的杀毒软件没有测试过,HIPS应该都会钩住这个函数,所以最好在虚拟机中使用而且是干净的操作系统
好了,废话不多说,贴代码了,这份代码同时也为那些不知道在内核中怎么操作注册表和操作文件的新手提供参考
ps:刚在路上突然想到,下面的开关中断是不是应该KeAquireSpinLock一下,因为如果是多核的话,其他的核在读取地址的时候,万一正在修改的话会不会出现BSOD?????
看了某驱动用的是InterLockedExChange来锁住CPU的地址线,应该要加吧。。。
#include <ntifs.h> extern ULONG_PTR KeServiceDescriptorTable; typedef NTSTATUS (__stdcall *ZWLOADDRIVER)(IN PUNICODE_STRING DriverServiceName); ZWLOADDRIVER OriginalZwLoadDriver; DRIVER_INITIALIZE DriverEntry; DRIVER_UNLOAD DriverUnload; NTSTATUS ZwCopyFile(PUNICODE_STRING DestinationFileName,PUNICODE_STRING SourceFileName) { NTSTATUS status; HANDLE SourceFileHandle=NULL; HANDLE DestinationFileHandle=NULL; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION FileInfo; ULONG AllocationSize; PVOID FileBuffer=NULL; BOOLEAN bAllocateInVirtualMemory=FALSE; InitializeObjectAttributes( &ObjectAttributes, SourceFileName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL); status=IoCreateFile(&SourceFileHandle, GENERIC_READ|SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, 0, IO_NO_PARAMETER_CHECKING); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateFile (%wZ) failed,eid=0x%08x\n",SourceFileName,status); goto cleanup; } //DbgPrint("Open %wZ success!\n",SourceFileName); status=ZwQueryInformationFile( SourceFileHandle, &IoStatusBlock, (PVOID)&FileInfo, sizeof(FileInfo), FileStandardInformation); if (!NT_SUCCESS(status)) { DbgPrint("ZwQueryFileInformation (%wZ) failed,eid=0x%08x\n",SourceFileName,status); goto cleanup; } //DbgPrint("ZwQueryInformationFile success!\n"); AllocationSize=FileInfo.AllocationSize.LowPart; FileBuffer=ExAllocatePoolWithTag(PagedPool,AllocationSize,'CODE'); if (!FileBuffer) { status=ZwAllocateVirtualMemory( (HANDLE)(-1), (PVOID)&FileBuffer, 0, &AllocationSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("Cannot Allocate Such Large Buffer!\n"); goto cleanup; } bAllocateInVirtualMemory=TRUE; } status=ZwReadFile( SourceFileHandle, NULL, NULL, NULL, &IoStatusBlock, FileBuffer, AllocationSize, NULL, NULL); if (!NT_SUCCESS(status)) { DbgPrint("ZwReadFile (%wZ) failed,eid=0x%08x\n",SourceFileName,status); goto cleanup; } InitializeObjectAttributes( &ObjectAttributes, DestinationFileName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL); status=IoCreateFile(&DestinationFileHandle, GENERIC_READ|GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateFile (%wZ) failed,eid=0x%08x\n",DestinationFileName,status); goto cleanup; } status=ZwWriteFile( DestinationFileHandle, NULL, NULL, NULL, &IoStatusBlock, FileBuffer, AllocationSize, NULL, NULL); if (!NT_SUCCESS(status)) DbgPrint("ZwWriteFile (%wZ) failed,eid=0x%08x\n",DestinationFileName,status); cleanup: if (bAllocateInVirtualMemory) ZwFreeVirtualMemory((HANDLE)(-1),(PVOID)&FileBuffer,&AllocationSize,MEM_RELEASE); else if(FileBuffer) ExFreePoolWithTag(FileBuffer,'CODE'); if(SourceFileHandle) ZwClose(SourceFileHandle); if (DestinationFileHandle) ZwClose(DestinationFileHandle); return status; } NTSTATUS FilterZwLoadDriver(IN PUNICODE_STRING DriverServiceName) { NTSTATUS status; HANDLE ServiceKeyHandle; OBJECT_ATTRIBUTES ObjectAttribute; UNICODE_STRING usValueKey; UNICODE_STRING usDestinationFileName; UNICODE_STRING usSourceFileName; ULONG cbNeeded; PKEY_VALUE_PARTIAL_INFORMATION Info; WCHAR szDestinationFileName[260]=L"\\??\\C:\\"; WCHAR *EndPointer; //DbgPrint("SSDT HOOK ZwLoadDriver success!\n"); InitializeObjectAttributes(&ObjectAttribute,DriverServiceName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL); status=ZwOpenKey(&ServiceKeyHandle,KEY_READ,&ObjectAttribute); if (!NT_SUCCESS(status)) { DbgPrint("ZwOpenKey failed,eid=0x%08x!\n",status); return status; } //DbgPrint("ZwOpenKey (%wZ) success!\n",DriverServiceName); RtlInitUnicodeString(&usValueKey,L"ImagePath"); ZwQueryValueKey(ServiceKeyHandle,&usValueKey,KeyValuePartialInformation,NULL,0,&cbNeeded); //DbgPrint("cbNeeded=%d\n",cbNeeded); Info=ExAllocatePoolWithTag(PagedPool,cbNeeded,'CODE'); status=ZwQueryValueKey(ServiceKeyHandle,&usValueKey,KeyValuePartialInformation,(PVOID)Info,cbNeeded,&cbNeeded); if (!NT_SUCCESS(status)) { DbgPrint("ZwQueryValueKey failed,eid=0x%08x\n",status); ExFreePoolWithTag(Info,'CODE'); return status; } ZwClose(ServiceKeyHandle); //DbgPrint("Type=%d,ImagePath=%ws,DataLength=%d\n",Info->Type,Info->Data,Info->DataLength);//include UNICODE_NULL_TERMINATOR RtlInitUnicodeString(&usSourceFileName,(PCWSTR)(Info->Data)); EndPointer=(WCHAR*)(Info->Data+Info->DataLength); while (*EndPointer!='\\') EndPointer--; memcpy(szDestinationFileName+wcslen(szDestinationFileName),EndPointer+1,((ULONG)(Info->Data)+Info->DataLength-(ULONG)EndPointer)); RtlInitUnicodeString(&usDestinationFileName,szDestinationFileName); //DbgPrint("Destination=%wZ\n",&usDestinationFileName); ExFreePoolWithTag(Info,'CODE'); status=ZwCopyFile(&usDestinationFileName,&usSourceFileName); if (!NT_SUCCESS(status)) { DbgPrint("ZwCopyFile failed,eid=%d!\n",status); return status; } DbgPrint("CopyFile %ws--->%ws success!\n",(&usSourceFileName)->Buffer+wcslen(L"\\??\\"),(&usDestinationFileName)->Buffer+wcslen(L"\\??\\")); DbgPrint("Mission Complete,Congratulations!\n"); return (OriginalZwLoadDriver)(DriverServiceName); } VOID SSDT_HOOK_ZwLoadDriver() { __asm { cli push eax mov eax, CR0 and eax, 0FFFEFFFFh mov CR0, eax pop eax } _asm{ mov ecx, dword ptr [ZwLoadDriver]; mov edx, [ecx+1]; mov eax, dword ptr [KeServiceDescriptorTable]; mov esi, [eax]; mov edx, [esi+edx*4]; mov dword ptr [OriginalZwLoadDriver], edx mov ecx, [ecx+1] mov eax, [eax] mov dword ptr [eax+ecx*4], offset FilterZwLoadDriver; } __asm { push eax mov eax, CR0 or eax, NOT 0FFFEFFFFh mov CR0, eax pop eax sti } } VOID SSDT_UNHOOK_ZwLoadDriver() { __asm { cli push eax mov eax, CR0 and eax, 0FFFEFFFFh mov CR0, eax pop eax } _asm{ mov ecx, dword ptr [ZwLoadDriver]; mov edx, [ecx+1]; mov eax, dword ptr [KeServiceDescriptorTable]; mov esi, [eax]; mov ebx, dword ptr [OriginalZwLoadDriver]; mov [esi+edx*4],ebx; } __asm { push eax mov eax, CR0 or eax, NOT 0FFFEFFFFh mov CR0, eax pop eax sti } } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath) { SSDT_HOOK_ZwLoadDriver(); DriverObject->DriverUnload=DriverUnload; return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT DriverObject) { SSDT_UNHOOK_ZwLoadDriver(); }
相关文章推荐
- 动态监控驱动sys、动态链接库dll、可执行文件exe加载
- 通过HookNtCreateSection 动态监控驱动sys、动态链接库dll、可执行文件exe加载
- 通过HookNtCreateSection 动态监控驱动sys、动态链接库dll、可执行文件exe加载
- 通过HookNtCreateSection 动态监控驱动sys、动态链接库dll、可执行文件exe加载
- 一段文件删除代码(动态加载驱动)
- C# 目录操作(新建,删除),获取目录下文件列表
- 解决jsp上传文件,重启tomcat后文件和文件夹自动删除
- Visual Studio 2015 自动生成 的大文件xxx.vc.db的删除问题
- Asp.Net 文件操作基类(读取,删除,批量拷贝,删除,写入,获取文件夹大小,文件属性,遍历目录)
- 解析PHP入口文件的自动加载功能
- SQL SERVER 设置自动备份和删除旧的数据库文件
- Asp.Net 文件操作基类(读取,删除,批量拷贝,删除,写入,获取文件夹大小,文件属性,遍历目录)
- Atitit.检测文本文件的编码 自动获取文件的中文编码
- Spring使用通配符自动加载hibernate映射文件生成sessionFactory
- 用MASM32 DIY的下次开机自动删除文件程序(v0.0.0005)
- PHP 命名空间以及自动加载(自动调用的函数,来include文件)
- 自动删除oracle下的过期文件命令
- Windows7删除休眠文件hiberfil.sys节省大量C盘空间
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- cocos2d-x开发 android.mk自动获取.cpp和.c文件