KDM驱动程序的安装、卸载、启动、停止
acmilan2016/06/27软件综合 IP:四川

现在的Windows操作系统支持三种驱动程序模型:KDM、WDM、WDF,其中后两者没有本质区别,只是WDF是用运行库封装的WDM而已。KDM是按照NT系统服务启动的,而WDM和WDF都是用设备管理器启动的,后两者比较复杂,这里不作介绍。

安装KDM驱动(安装NT服务):

  1. 打开服务控制管理器——OpenSCManager
  2. 创建服务——CreateService
  3. 关闭所有句柄——CloseServiceHandle

删除KDM驱动(删除NT服务):

  1. 打开服务控制管理器——OpenSCManager
  2. 按名称打开服务——OpenService
  3. 删除服务——DeleteService
  4. 关闭所有句柄——CloseServiceHandle

启动KDM驱动(启动NT服务,也可以用net start命令实现):

  1. 打开服务控制管理器——OpenSCManager
  2. 按名称打开服务——OpenService
  3. 启动服务——StartService
  4. 关闭所有句柄——CloseServiceHandle

停止KDM驱动(停止NT服务,也可以用net stop命令实现):

  1. 打开服务控制管理器——OpenSCManager
  2. 按名称打开服务——OpenService
  3. 停止服务——ControlService,SERVICE_CONTROL_STOP
  4. 关闭所有句柄——CloseServiceHandle

注意:新系统要先关闭驱动程序强制签名。

【示例程序】

警告:一定要在VMWare Workstation、VirtualBox等虚拟机中测试,不要在工作用机中加载编译的驱动程序

内核模式驱动程序非常危险,可能造成蓝屏死机,重要数据损坏丢失,Windows系统损坏,甚至硬件烧毁等严重后果

命令行编译使用下面的命令:

<code class="language-bat">cl ntdrv.cpp kernel32.lib user32.lib advapi32.lib /DUNICODE /D_UNICODE
</code>

CPP代码如下:

<code class="language-cpp">// ntdrv.cpp : 定义控制台应用程序的入口点。
//

//#include "stdafx.h"  
#include <windows.h>
#include <tchar.h>

BOOL InstallNTDriver(TCHAR * svrName, TCHAR * lpszDriverPath)
{
	BOOL bRet = TRUE;

	TCHAR szDriverPath[MAX_PATH] = { 0 };

	GetFullPathName(lpszDriverPath, MAX_PATH, szDriverPath, NULL);

	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (!hSCM)
	{
		bRet = FALSE;
		goto ret;
	}

	SC_HANDLE hService = CreateService(hSCM,
		svrName,             //服务的名称  
		svrName,             //显示的名称DisplayName  
		SERVICE_ALL_ACCESS,         //访问所有权  
		SERVICE_KERNEL_DRIVER,      //表示加载的服务是驱动程序  
		SERVICE_DEMAND_START,       //启动类型为手动启动  
		SERVICE_ERROR_IGNORE,       //忽略错误  
		szDriverPath,               //驱动文件名(保护路径),注册表中的ImagePath值  
		NULL,
		NULL,
		NULL,
		NULL,
		NULL);
	if (!hService)
	{
		bRet = FALSE;
		goto ret;
	}

ret:
	if (hService)
	{
		CloseServiceHandle(hService);
	}
	if (hSCM)
	{
		CloseServiceHandle(hSCM);
	}
	return bRet;
}

BOOL StartNTDriver(TCHAR * szSvrName)
{
	BOOL bRet = TRUE;

	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (!hSCM)
	{
		bRet = FALSE;
		goto ret;
	}

	SC_HANDLE hService = OpenService(hSCM, szSvrName, SERVICE_ALL_ACCESS);
	if (!hService)
	{
		bRet = FALSE;
		goto ret;
	}

	bRet = StartService(hService, NULL, NULL);

ret:
	if (hService)
	{
		CloseServiceHandle(hService);
	}
	if (hSCM)
	{
		CloseServiceHandle(hSCM);
	}
	return bRet;
}

BOOL StopNTDriver(TCHAR * szSvrName)
{
	BOOL bRet = TRUE;

	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (!hSCM)
	{
		bRet = FALSE;
		goto ret;
	}

	SC_HANDLE hService = OpenService(hSCM, szSvrName, SERVICE_ALL_ACCESS);
	if (!hService)
	{
		bRet = FALSE;
		goto ret;
	}

	SERVICE_STATUS SvrSta = { 0 };
	bRet = ControlService(hService, SERVICE_CONTROL_STOP, &SvrSta);

ret:
	if (hService)
	{
		CloseServiceHandle(hService);
	}
	if (hSCM)
	{
		CloseServiceHandle(hSCM);
	}
	return bRet;
}

BOOL DeleteNTDriver(TCHAR * szSvrName)
{
	BOOL bRet = TRUE;

	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (!hSCM)
	{
		bRet = FALSE;
		goto ret;
	}

	SC_HANDLE hService = OpenService(hSCM, szSvrName, SERVICE_ALL_ACCESS);
	if (!hService)
	{
		bRet = FALSE;
		goto ret;
	}

	bRet = DeleteService(hService);

ret:
	if (hService)
	{
		CloseServiceHandle(hService);
	}
	if (hSCM)
	{
		CloseServiceHandle(hSCM);
	}
	return bRet;
}

