S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

CreateService加载驱动过程

Posted on 2009-10-30 08:10 S.l.e!ep.¢% 阅读(1945) 评论(1)  编辑 收藏 引用 所属分类: Windows WDM
CreateService加载驱动过程
2009-07-30 21:56

用instDrv加载驱动,用CreateService()函数等等过程如下,

1,先是它向Service进程注册服务。

2,然后Service进程调用ZwLoadDriver()加载驱动。进入NtLoadDriver()系统调用,它先会检测SerVice进程(当前进程)是不是有加载驱动的权限,然后检测当前进程是不是System进程,是的话直接调用IopLoadUnloadDriver()加载驱动,-》IopLoadDriver()最后会调用驱动的DriverEntry(),所以这种方法加载驱动的DriverEntry()函数是在System进程的地址空间执行的。

如果当前进程不是System进程的话,则调用如下的函数,向system进程的系统线程的工作队列中插入这项,函数为IopLoadUnloadDriver(),也就是说系统线程会替它调用IopLoadUnloadDriver()函数

ExInitializeWorkItem( &loadPacket.WorkQueueItem,
                              IopLoadUnloadDriver,
                              &loadPacket ); ExQueueWorkItem( &loadPacket.WorkQueueItem, DelayedWorkQueue );

IopLoadUnloadDriver会调用IopLoadDriver()做真正的加载驱动的工作

1,先根据键句柄调用NtQueryKey()函数得到驱动的全路径名。

2,循环检查PsLoadedModuleList内核模块链表看是不是这个驱动已经加载

3.调用 status = MmLoadSystemImage( &baseName,
                                NULL,
                                NULL,
                                0,
                                &sectionPointer,
                                (PVOID *) &imageBaseAddress );
   这函数里面会调用 InitializeObjectAttributes (&ObjectAttributes,
                                    ImageFileName,
                                    (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
                                    NULL,
                                    NULL);

        Status = ZwOpenFile (&FileHandle,
                             FILE_EXECUTE,
                             &ObjectAttributes,
                             &IoStatus,
                             FILE_SHARE_READ | FILE_SHARE_DELETE,
                             0);   //返回句柄为0x80000140
函数根据驱动文件名打开文件,向system进程的句柄表中插入一项,返回句柄表的下标,就是文件句柄(这里是内核句柄))

Status = MmCheckSystemImage (FileHandle, FALSE);//这个函数是检查这个PE文件各个节看是不是好的。
最后调用

InitializeObjectAttributes (&ObjectAttributes,
                                    NULL,
                                    (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
                                    NULL,
                                    NULL);

        Status = ZwCreateSection (&SectionHandle,
                                  SectionAccess,
                                  &ObjectAttributes,
                                  (PLARGE_INTEGER) NULL,
                                  PAGE_EXECUTE,
                                  SEC_IMAGE,
                                  FileHandle);
建立节对象向system进程句柄表中插入一项,返回句柄为0x80000170

Status = ObReferenceObjectByHandle (SectionHandle,
                                            SECTION_MAP_EXECUTE,
                                            MmSectionObjectType,
                                            KernelMode,
                                            (PVOID *) &SectionPointer,
                                            (POBJECT_HANDLE_INFORMATION) NULL);//根据句柄从system进程句柄中找到节对象的地址。

        ZwClose (SectionHandle);//把此句柄关了,会从system 进程句柄中删除一项。下次访问节对象时就通过地址来访问。不用句柄。

调用 Status = MiLoadImageSection (&SectionPointer,
                                 ImageBaseAddress,
                                 ImageFileName,
                                 LoadFlags & MM_LOAD_IMAGE_IN_SESSION,
                                 FoundDataTableEntry);
进行真正的文件映射它里面会调用 MmMapViewOfSection (SectionPointer,TargetProcess(system),
                                 &Base,
                                 0,
                                 0,
                                 &SectionOffset,
                                 &ViewSize,
                                 ViewUnmap,
                                 0,
                                 PAGE_EXECUTE);
进行文件映射,返回基址为0xba377000

最后分配 PKLDR_DATA_TABLE_ENTRY DataTableEntry;
初始化它,最后调用 MiProcessLoaderEntry (DataTableEntry, TRUE);
把它个内核模块结构加入PsLoadModuleList链表中等等,还会处理这个驱动的Reference等等

4,调用    status = ObCreateObject( KeGetPreviousMode(),
                             IoDriverObjectType,
                             &objectAttributes,
                             KernelMode,
                             (PVOID) NULL,
                             (ULONG) (sizeof( DRIVER_OBJECT ) + sizeof ( DRIVER_EXTENSION )),
                             0,
                             0,
                             (PVOID *) &driverObject );建立驱动对象

初始化驱动对象后,调用 status = ObInsertObject( driverObject,
                             (PACCESS_STATE) NULL,
                             FILE_READ_DATA,
                             0,
                             (PVOID *) NULL,
                             &driverHandle );把驱动对象插入到system进程的句柄表的一项,返回句柄,注意这个函数还会把这对象插入对象目录中。

5,最后会调用 status = driverObject->DriverInit( driverObject, &registryPath->Name );也就是DriverEntry()函数。

Feedback

# re: CreateService加载驱动过程  回复  更多评论   

2015-04-29 13:11 by peace
可以在内核太下直接调用这些函数来加载吗?

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理