首页
社区
课程
招聘
5
[原创]Win32Asm 驱动学习笔记<5> 驱动程序的安装与卸载
发表于: 2013-8-16 11:21 8863

[原创]Win32Asm 驱动学习笔记<5> 驱动程序的安装与卸载

2013-8-16 11:21
8863

Win32Asm 驱动学习笔记 第五章《 驱动程序的安装与卸载》

     
版权声明

         本文所述内容很多来自互联网以及其他一些参考资料,并不是全部原创,属于学习笔记汇总,凡因此文引发的版权问题,作者本人不负任何责任。

自序

      虽我未学,下笔无文,然驱动入门之路何其曲折,何妨我将其倾注于笔墨文字,因其内容多引用经典,作者心得体会穿插其间,故不敢擅称教程,借以笔记之说,攒此文字,以谓后来者。
      另外,作者不才,内容错漏之处还请海涵指正,谢谢。

第五章 驱动程序的安装与卸载
本章目录:
5.1  Windows服务
5.2  服务控制管理器(SCM)
5.3  服务控制程序(SCP)
     5.3.1 建立到SCM的连接
     5.3.2 安装一个新的驱动
     5.3.3 打开已存在的驱动
     5.3.4  停止已存在的驱动
     5.3.5 启动驱动程序
     5.3.6 卸载驱动
5.4 通用模板
     5.4.1 模板的建立
     5.4.2 模板的导入

5.5 本章小结

正文开始:
      前面我们学到了一个简单的驱动程序“beeper.sys”,今天我们来学习怎么自己编程来加载它,我们前面介绍过,NT式驱动的加载与卸载是基于服务的, 我们先来简单介绍下Windows服务吧,在这方面罗云彬翻译的KmdTut中文版里介绍的不错,我对原文进行了适当的补充完善后摘抄入此,内容如下:
5.1 Windows服务    
      Windows  NT使用某种机制来启动进程,并让它们不和某个具体的交互式的用户界面相关联,这些进程就被称为服务(service),服务的一个很好的例子就是Web 服务器,这些Web服务都没有用户界面,服务是唯一以这种方式运行的应用程序(注:指没有用户界面,当然,严格地说病毒、木马以及所有不想见光的程序也是 这样的~~),服务可以在系统启动的时候自动启动,也可以被手工启动,从这一点来看,设备驱动程序和服务是类似的。
    Windows  NT还支持驱动程序服务,只要使用的时候遵循设备驱动程序协议就可以了,这和用户模式的服务类似,所以,"服务"一词既可以指用户模式的服务进程或者内核 模式的设备驱动程序,微软不知何故没有明确地区分两者的概念,所以下面的叙述可能看起来有点让人疑惑。可能有的地方我会说到"driver"一词,但在其 他的文章中可能说到"service"一词,但既然这篇教程讲的是如何编写内核设备驱动程序,那么我们就约定无论说到"service"还 是"driver",我们的意思都是指"驱动程序",当的确需要提及"服务"的时候,我会明确地指出来的。
    另外,请读者时刻记得,文档中关于服务管理的函数其实是叙述得相当含糊的,因为这些函数既能用于驱动程序也能用于服务,在下面的文章中,我们只强调它们在驱动方面的用途和忽略服务方面的用途。
    Windows NT中有主要有两个组件和服务管理相关:
◎ 服务控制管理器(Service Control Manager/SCM)--用于启动服务以及和它通讯
◎ 服务控制程序(Service Control Program/SCP)--用于和SCM进行通讯,告诉它何时启动或者停止服务

    服务程序中包含可执行代码,这两个组件对服务和驱动程序的处理方式是相同的。我们先来看看这两个组件,在后面再讲述驱动程序。

5.2 服务控制管理器(SCM)
       SCM的代码位于\%SystemRoot%\System32\Services.exe中,当系统启动的时候,SCM被WinLogon进程启动,然 后它扫描注册表中HKLM\SYSTEM\CurrentControlSet\Services键下的相关内容,根据这些内容创建一个服务数据库,数据 库中包括所有服务的相关参数,如果服务或者驱动被标为自动启动的,那么启动它们并检测启动中是否出错。
    为了更深入一步,我们可以用注册表编辑器regedit.exe来打开并观察注册表中的 HKLM\SYSTEM\CurrentControlSet\Services\下面的内容。
    想要查看系统中安装了哪些服务(注意不是驱动),可以在控制面板中选择"管理工具",再打开"服务"来查看。
    要查看系统中安装了哪些驱动,可以在控制面板中选择"管理工具",再打开"计算机管理",在"系统信息"下的"软件环境"中,你可以看到所有驱动的列表,但是不幸的是,在Windows XP中,这个功能被取消了。
    仔细对比一下上面三个地方的内容,我们可以发现这些内容是很一致的。
    HKLM\SYSTEM\CurrentControlSet\Services\下面有很多子键,表示一个服务的内部名称,每个子键下包含了和这个服务相关的参数。
    现在来考察一下安装一个服务所需的最低数量的参数,我们拿前面提到beeper.sys来举例。



