天天看點

RootKit hook之[一] Object Hook

标 題: 【轉】objectHook簡單介紹

作 者: ggdd

時 間: 2011-01-15,13:13:20

鍊 接: http://bbs.pediy.com/showthread.php?t=128161

其實這東西很多大牛多玩膩了的東西,看下論壇上比較少這類的,就來獻獻醜,科普一下 大牛們直接

可以飄過,這東西主要是自我複習一下OBJECT的一些知識,技術這東西久了不弄容易忘記,是以

拿出來跟和我一樣菜的菜鳥們分享一下。如果有不對的地方歡迎大家指正,這樣對于自己也進步得

快點,多多交流,互相學習,水準才能提高得快。

   第一我們先看下OBJECT的組成 主要是3部分 如下圖

         |---------|

             | 附加資訊| --->  主要的幾個結構是 OBJECT_HEADER_CREATOR_INFO 建立資訊

                              OBJECT_HEADER_NAME_INFO 這裡面有對象名等主要資訊

                              OBJECT_HEADER_HANDLE_INFO 一些句柄資訊          

         |_________|                

             |                   |

             | 對象頭      |---->     一個重要的結構   OBJECT_HEADER              

             |_________|  

             |                  |

             | OBJECT      | --->       對象                

         |_________|  

   我們主要看下OBJECT_HEADER這個資料結構幾個重要我成員我注釋出來

複制代碼

typedef struct _OBJECT_HEADER {

LONG PointerCount;

union {

LONG HandleCount;

PSINGLE_LIST_ENTRY SEntry;

};

POBJECT_TYPE Type; //這個很重要HOOK就靠它,對象類型結構也是一個對象,TYPE它是系統第一個建立出來的對象類型

UCHAR NameInfoOffset; //OBJECT_HEADER_NAME_INFO 偏移

UCHAR HandleInfoOffset; //OBJECT_HEADER_HANDLE_INFO 偏移

UCHAR QuotaInfoOffset;

UCHAR Flags;

union

{

POBJECT_CREATE_INFORMATION ObjectCreateInfo;

PVOID QuotaBlockCharged;

};

PSECURITY_DESCRIPTOR SecurityDescriptor;

QUAD Body;//對象本身

} OBJECT_HEADER, *POBJECT_HEADER;

對象類型結構

typedef struct _OBJECT_TYPE {

ERESOURCE Mutex;

LIST_ENTRY TypeList; //隊列

UNICODE_STRING Name;

PVOID DefaultObject;

ULONG Index;

ULONG TotalNumberOfObjects;

ULONG TotalNumberOfHandles;

ULONG HighWaterNumberOfObjects;

ULONG HighWaterNumberOfHandles;

OBJECT_TYPE_INITIALIZER TypeInfo; //這個很重要,下面講這個結構

#ifdef POOL_TAGGING

ULONG Key;

#endif

} OBJECT_TYPE, *POBJECT_TYPE;

對象類型結構主要是建立對象類型比如*IoFileObjectType,*PsProcessType,*PsThreadType這些類型

系統初始化的時候第一個建立的對象類型結構就是TYPE類型結構生成對象目錄\ObjectTypes 其它後面的

比如檔案對象類型就挂在\ObjectTypes\File 再比如\ObjectTypes\Device

說白點就是你要生成對象就會建立(指定)相對應的對象類型結構

最重要的一個資料結構

typedef struct _OBJECT_TYPE_INITIALIZER {

USHORT Length;

BOOLEAN UseDefaultObject;

BOOLEAN CaseInsensitive;

ULONG InvalidAttributes;

GENERIC_MAPPING GenericMapping;

ULONG ValidAccessMask;

BOOLEAN SecurityRequired;

BOOLEAN MaintainHandleCount;

BOOLEAN MaintainTypeList;

POOL_TYPE PoolType;

ULONG DefaultPagedPoolCharge;

ULONG DefaultNonPagedPoolCharge;

PVOID DumpProcedure;

} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

這些方法何時被調用呢,我舉個例子

當你調用NtCreateFile->IoCreateFile->ObOpenObjectByName->ObpLookupObjectName->IopParseFile->IopParseDevice

IopParseFile最終也會調用IopParseDevice

ObjectHook其實就是比如你要HOOK 建立打開就是OBJECT_TYPE_INITIALIZER->ParseProcedure

說了一大堆廢話 上段代碼。

#include <ntddk.h>

#define OBJECT_TO_OBJECT_HEADER(o)\

CONTAINING_RECORD((o),OBJECT_HEADER,Body)

#define CONTAINING_RECORD(address,type,field)\

((type*)(((ULONG_PTR)address)-(ULONG_PTR)(&(((type*)0)->field))))

