获取加载后就自动删除的驱动SYS文件
最近闲得没事做,想逆几个驱动玩玩,于是就把目标投向了Xuetr,利用Xuetr查询它的驱动文件位置
发现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的地址线,应该要加吧。。。
1 #include <ntifs.h> 2 3 extern ULONG_PTR KeServiceDescriptorTable; 4 5 typedef NTSTATUS (__stdcall *ZWLOADDRIVER)(IN PUNICODE_STRING DriverServiceName); 6 7 ZWLOADDRIVER OriginalZwLoadDriver; 8 9 DRIVER_INITIALIZE DriverEntry; 10 DRIVER_UNLOAD DriverUnload; 11 12 NTSTATUS ZwCopyFile(PUNICODE_STRING DestinationFileName,PUNICODE_STRING SourceFileName) 13 { 14 NTSTATUS status; 15 HANDLE SourceFileHandle=NULL; 16 HANDLE DestinationFileHandle=NULL; 17 OBJECT_ATTRIBUTES ObjectAttributes; 18 IO_STATUS_BLOCK IoStatusBlock; 19 FILE_STANDARD_INFORMATION FileInfo; 20 ULONG AllocationSize; 21 PVOID FileBuffer=NULL; 22 BOOLEAN bAllocateInVirtualMemory=FALSE; 23 24 InitializeObjectAttributes( &ObjectAttributes, 25 SourceFileName, 26 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 27 NULL, 28 NULL); 29 status=IoCreateFile(&SourceFileHandle, 30 GENERIC_READ|SYNCHRONIZE, 31 &ObjectAttributes, 32 &IoStatusBlock, 33 NULL, 34 FILE_ATTRIBUTE_NORMAL, 35 FILE_SHARE_READ, 36 FILE_OPEN, 37 FILE_SYNCHRONOUS_IO_NONALERT, 38 NULL, 39 0, 40 CreateFileTypeNone, 41 0, 42 IO_NO_PARAMETER_CHECKING); 43 if (!NT_SUCCESS(status)) 44 { 45 DbgPrint("IoCreateFile (%wZ) failed,eid=0x%08x\n",SourceFileName,status); 46 goto cleanup; 47 } 48 49 //DbgPrint("Open %wZ success!\n",SourceFileName); 50 51 status=ZwQueryInformationFile( 52 SourceFileHandle, 53 &IoStatusBlock, 54 (PVOID)&FileInfo, 55 sizeof(FileInfo), 56 FileStandardInformation); 57 if (!NT_SUCCESS(status)) 58 { 59 DbgPrint("ZwQueryFileInformation (%wZ) failed,eid=0x%08x\n",SourceFileName,status); 60 goto cleanup; 61 } 62 63 //DbgPrint("ZwQueryInformationFile success!\n"); 64 65 AllocationSize=FileInfo.AllocationSize.LowPart; 66 67 FileBuffer=ExAllocatePoolWithTag(PagedPool,AllocationSize,'CODE'); 68 if (!FileBuffer) 69 { 70 status=ZwAllocateVirtualMemory( (HANDLE)(-1), 71 (PVOID)&FileBuffer, 72 0, 73 &AllocationSize, 74 MEM_COMMIT, 75 PAGE_READWRITE); 76 if (!NT_SUCCESS(status)) 77 { 78 DbgPrint("Cannot Allocate Such Large Buffer!\n"); 79 goto cleanup; 80 } 81 bAllocateInVirtualMemory=TRUE; 82 } 83 84 status=ZwReadFile( SourceFileHandle, 85 NULL, 86 NULL, 87 NULL, 88 &IoStatusBlock, 89 FileBuffer, 90 AllocationSize, 91 NULL, 92 NULL); 93 94 if (!NT_SUCCESS(status)) 95 { 96 DbgPrint("ZwReadFile (%wZ) failed,eid=0x%08x\n",SourceFileName,status); 97 goto cleanup; 98 } 99 100 InitializeObjectAttributes( &ObjectAttributes, 101 DestinationFileName, 102 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 103 NULL, 104 NULL); 105 status=IoCreateFile(&DestinationFileHandle, 106 GENERIC_READ|GENERIC_WRITE, 107 &ObjectAttributes, 108 &IoStatusBlock, 109 NULL, 110 FILE_ATTRIBUTE_NORMAL, 111 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 112 FILE_OVERWRITE_IF, 113 FILE_SYNCHRONOUS_IO_NONALERT, 114 NULL, 115 0, 116 CreateFileTypeNone, 117 NULL, 118 IO_NO_PARAMETER_CHECKING); 119 if (!NT_SUCCESS(status)) 120 { 121 DbgPrint("IoCreateFile (%wZ) failed,eid=0x%08x\n",DestinationFileName,status); 122 goto cleanup; 123 } 124 125 status=ZwWriteFile( DestinationFileHandle, 126 NULL, 127 NULL, 128 NULL, 129 &IoStatusBlock, 130 FileBuffer, 131 AllocationSize, 132 NULL, 133 NULL); 134 135 if (!NT_SUCCESS(status)) 136 DbgPrint("ZwWriteFile (%wZ) failed,eid=0x%08x\n",DestinationFileName,status); 137 138 cleanup: 139 if (bAllocateInVirtualMemory) 140 ZwFreeVirtualMemory((HANDLE)(-1),(PVOID)&FileBuffer,&AllocationSize,MEM_RELEASE); 141 else if(FileBuffer) 142 ExFreePoolWithTag(FileBuffer,'CODE'); 143 if(SourceFileHandle) 144 ZwClose(SourceFileHandle); 145 if (DestinationFileHandle) 146 ZwClose(DestinationFileHandle); 147 148 return status; 149 } 150 151 NTSTATUS FilterZwLoadDriver(IN PUNICODE_STRING DriverServiceName) 152 { 153 NTSTATUS status; 154 HANDLE ServiceKeyHandle; 155 OBJECT_ATTRIBUTES ObjectAttribute; 156 UNICODE_STRING usValueKey; 157 UNICODE_STRING usDestinationFileName; 158 UNICODE_STRING usSourceFileName; 159 ULONG cbNeeded; 160 PKEY_VALUE_PARTIAL_INFORMATION Info; 161 WCHAR szDestinationFileName[260]=L"\\??\\C:\\"; 162 WCHAR *EndPointer; 163 164 //DbgPrint("SSDT HOOK ZwLoadDriver success!\n"); 165 166 InitializeObjectAttributes(&ObjectAttribute,DriverServiceName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL); 167 status=ZwOpenKey(&ServiceKeyHandle,KEY_READ,&ObjectAttribute); 168 if (!NT_SUCCESS(status)) 169 { 170 DbgPrint("ZwOpenKey failed,eid=0x%08x!\n",status); 171 return status; 172 } 173 174 //DbgPrint("ZwOpenKey (%wZ) success!\n",DriverServiceName); 175 176 RtlInitUnicodeString(&usValueKey,L"ImagePath"); 177 ZwQueryValueKey(ServiceKeyHandle,&usValueKey,KeyValuePartialInformation,NULL,0,&cbNeeded); 178 //DbgPrint("cbNeeded=%d\n",cbNeeded); 179 180 Info=ExAllocatePoolWithTag(PagedPool,cbNeeded,'CODE'); 181 status=ZwQueryValueKey(ServiceKeyHandle,&usValueKey,KeyValuePartialInformation,(PVOID)Info,cbNeeded,&cbNeeded); 182 if (!NT_SUCCESS(status)) 183 { 184 DbgPrint("ZwQueryValueKey failed,eid=0x%08x\n",status); 185 ExFreePoolWithTag(Info,'CODE'); 186 return status; 187 } 188 189 ZwClose(ServiceKeyHandle); 190 191 //DbgPrint("Type=%d,ImagePath=%ws,DataLength=%d\n",Info->Type,Info->Data,Info->DataLength);//include UNICODE_NULL_TERMINATOR 192 193 RtlInitUnicodeString(&usSourceFileName,(PCWSTR)(Info->Data)); 194 195 EndPointer=(WCHAR*)(Info->Data+Info->DataLength); 196 197 while (*EndPointer!='\\') 198 EndPointer--; 199 memcpy(szDestinationFileName+wcslen(szDestinationFileName),EndPointer+1,((ULONG)(Info->Data)+Info->DataLength-(ULONG)EndPointer)); 200 201 RtlInitUnicodeString(&usDestinationFileName,szDestinationFileName); 202 203 //DbgPrint("Destination=%wZ\n",&usDestinationFileName); 204 205 ExFreePoolWithTag(Info,'CODE'); 206 207 status=ZwCopyFile(&usDestinationFileName,&usSourceFileName); 208 if (!NT_SUCCESS(status)) 209 { 210 DbgPrint("ZwCopyFile failed,eid=%d!\n",status); 211 return status; 212 } 213 214 DbgPrint("CopyFile %ws--->%ws success!\n",(&usSourceFileName)->Buffer+wcslen(L"\\??\\"),(&usDestinationFileName)->Buffer+wcslen(L"\\??\\")); 215 216 DbgPrint("Mission Complete,Congratulations!\n"); 217 218 return (OriginalZwLoadDriver)(DriverServiceName); 219 } 220 221 VOID SSDT_HOOK_ZwLoadDriver() 222 { 223 __asm 224 { 225 cli 226 push eax 227 mov eax, CR0 228 and eax, 0FFFEFFFFh 229 mov CR0, eax 230 pop eax 231 } 232 233 _asm{ 234 mov ecx, dword ptr [ZwLoadDriver]; 235 mov edx, [ecx+1]; 236 mov eax, dword ptr [KeServiceDescriptorTable]; 237 mov esi, [eax]; 238 mov edx, [esi+edx*4]; 239 mov dword ptr [OriginalZwLoadDriver], edx 240 mov ecx, [ecx+1] 241 mov eax, [eax] 242 mov dword ptr [eax+ecx*4], offset FilterZwLoadDriver; 243 } 244 245 __asm 246 { 247 push eax 248 mov eax, CR0 249 or eax, NOT 0FFFEFFFFh 250 mov CR0, eax 251 pop eax 252 sti 253 } 254 } 255 256 VOID SSDT_UNHOOK_ZwLoadDriver() 257 { 258 __asm 259 { 260 cli 261 push eax 262 mov eax, CR0 263 and eax, 0FFFEFFFFh 264 mov CR0, eax 265 pop eax 266 } 267 268 _asm{ 269 270 mov ecx, dword ptr [ZwLoadDriver]; 271 mov edx, [ecx+1]; 272 mov eax, dword ptr [KeServiceDescriptorTable]; 273 mov esi, [eax]; 274 mov ebx, dword ptr [OriginalZwLoadDriver]; 275 mov [esi+edx*4],ebx; 276 } 277 278 __asm 279 { 280 push eax 281 mov eax, CR0 282 or eax, NOT 0FFFEFFFFh 283 mov CR0, eax 284 pop eax 285 sti 286 } 287 } 288 289 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath) 290 { 291 SSDT_HOOK_ZwLoadDriver(); 292 293 DriverObject->DriverUnload=DriverUnload; 294 295 return STATUS_SUCCESS; 296 } 297 298 VOID DriverUnload(PDRIVER_OBJECT DriverObject) 299 { 300 SSDT_UNHOOK_ZwLoadDriver(); 301 }