图5.1 beeper.sys驱动的注册表键值

    这些参数的含义如下:

◎ DisplayName--用户程序访问服务时使用的名称;

◎ ErrorControl--如果SCM启动服务的时候驱动报错,这个值决定了SCM如何对付这个错误,我们对两种取值有点兴趣:
· SERVICE_ERROR_IGNORE (0)--I/O管理器忽略这个错误,不作记录
· SERVICE_ERROR_NORMAL (1)--如果驱动被装入的时候报错,系统将给用户显示一个告警框,并将错误记录到系统日志中

      你可以在控制面板中的"管理工具"中选择"事件查看器"来查看系统日志,例如,beeper.sys驱动在初始化的时候做完了所有该做的事(这个例子会让 喇叭发声音,但是发声功能是在初始化函数DriverEntry中做的,初始化函数执行完,后面就没什么事了),所以它就返回一个错误,系统就会将它从内 存中卸载。但是这里的ErrorControl参数等于SERVICE_ERROR_IGNORE,所以系统日志中并没有错误记录。

◎ ImagePath--指驱动文件的全路径文件名,如果该参数没有指定路径,那么系统会在\%SystemRoot%\Drivers目录下查找
◎ Start--指明何时装载驱动,这里我们关心的也是两个取值
· SERVICE_AUTO_START (2)--驱动在系统启动的时候装载
· SERVICE_DEMAND_START (3)--驱动由SCM根据用户要求装载

     如果驱动的Start参数为SERVICE_AUTO_START  (2),那么SCM会在系统启动的时候就装载它,这样的驱动被称为自动启动的服务,如果驱动的执行依赖于其他的驱动,SCM也会把其他的驱动也启动起来 (要控制设备驱动被装载的顺序,可以使用Group、Tag和DependOnGroup等参数值;要控制服务被装载的顺序,可以使用Group和 DependOnService参数)。Start参数还有其他的取值,如SERVICE_BOOT_START  (0),但这个参数只能供设备驱动程序使用,I/O管理器将在用户模式的进程启动之前把装载这些驱动程序,这时SCM还没有启动呢!

◎ Type--用于指定服务的类型,既然我们这里讲的是KMD的编程,那么我们只对一个取值感兴趣,那就是SERVICE_KERNEL_DRIVER (1)

    仔细观察图5.1后,你对beeper.sys有什么要说的吗?好的,我们看到beeper这个内核模式驱动程序位于”D:\RadASM\Masm\Projects\beeper"目录下,它的名称为"beeper",由用户控制启动,出错信息不被记录。
    Path前面的"\??"前缀的含义你下面就会知道!
    如果我们要启动SCM数据库中不存在的驱动程序,那么可以在任何时刻在SCP的帮助下动态装入(也许称为DCP/device control program更为贴切,但是微软的术语库中并没有这个词)。

5.3 服务控制程序(SCP)

     从名称理解,服务控制程序(service control  program/SCP)可以控制服务或者设备驱动程序,这些功能是在SCM的管理下,通过调用适当的函数来完成的,这些函数位 于\%SystemRoot%\System32\advapi.dll (Advanced API)中。
    这里是一段关于使用SCP来控制beeper.sys驱动的代码例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;  Service Control Program for beeper driver
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.386
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                             I N C L U D E   F I L E S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
include \RadASM\masm32\Macros\Strings.mac
 
 
 includelib debug.lib
 include debug.inc
