用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,
§ionPointer,
(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, ®istryPath->Name );也就是DriverEntry()函数。