void winprintf(TCHAR *fmt, ...)
{
	TCHAR buf[1024]; // wsprintf/wvsprintf只支持1024个字符
	va_list va;
	va_start(va, fmt);
	wvsprintf(buf, fmt, va);
	va_end(va);
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD written;
	if (!WriteConsole(hout, buf, lstrlen(buf), &written, 0))
	{
		WriteFile(hout, buf, lstrlen(buf) * sizeof (TCHAR), &written, 0);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	if (argc < 3)
	{
		winprintf(_T("用法:ntdrv [install|delete|start|stop] svrname [path]\r\n"));
		return 0;
	}

	if (lstrcmpi(argv[1], _T("install")) == 0)
	{
		if (argc < 4)
		{
			winprintf(_T("用法:ntdrv install svrname path\r\n"));
			return 0;
		}
		if (!InstallNTDriver(argv[2], argv[3]))
		{
			winprintf(_T("安装失败,错误码:%d\r\n"), GetLastError());
			return 1;
		}
		else
		{
			winprintf(_T("安装成功\r\n"));
			return 0;
		}
	}
	else if (lstrcmpi(argv[1], _T("delete")) == 0)
	{
		if (!DeleteNTDriver(argv[2]))
		{
			winprintf(_T("删除失败,错误码:%d\r\n"), GetLastError());
			return 1;
		}
		else
		{
			winprintf(_T("删除成功\r\n"));
			return 0;
		}
	}
	else if (lstrcmpi(argv[1], _T("delete")) == 0)
	{
		if (!DeleteNTDriver(argv[2]))
		{
			winprintf(_T("删除失败,错误码:%d\r\n"), GetLastError());
			return 1;
		}
		else
		{
			winprintf(_T("删除成功\r\n"));
			return 0;
		}
	}
	else if (lstrcmpi(argv[1], _T("start")) == 0)
	{
		if (!StartNTDriver(argv[2]))
		{
			winprintf(_T("启动失败,错误码:%d\r\n"), GetLastError());
			return 1;
		}
		else
		{
			winprintf(_T("启动成功\r\n"));
			return 0;
		}
	}
	else if (lstrcmpi(argv[1], _T("stop")) == 0)
	{
		if (!StopNTDriver(argv[2]))
		{
			winprintf(_T("停止失败,错误码:%d\r\n"), GetLastError());
			return 1;
		}
		else
		{
			winprintf(_T("停止成功\r\n"));
			return 0;
		}
	}

	return 0;
}
</tchar.h></windows.h></code>

[修改于 7年11个月前 - 2016/06/28 11:30:58]

来自:计算机科学 / 软件综合
5
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
acmilan 作者
7年11个月前 IP:四川
822023

C#对应的函数声明

<code class="language-cs">using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
    public partial class WinAPI
    {
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static IntPtr OpenSCManager(
            string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static IntPtr CreateService(
            IntPtr hSCManager, string lpServiceName, string lpDisplayName,
            uint dwDesiredAccess, uint dwServerType, uint dwStartType,
            uint dwErrorControl, string lpBinaryPathName,
            // 后面的参数都填null就行了
            string lpLoadOrderGroup, [Out] uint[] lpdwTagId, string lpDependencies,
            string lpServiceStartName, string lpPassword);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static IntPtr OpenService(
            IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool CloseServiceHandle(IntPtr hSCObject);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool StartService(
            IntPtr hService, uint dwNumServiceArgs, string[] lpServiceArgVectors);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool ControlService(
            IntPtr hService, uint dwControl, [Out] ServiceStatus lpServiceStatus);

        [StructLayout(LayoutKind.Sequential)]
        public class ServiceStatus
        {
            public uint dwServiceType;
            public uint dwCurrentState;
            public uint dwControlsAccepted;
            public uint dwWin32ExitCode;
            public uint dwServiceSpecificExitCode;
            public uint dwCheckPoint;
            public uint dwWaitHint;
        }

        public static readonly uint SC_MANAGER_ALL_ACCESS = 0xf003f;
        public static readonly uint SERVICE_ALL_ACCESS = 0xf01ff;
        public static readonly uint SERVICE_KERNEL_DRIVER = 1;
        public static readonly uint SERVICE_DEMAND_START = 3;
        public static readonly uint SERVICE_ERROR_IGNORE = 0;
        public static readonly uint SERVICE_CONTROL_STOP = 1;
    }
}
</code>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
7年10个月前 修改于 7年10个月前 IP:四川
822181
在NT4中。控制面板里专门有一项“设备”用来管理这些作为服务启动的驱动程序,在Windows 2000以后的系统中,这些驱动服务默认被隐藏了,但是仍然可以用net start和net stop管理
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
7年10个月前 IP:浙江
822215
记得通过service的方式只能加载KDM驱动,并且服务名不能和已有的冲突……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
7年10个月前 修改于 7年10个月前 IP:四川
822243
引用 phpskycn:
记得通过service的方式只能加载KDM驱动,并且服务名不能和已有的冲突……
KDM驱动现在仍然存在,比如Intel的芯片组驱动就是KDM驱动。。。只不过即插即用设备都用WDM或WDF了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
7年10个月前 修改于 7年10个月前 IP:四川
822456
KDM驱动指的是传统NT驱动中的非PNP版本
WDM驱动指的是传统NT驱动中的PNP版本
WDF驱动是对传统NT驱动的封装
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年3个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}