tqsheng

go.....
随笔 - 366, 文章 - 18, 评论 - 101, 引用 - 0
数据加载中……

360注册表操作原理分析

分类: 转载2011-08-09 10:25 281人阅读 评论(0) 收藏 举报
 
360注册表操作原理分析 (前段闲的蛋疼才分析的,错误的,大牛们请指出) 
360为了有效的对注册表进行操作,绕过了RegXXXX函数的使用,自己封装了一套API:BAPI.DLL 以及BAPIDRY.SYS来实现可靠的,有效的注册表和文件操作; 
调用流程如下: 
(以BRegDeleteKey为例) 
对BRegDeleteKey的封装在Ring 3模仿了微软的做法,BRegDeleteKey-->BRegDeleteKeyW之类的, 
对于BRegDeleteKeyW则不再调用NtDeleteKey,而是利用了ZwDeviceIoControl向BAPIDRY.SYS发控制码,自己驱动去做NtDeleteKey做的操作; 
关键在于360 Reg操作所用的方式:通过CmRegXXXX实现,360是如何可靠的获取CmRegXXXX的地址的呢?如下: 
1、通过打开注册表的键值,获取注册表类型的objectType 
2、打开两个注册表项,获取对象以待后面用 
3、对其中一个注册表对象 

nt!_CM_KEY_BODY 
+0x000 Type : Uint4B 
+0x004 KeyControlBlock : Ptr32 _CM_KEY_CONTROL_BLOCK 
+0x008 NotifyBlock : Ptr32 _CM_NOTIFY_BLOCK 
+0x00c ProcessID : Ptr32 Void 
+0x010 Callers : Uint4B 
+0x014 CallerAddress : [10] Ptr32 Void 
+0x03c KeyBodyList : _LIST_ENTRY 

里面的CM_KEY_CONTROL_BLOCK. 
nt!_CM_KEY_CONTROL_BLOCK 
+0x000 RefCount : Uint4B 
+0x004 ExtFlags : Pos 0, 8 Bits 
+0x004 PrivateAlloc : Pos 8, 1 Bit 
+0x004 Delete : Pos 9, 1 Bit 
+0x004 DelayedCloseIndex : Pos 10, 12 Bits 
+0x004 TotalLevels : Pos 22, 10 Bits 
+0x008 KeyHash : _CM_KEY_HASH 
+0x008 ConvKey : Uint4B 
+0x00c NextHash : Ptr32 _CM_KEY_HASH 
+0x010 KeyHive : Ptr32 _HHIVE 
+0x014 KeyCell : Uint4B 
+0x018 ParentKcb : Ptr32 _CM_KEY_CONTROL_BLOCK 
+0x01c NameBlock : Ptr32 _CM_NAME_CONTROL_BLOCK 
+0x020 CachedSecurity : Ptr32 _CM_KEY_SECURITY_CACHE 
+0x024 ValueCache : _CACHED_CHILD_LIST 
+0x02c IndexHint : Ptr32 _CM_INDEX_HINT_BLOCK 
+0x02c HashKey : Uint4B 
+0x02c SubKeyCount : Uint4B 
+0x030 KeyBodyListHead : _LIST_ENTRY 
+0x030 FreeListEntry : _LIST_ENTRY 
+0x038 KcbLastWriteTime : _LARGE_INTEGER 
+0x040 KcbMaxNameLen : Uint2B 
+0x042 KcbMaxValueNameLen : Uint2B 
+0x044 KcbMaxValueDataLen : Uint4B 
+0x048 KcbUserFlags : Pos 0, 4 Bits 
+0x048 KcbVirtControlFlags : Pos 4, 4 Bits 
+0x048 KcbDebug : Pos 8, 8 Bits 
+0x048 Flags : Pos 16, 16 Bits 
里面的HHIVE 

