您的位置:首页 > 其它

获取加载后就自动删除的驱动SYS文件

2012-11-10 16:40 519 查看
最近闲得没事做,想逆几个驱动玩玩,于是就把目标投向了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的地址线,应该要加吧。。。

#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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