首页
论坛
课程
招聘
[原创]objectHook简单介绍
2011-1-15 13:13 27423

[原创]objectHook简单介绍

2011-1-15 13:13
27423
其实这东西很多大牛多玩腻了的东西,看下论坛上比较少这类的,就来献献丑,科普一下 大牛们直接
可以飘过,这东西主要是自我复习一下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;
}




2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

上传的附件:
  • 3.jpg (36.47kb,1372次下载)
  • 6.jpg (29.65kb,1360次下载)
收藏
点赞0
打赏
分享
最新回复 (19)
雪    币: 582
活跃值: 活跃值 (100)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
RootSuLe 活跃值 4 2011-1-15 14:07
2
0
收藏了,谢谢
雪    币: 7506
活跃值: 活跃值 (298)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2011-1-15 14:20
3
0
写得不错~
另外,这货不是SSDT,直接改就行,不用改Cr0关写保护,因为ObjectType本来就是可写的~~
ObjectHook的方法很简单,主要是它的各种应用需要挖掘,比如拒绝、替换、重定向Object。。。
雪    币: 247
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ytfsse 活跃值 2011-1-15 16:11
4
0
替代容易的,还原比较麻烦。。。。
雪    币: 122
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
butian 活跃值 2011-1-15 16:43
5
0
good!正在寻找中!@
雪    币: 294
活跃值: 活跃值 (22)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
ggdd 活跃值 1 2011-1-16 00:00
6
0
谢谢教主的指点,又学到东西了 不用改Cr0关写保护
雪    币: 50
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
◕‿◕ 活跃值 2011-1-16 00:36
7
0
只要结构体里面有函数指针,想改啥就改啥
雪    币: 284
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 活跃值 2011-1-16 08:22
8
0
mark备查
雪    币: 78
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whypro 活跃值 2011-1-16 09:07
9
0
学习了好文顶顶
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yingthesky 活跃值 2011-1-16 22:25
10
0
mark一下
雪    币: 71
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 活跃值 2011-1-16 22:40
11
0
这篇文章不错

mark一下
雪    币: 408
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
snopy 活跃值 2011-1-17 11:24
12
0
学习了好文顶顶
雪    币: 336
活跃值: 活跃值 (16)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2011-5-10 09:37
13
0
多谢分享,简单明了
雪    币: 1112
活跃值: 活跃值 (101)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
ycmint 活跃值 5 2011-5-10 21:14
14
0
恩  http://www.xfocus.net/articles/200802/966.html
这里有个讲的 也不错.....关于 注册表项的保护....类似原理...
雪    币: 96
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
收破烂的 活跃值 2011-6-29 13:52
15
0
mark下,,谢谢楼主。
雪    币: 88
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gezz 活跃值 2011-6-29 17:19
16
0
刚想找资料 就来一篇。楼主及时雨啊~
雪    币: 277
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chadd 活跃值 2011-6-29 17:34
17
0
多谢分享!!
雪    币: 130
活跃值: 活跃值 (219)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Nermor 活跃值 1 2012-5-25 14:34
18
0
看combojiang rootkit系列,第一章object hook 由于是逆向汇编,看的不明就里。

多谢lz写的此篇 object hook! thanks!

object hook!
雪    币: 2204
活跃值: 活跃值 (691)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
木志本柯 活跃值 2018-7-8 15:44
19
0
正是因为你的懒惰所以没加精咯
雪    币: 2204
活跃值: 活跃值 (691)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
木志本柯 活跃值 2018-7-14 22:37
20
0
我遇到了一个问题你的NewParseProcedure的参数是怎么确定的,我想hook SecurityProcedure但在定义NewSecurityProcedure时要怎么确定函数的参数。
游客
登录 | 注册 方可回帖
返回