nt!_HHIVE 
+0x000 Signature : Uint4B 
+0x004 GetCellRoutine : Ptr32 _CELL_DATA* 
+0x008 ReleaseCellRoutine : Ptr32 void 
+0x00c Allocate : Ptr32 void* 
+0x010 Free : Ptr32 void 
+0x014 FileSetSize : Ptr32 unsigned char 
+0x018 FileWrite : Ptr32 unsigned char 
+0x01c FileRead : Ptr32 unsigned char 
+0x020 FileFlush : Ptr32 unsigned char 
+0x024 BaseBlock : Ptr32 _HBASE_BLOCK 
+0x028 DirtyVector : _RTL_BITMAP 
+0x030 DirtyCount : Uint4B 
+0x034 DirtyAlloc : Uint4B 
+0x038 RealWrites : UChar 
+0x03c Cluster : Uint4B 
+0x040 Flat : UChar 
+0x041 ReadOnly : UChar 
+0x042 Log : UChar 
+0x044 HiveFlags : Uint4B 
+0x048 LogSize : Uint4B 
+0x04c RefreshCount : Uint4B 
+0x050 StorageTypeCount : Uint4B 
+0x054 Version : Uint4B 
+0x058 Storage : [2] _DUAL 
里面的函数HvpGetCellMapped进行hook,在而后分别对哪两个打开的注册表项进行若干的注册表操作(调用前面获取的NtRegxxx来完成),那么360为什么要hook那个函数腻,原因是,NtRegxxxx的若干操作会调用相应的CmRegxxxx来完成,而CmRegxxx又会调用HvpGetCellMapped这个函数,Fake_HvpGetCellMapped的作用很简单: 
假设对那个自己的测试键值调用了NtSetValueKey,在找个函数里可以找到如下代码: 
if (NT_SUCCESS(status)) 

status = CmSetValueKey(........) 