; ----------------------debug-------------------------------
; PrintError
; PrintText<"debug message!">
; PrintString<driver>
; PrintStringByAddr<offset driver>
; PrintDword<hSCManager,driver>
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       C O D E
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code
start proc
local hSCManager:HANDLE
local hService:HANDLE
local acDriverPath[MAX_PATH]:CHAR
LOCAL bRet:BOOL
LOCAL SvrSta
     
    invoke OpenSCManager, NULL, NULL, SC_MANAGER_CREATE_SERVICE
     
     mov hSCManager, eax
     
     PrintDec hSCManager
    
    .if hSCManager != NULL
           
       invoke GetFullPathName, $CTA0("beeper.sys"),sizeof acDriverPath,addr acDriverPath,NULL
       PrintString acDriverPath
         
       invoke CreateService, hSCManager, $CTA0("beeper"), $CTA0("Beeper"), \
                SERVICE_START + DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, \
                SERVICE_ERROR_IGNORE, addr acDriverPath, NULL, NULL, NULL, NULL, NULL
        mov hService, eax
        
        PrintDec hService
        
         .if hService==NULL
                   
              PrintError
             
              invoke GetLastError
            
              ; 服务创建失败,是由于服务已经创立过
              .if  eax==ERROR_IO_PENDING || eax==ERROR_SERVICE_EXISTS   ||  eax==ERROR_SERVICE_MARKED_FOR_DELETE
                    
                    invoke OpenService ,hSCManager,$CTA0("beeper"), SERVICE_ALL_ACCESS
                    mov hService, eax
                    push eax
                    ;如果打开服务也失败,则意味错误
                     .if eax==NULL
                              pop eax
                              PrintError
                              jmp exit
                       
                        .endif
                     pop eax 
                      
                      
                     ;服务创建失败,是由于服务已经标记删除 
                     .if  eax==ERROR_SERVICE_MARKED_FOR_DELETE
                    
                          invoke ControlService,hService,SERVICE_CONTROL_STOP, addr SvrSta
                          invoke CloseServiceHandle,hService
                           
                          ;再次创建
                          invoke CreateService, hSCManager, $CTA0("beeper"), $CTA0("beeper"), \
                SERVICE_START + DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, \
                SERVICE_ERROR_IGNORE, addr acDriverPath, NULL, NULL, NULL, NULL, NULL
                             
                           ;如果再次创建再失败,则意味着错误                      
                          .if eax==NULL
                           
                               PrintError
                                mov bRet,FALSE
                                jmp exit
                               
                          .endif
                          
   
                       .endif
                        
                 ;由于其他原因创建服务失败
                .else
                   
                   PrintText "注册驱动时出错,出错信息如下:"
                   PrintError                
                   mov bRet,FALSE
                   jmp exit
                
         
                .endif
               
          .endif
            
            invoke StartService, hService, 0, NULL
            invoke DeleteService, hService
             
      
     .else
      
 
            invoke MessageBox, NULL, $CTA0("打开服务管理器出错."), \
                            NULL, MB_ICONSTOP
         
            PrintText "打开服务管理器出错"
            PrintError
         
    .endif
    
     
    exit:
     
      .if  hService
 
               invoke CloseServiceHandle ,hService ; 服务句柄
     .endif
      
      .if hSCManager
 
             invoke CloseServiceHandle ,hSCManager; SCM句柄
     
      .endif
       
    invoke ExitProcess, 0
     
start endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
end start

[注意]看雪招聘,专注安全领域的专业人才平台!

上传的附件:
收藏
免费 5
支持
分享
赞赏记录
参与人
雪币
留言
时间
心游尘世外
为你点赞~
2024-5-31 06:07
QinBeast
为你点赞~
2024-5-31 05:59
飘零丶
为你点赞~
2024-4-3 00:51
shinratensei
为你点赞~
2024-2-23 01:58
PLEBFE
为你点赞~
2023-3-5 04:19
最新回复 (7)
雪    币: 27
活跃值: (122)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
非安全果然酷爱Win32 ASM

希望能坚持这个系列教程,并且能逐步加深 : )
2013-8-16 11:30
0
雪    币: 750
活跃值: (227)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
3
呵呵 ,我会的,谢谢支持。
2013-8-16 11:50
0
雪    币: 103991
活跃值: (201949)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
4
+1
2013-8-16 13:50
0
雪    币: 750
活跃值: (227)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
5
谢谢支持,每次都能看到你额
2013-8-16 14:06
0
雪    币: 259
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
写得很多都没有涉及一个问题,这些驱动程序与应用程序之间的通迅就是不成功(I/O控制),点击后总是提示:“控制失败:系统找不到指定的文件。”,难道你从来没有遇到过吗?能解决吗?
2014-7-2 19:41
0
雪    币: 750
活跃值: (227)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
7
名称不对的问题吧,你可以看下我相关的例子有完整的实例,下面的笔记会讲到I/O通讯,只是我还没有时间完成。
2014-7-5 06:22
0
雪    币: 259
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢,就是名称的问题,和文件名一致就可以了
2014-8-12 11:18
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册