最近閑得沒事做,想逆幾個驅動玩玩,於是就把目標投向了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 }