这里就是和谐的CmSetValueKey,当这个东西运行,在这个函数里可以找到调用了HvpGetCellMapped这个函数,然而现在却调用了Fake_HvpGetCellMapped这个函数,找个函数里面通过栈回溯机制,定位到上面那个图的代码对应的 
CALL CmpSetValueKey,(栈回溯是通过找个函数的第一个参数 
作为回溯查找对象的,前面打开自己的注册表时保存了找个值,这样就确定了CmRegxxxx的地址。 

后面还有一段用于校验CmRegxxxx是否被inline hook的,就不说了。 

360操作注册表

分类: 转载 281人阅读 评论(0) 收藏 举报
 
360注册表操作原理分析 (前段闲的蛋疼才分析的,错误的,大牛们请指出) 
360为了有效的对注册表进行操作,绕过了RegXXXX函数的使用,自己封装了一套API:BAPI.DLL 以及BAPIDRY.SYS来实现可靠的,有效的注册表和文件操作; 
调用流程如下: 
(以BRegDeleteKey为例) 
对BRegDeleteKey的封装在Ring 3模仿了微软的做法,BRegDeleteKey-->BRegDeleteKeyW之类的, 
对于BRegDeleteKeyW则不再调用NtDeleteKey,而是利用了ZwDeviceIoControl向BAPIDRY.SYS发控制码,自己驱动去做NtDeleteKey做的操作; 
关键在于360 Reg操作所用的方式:通过CmRegXXXX实现,360是如何可靠的获取CmRegXXXX的地址的呢?如下: 
1、通过打开注册表的键值,获取注册表类型的objectType 
2、打开两个注册表项,获取对象以待后面用 
3、对其中一个注册表对象 

nt!_CM_KEY_BODY 
+0x000 Type : Uint4B 
+0x004 KeyControlBlock : Ptr32 _CM_KEY_CONTROL_BLOCK 
+0x008 NotifyBlock : Ptr32 _CM_NOTIFY_BLOCK 
+0x00c ProcessID : Ptr32 Void 
+0x010 Callers : Uint4B 
+0x014 CallerAddress : [10] Ptr32 Void 
+0x03c KeyBodyList : _LIST_ENTRY 

里面的CM_KEY_CONTROL_BLOCK. 
nt!_CM_KEY_CONTROL_BLOCK 
+0x000 RefCount : Uint4B 
+0x004 ExtFlags : Pos 0, 8 Bits 
+0x004 PrivateAlloc : Pos 8, 1 Bit 
+0x004 Delete : Pos 9, 1 Bit 
+0x004 DelayedCloseIndex : Pos 10, 12 Bits 
+0x004 TotalLevels : Pos 22, 10 Bits 
+0x008 KeyHash : _CM_KEY_HASH 
+0x008 ConvKey : Uint4B 
+0x00c NextHash : Ptr32 _CM_KEY_HASH 
+0x010 KeyHive : Ptr32 _HHIVE 
+0x014 KeyCell : Uint4B 
+0x018 ParentKcb : Ptr32 _CM_KEY_CONTROL_BLOCK 
+0x01c NameBlock : Ptr32 _CM_NAME_CONTROL_BLOCK 
+0x020 CachedSecurity : Ptr32 _CM_KEY_SECURITY_CACHE 
+0x024 ValueCache : _CACHED_CHILD_LIST 
+0x02c IndexHint : Ptr32 _CM_INDEX_HINT_BLOCK 
+0x02c HashKey : Uint4B 
+0x02c SubKeyCount : Uint4B 
+0x030 KeyBodyListHead : _LIST_ENTRY 
+0x030 FreeListEntry : _LIST_ENTRY 
+0x038 KcbLastWriteTime : _LARGE_INTEGER 
+0x040 KcbMaxNameLen : Uint2B 
+0x042 KcbMaxValueNameLen : Uint2B 
+0x044 KcbMaxValueDataLen : Uint4B 
+0x048 KcbUserFlags : Pos 0, 4 Bits 
+0x048 KcbVirtControlFlags : Pos 4, 4 Bits 
+0x048 KcbDebug : Pos 8, 8 Bits 
+0x048 Flags : Pos 16, 16 Bits 
里面的HHIVE 

nt!_HHIVE 
+0x000 Signature : Uint4B 
+0x004 GetCellRoutine : Ptr32 _CELL_DATA* 
+0x008 ReleaseCellRoutine : Ptr32 void 
+0x00c Allocate : Ptr32 void* 
+0x010 Free : Ptr32 void 
+0x014 FileSetSize : Ptr32 unsigned char 
+0x018 FileWrite : Ptr32 unsigned char 
+0x01c FileRead : Ptr32 unsigned char 
+0x020 FileFlush : Ptr32 unsigned char 
+0x024 BaseBlock : Ptr32 _HBASE_BLOCK 
+0x028 DirtyVector : _RTL_BITMAP 
+0x030 DirtyCount : Uint4B 
+0x034 DirtyAlloc : Uint4B 
+0x038 RealWrites : UChar 
+0x03c Cluster : Uint4B 
+0x040 Flat : UChar 
+0x041 ReadOnly : UChar 
+0x042 Log : UChar 
+0x044 HiveFlags : Uint4B 
+0x048 LogSize : Uint4B 
+0x04c RefreshCount : Uint4B 
+0x050 StorageTypeCount : Uint4B 
+0x054 Version : Uint4B 
+0x058 Storage : [2] _DUAL 
里面的函数HvpGetCellMapped进行hook,在而后分别对哪两个打开的注册表项进行若干的注册表操作(调用前面获取的NtRegxxx来完成),那么360为什么要hook那个函数腻,原因是,NtRegxxxx的若干操作会调用相应的CmRegxxxx来完成,而CmRegxxx又会调用HvpGetCellMapped这个函数,Fake_HvpGetCellMapped的作用很简单: 
假设对那个自己的测试键值调用了NtSetValueKey,在找个函数里可以找到如下代码: 
if (NT_SUCCESS(status)) 

status = CmSetValueKey(........) 


这里就是和谐的CmSetValueKey,当这个东西运行,在这个函数里可以找到调用了HvpGetCellMapped这个函数,然而现在却调用了Fake_HvpGetCellMapped这个函数,找个函数里面通过栈回溯机制,定位到上面那个图的代码对应的 
CALL CmpSetValueKey,(栈回溯是通过找个函数的第一个参数 
作为回溯查找对象的,前面打开自己的注册表时保存了找个值,这样就确定了CmRegxxxx的地址。 
后面还有一段用于校验CmRegxxxx是否被inline hook的,就不说了。 

posted on 2013-02-11 21:08 tqsheng 阅读(1293) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理