其實這東西很多大牛多玩膩了的東西,看下論壇上比較少這類的,就來獻獻醜,科普一下 大牛們直接
可以飄過,這東西主要是自我複習一下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;/*
PVOID OpenProcedure; 這幾個函數指標就是我們最需要的
PVOID CloseProcedure; 這些函數都是決定你的物件的的一些
PVOID DeleteProcedure; 操作或者叫方法,比如打開 創建 刪除
PVOID ParseProcedure; 不同的物件類型(OBJECT_TYPE)操作也不同
PVOID SecurityProcedure; 所以要清楚的知道(OBJECT_TYPE)物件是什麼類型
PVOID QueryNameProcedure; 如果沒有配置系統調用的物件類型 都是用NtOpenFile
PVOID OkayToCloseProcedure;*/
} 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;
}