typedef struct _OBJECT_TYPE_INITIALIZER {

USHORT Length;

BOOLEAN UseDefaultObject;

BOOLEAN CaseInsensitive;

ULONG InvalidAttributes;

GENERIC_MAPPING GenericMapping;

ULONG ValidAccessMask;

BOOLEAN SecurityRequired;

BOOLEAN MaintainHandleCount;

BOOLEAN MaintainTypeList;

POOL_TYPE PoolType;

ULONG DefaultPagedPoolCharge;

ULONG DefaultNonPagedPoolCharge;

PVOID DumpProcedure;

PVOID OpenProcedure;

PVOID CloseProcedure;

PVOID DeleteProcedure;

PVOID ParseProcedure;

PVOID SecurityProcedure;

PVOID QueryNameProcedure;

PVOID OkayToCloseProcedure;

} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_TYPE {

ERESOURCE Mutex;

LIST_ENTRY TypeList;

UNICODE_STRING Name;

PVOID DefaultObject;

ULONG Index;

ULONG TotalNumberOfObjects;

ULONG TotalNumberOfHandles;

ULONG HighWaterNumberOfObjects;

ULONG HighWaterNumberOfHandles;

OBJECT_TYPE_INITIALIZER TypeInfo;

#ifdef POOL_TAGGING

ULONG Key;

#endif

} OBJECT_TYPE, *POBJECT_TYPE;

typedef struct _OBJECT_CREATE_INFORMATION {

ULONG Attributes;

HANDLE RootDirectory;

PVOID ParseContext;

KPROCESSOR_MODE ProbeMode;

ULONG PagedPoolCharge;

ULONG NonPagedPoolCharge;

ULONG SecurityDescriptorCharge;

PSECURITY_DESCRIPTOR SecurityDescriptor;

PSECURITY_QUALITY_OF_SERVICE SecurityQos;

SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;

} OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION;

typedef struct _OBJECT_HEADER {

LONG PointerCount;

union {

LONG HandleCount;

PSINGLE_LIST_ENTRY SEntry;

};

POBJECT_TYPE Type;

UCHAR NameInfoOffset;

UCHAR HandleInfoOffset;

UCHAR QuotaInfoOffset;

UCHAR Flags;

union

{

POBJECT_CREATE_INFORMATION ObjectCreateInfo;

PVOID QuotaBlockCharged;

};

PSECURITY_DESCRIPTOR SecurityDescriptor;

QUAD Body;

} OBJECT_HEADER, *POBJECT_HEADER;

POBJECT_TYPE pType= NULL;

POBJECT_HEADER addrs=NULL;

PVOID OldParseProcedure = NULL;

NTSTATUS NewParseProcedure(IN PVOID ParseObject,

IN PVOID ObjectType,

IN OUT PACCESS_STATE AccessState,

IN KPROCESSOR_MODE AccessMode,

IN ULONG Attributes,

IN OUT PUNICODE_STRING CompleteName,

IN OUT PUNICODE_STRING RemainingName,

IN OUT PVOID Context OPTIONAL,

IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,

OUT PVOID *Object)

{

NTSTATUS Status;

KdPrint(("object is hook\n"));

__asm

{

push eax

push Object

push SecurityQos

push Context

push RemainingName

push CompleteName

push Attributes

movzx eax, AccessMode

push eax

push AccessState

push ObjectType

push ParseObject

call OldParseProcedure

mov Status, eax

pop eax

}

return Status;

}

NTSTATUS Hook()

{

NTSTATUS Status;

HANDLE hFile;

UNICODE_STRING Name;

OBJECT_ATTRIBUTES Attr;

IO_STATUS_BLOCK ioStaBlock;

PVOID pObject = NULL;

RtlInitUnicodeString(&Name,L"\\Device\\HarddiskVolume1\\1.txt");

InitializeObjectAttributes(&Attr,&Name,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,\

0,NULL);

Status = ZwOpenFile(&hFile,GENERIC_ALL,&Attr,&ioStaBlock,\

0,FILE_NON_DIRECTORY_FILE);

if (!NT_SUCCESS(Status))

{

KdPrint(("File is Null\n"));

return Status;

}

Status = ObReferenceObjectByHandle(hFile,GENERIC_ALL,NULL,KernelMode,&pObject,NULL);

if (!NT_SUCCESS(Status))

{

KdPrint(("Object is Null\n"));

return Status;

}

KdPrint(("pobject is %08X\n",pObject));

addrs=OBJECT_TO_OBJECT_HEADER(pObject);//擷取對象頭

pType=addrs->Type;//擷取對象類型結構 object-10h

KdPrint(("pType is %08X\n",pType));

OldParseProcedure = pType->TypeInfo.ParseProcedure;//擷取服務函數原始位址OBJECT_TYPE+9C位置為打開

KdPrint(("OldParseProcedure addrs is %08X\n",OldParseProcedure));

KdPrint(("addrs is %08X\n",addrs));

//這裡最好檢查一下OldParseProcedure ,我真的是太懶了。

__asm

{

cli;

mov eax, cr0;

and eax, not 10000h;

mov cr0, eax;

}

pType->TypeInfo.ParseProcedure = NewParseProcedure;//hook

__asm

{

mov eax, cr0;

or eax, 10000h;

mov cr0, eax;

sti;

}

Status = ZwClose(hFile);

return Status;

}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)

{

NTSTATUS Status = STATUS_SUCCESS;

Status=Hook();

return Status;