内核对象:用来管理进程,线程,文件等诸多种类的大量资源。
内核对象只是一个内存块,由操作系统分配,并只能由操作系统访问。
内核对象的句柄表(由进程中的所有线程访问):
索引 | 指向内核对象内存块的指针 | 访问掩码 | 标志 |
1 | 0xF0000000 | 0x??????? | 0x0000000 |
1. 创建内核对象,举例如下
CreateFile(PCTSTR PszFIleName, DWORD dwDesiredAccess, DWORD dwShareMode, PSECURITY_ATTRIBUTES psa, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);//创建文件内核对象
2. 关闭内核对象,举例如下
CloseHandle(HANDLE hobjiect);//作用是将内核对象的使用计数减1,如果为0时,销毁内核对象,不管是否销毁,该进程的所有线程不能访问该内核对象。
由于内核对象的具有安全属性,并且不同进程的内核对象存在于各自进程的地址中,如何跨进程访问内核对象呢?
三种机制实现上述功能:
一、使用对象句柄继承,举例如下:
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
Handle hMutex = CreateMutex(&sa, FALSE, NULL);
进程句柄表的表现如何?当标志一栏的数值为1时,即代表该内核对象可以被继承。
索引 | 指向内核对象内存块的指针 | 访问掩码 | 标志 |
1 | 0xF0000000 | 0x??????? | 0x0000000 |
2 | 0x00000000 | (不可用) | (不可用) |
1 | 0xF0000010 | 0x??????? | 0x0000001 |
如何让子进程能够使用父进程的对象句柄呢?举例如下:
Bool CreatePorcess()中将安全描述符的继承参数设置为TRUE;这样的作用是什么呢?
创建子进程后,子进程不会立即运行,而是等待遍历父进程的进程句柄表,将标志为1即可以继承的句柄复制到子进程的句柄表,同时将句柄的使用计数加1。
如何将句柄值传递给子进程呢?
1. 采用命令行的方式。2. 让父进程等待子进程完成初始化,然后父进程可以将一条消息发送到由子进程中的一个线程创建的一个窗口。3.父进程向环境快中添加一个环境变量。
二、为对象命名
举例:CreateMutex(PSECURITY_ATTRIBUTES psa, BOOL bInitialOwner, PCTSTR psaName);
原理如果进程A创建一个命名的内核对象。进程B调用Create函数创建同样名字的内核对象时,系统首先会检查是否存在该名字的内核对象,如果存在进一步检查访问安全性,如果OK就会在进程B中创建进程A同样的进程句柄表。但是由于系统无法保证内核对象名称的唯一性,为此我们可以采用OpenMutex的方式,如果存在系统会在进程B复制内核对象的句柄表,否则返回失败。
三、复制对象句柄
DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, PHANDLE phTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions);
这个函数获得一个进程的句柄表中的一个记录项,然后在另一个进程的句柄表中创建这个记录项的一个副本。
第一个参数是当前的源进程句柄;第二参数是当前的资源句柄;第三个是目标进程的句柄,
第四个是你要得到的目的句柄,这里应该是一个变量,使用指针,DuplicateHandle函数会将得到的句柄设置到这个参数上,
第五个是访问的方式,
第六个参数是得到的句柄能不能被得到的其的进程的子进程继承。
如果第七个参数是DUPLICATE_SAME_ACCESS flag标志,那么这个参数将被忽略,
1. DuplicateHandle获得一个进程句柄表中的一个记录项,然后在另一个进程的句柄表中创建这个记录项的一个副本。2. DuplicateHandle 中dwOptions参数可以指定DUPLICATE_SAME_ACCESS和DUPLICATE_CLOSE_SOURCE标志。如果指定DUPLICATE_SAME_ACCESS标志将希望目标句柄拥有与源进程的句柄一样的访问掩码。如果指定DUPLICATE_CLOSE_SOURCE标志,会关闭源进程的句柄。使用这个标志,内核对象计数不会受到影响。
3. DuplicateHandle 函数与继承一样,目标进程并不知道它现在能访问一个新的内核对象,所以源进程以某种方式通知目标进程。与继承不一样的是,源进程不能使用命令行参数或更改目标进程的环境变量。
4. 可以利用DuplicateHandle修改内核对象的访问权限
5.绝对不能使用CloseHandle函数关闭通过phTargetHandle参数返回的句柄。