《Windows核心编程》第3章——handle复制相关实验
- 先写一个程序,用来查看进程的内核对象,这样我们就能比较子进程是否继承了父进程的某个句柄:
#include <windows.h>
#include <stdio.h> #define NT_SUCCESS(x) ((x) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 #define SystemHandleInformation 16
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2 typedef NTSTATUS(NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
); typedef NTSTATUS(NTAPI *_NtDuplicateObject)(
HANDLE SourceProcessHandle,
HANDLE SourceHandle,
HANDLE TargetProcessHandle,
PHANDLE TargetHandle,
ACCESS_MASK DesiredAccess,
ULONG Attributes,
ULONG Options
); typedef NTSTATUS(NTAPI *_NtQueryObject)(
HANDLE ObjectHandle,
ULONG ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
); typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING; typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE; typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; typedef enum _POOL_TYPE
{
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE; typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
{
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
} int main(int argc, WCHAR *argv[])
{
NTSTATUS status;
ULONG pid;
HANDLE processHandle;
ULONG handleInfoSize = 0x10000;
PSYSTEM_HANDLE_INFORMATION handleInfo;
HANDLE dupHandle = NULL;
ULONG returnLength;
int nCount = ;
pid = ;//Input which process do you want to query. _NtQuerySystemInformation NtQuerySystemInformation =
(_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
if (NULL == NtQuerySystemInformation){
printf("Get address of NtQuerySystemInformation failed!\n");
return FALSE;
} _NtDuplicateObject NtDuplicateObject =
(_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
if (NULL == NtDuplicateObject){
printf("Get address of NtDuplicateObject failed!\n");
return FALSE;
} _NtQueryObject NtQueryObject =
(_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
if (NULL == NtQueryObject){
printf("Get address of NtQueryObject failed!\n");
return FALSE;
} if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid))){
printf("Open process failed!\n");
return FALSE;
} handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
while ((status = NtQuerySystemInformation(//Query system handle information, if return STATUS_INFO_LENGTH_MISMATCH, you should realloc space.
SystemHandleInformation,
handleInfo,
handleInfoSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH){
handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= );//assign new value to handleInfoSize }
if (!NT_SUCCESS(status))
{
return FALSE;
} for (int i = ; i < handleInfo->HandleCount; i++)//reverse all handles
{
SYSTEM_HANDLE handle = handleInfo->Handles[i];
POBJECT_TYPE_INFORMATION objectTypeInfo;
PVOID objectNameInfo;
UNICODE_STRING objectName; if (handle.ProcessId != pid)
continue; if (!NT_SUCCESS(status = NtDuplicateObject(//duplicate handle information into self.
processHandle,
(HANDLE)handle.Handle,
GetCurrentProcess(),
&dupHandle,
,
, )))
{
continue;
} ////////////////////////////////////////////////////////////////////////////////////
//you can query objectNameInfo directly.
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
if (!NT_SUCCESS(status = NtQueryObject(//Get the object according handle.
dupHandle,
ObjectTypeInformation,
objectTypeInfo,
0x1000,
NULL
)))
{
printf("Query [%#x] Error:%x!\n", handle.Handle, status);
CloseHandle(dupHandle);
continue;
} if (handle.GrantedAccess == 0x0012019f)
{
/* We have the type, so display that. */
printf(
"[%#x] %.*S: (did not get name)\n",
handle.Handle,
objectTypeInfo->Name.Length / ,
objectTypeInfo->Name.Buffer
);
free(objectTypeInfo);
CloseHandle(dupHandle);
continue;
} objectNameInfo = malloc(0x1000);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
0x1000,
&returnLength
))){
objectNameInfo = realloc(objectNameInfo, returnLength);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
returnLength,
NULL
)))
{
/* We have the type name, so just display that. */
printf(
"[%#x] %.*S: (could not get name)\n",
handle.Handle,
objectTypeInfo->Name.Length / ,
objectTypeInfo->Name.Buffer
);
free(objectTypeInfo);
free(objectNameInfo);
CloseHandle(dupHandle);
continue;
}
}
objectName = *(PUNICODE_STRING)objectNameInfo; if (objectName.Length)
{
/* The object has a name. */
printf(
"[%#x] %.*S: %.*S\n",
handle.Handle,
objectTypeInfo->Name.Length / ,
objectTypeInfo->Name.Buffer,
objectName.Length / ,
objectName.Buffer
);
}
else
{
/* Print something else. */
printf(
"[%#x] %.*S: (unnamed)\n",
handle.Handle,
objectTypeInfo->Name.Length / ,
objectTypeInfo->Name.Buffer
);
} nCount++;
free(objectTypeInfo);
free(objectNameInfo);
CloseHandle(dupHandle);
}
printf("Handle Count:%d\n", nCount); free(handleInfo);
CloseHandle(processHandle);
getchar();
}
- 然后父进程就随便写一个,主要是为了创建三个命名内核对象,然后让子进程继承其中的两个:
#include <iostream>
#include <windows.h>
void main(){
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;//if the handle can be inherited. HANDLE hMuxtex1 = CreateMutex(&sa, FALSE, "TestHandle1");
HANDLE hMuxtex2 = CreateMutex(NULL, FALSE, "TestHandle2");
HANDLE hMuxtex3 = CreateMutex(&sa, FALSE, "TestHandle3");
STARTUPINFO si;
PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CreateProcess(NULL, "E:\\Coding\\Cpp\\test\\Windows_Core\\P96_3\\Debug\\P96_3.exe", NULL, NULL, TRUE, , NULL, NULL, &si, &pi);
while (TRUE);
}
- 验证结果
父进程创建的三个互斥量句柄:

然后再去查看子进程:

果然之继承了其中的1和3句柄。
《Windows核心编程》第3章——handle复制相关实验的更多相关文章
- windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题
// 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ...
- windows核心编程 第5章job lab示例程序 解决小技巧
看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里” 用process explorer程序查看 ...
- Windows核心编程 第十一章 线程池的使用
第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...
- Windows核心编程 第三章 内核对象
第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...
- 《windows核心编程》 17章 内存映射文件
内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以 ...
- Windows核心编程 第27章 硬件输入模型和局部输入状态
第27章 硬件输入模型和局部输入状态 这章说的是按键和鼠标事件是如何进入系统并发送给适当的窗口过程的.微软设计输入模型的一个主要目标就是为了保证一个线程的动作不要对其他线程的动作产生不好的影响. 27 ...
- Windows核心编程 第十七章 -内存映射文件(下)
17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...
- Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)
7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...
- Windows核心编程 第四章 进程(中)
4.2 CreateProcess函数 可以用C r e a t e P r o c e s s函数创建一个进程: BOOL CreateProcessW( _In_opt_ LPCWSTR lpAp ...
随机推荐
- USACO 5.3 Network of Schools
Network of SchoolsIOI '96 Day 1 Problem 3 A number of schools are connected to a computer network. A ...
- HBase的基础知识
1.HBase(NoSQL:不是关系型数据库)的逻辑数据模型 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC S ...
- js获取单个查询串的值
function getSearchString(key) { // 获取URL中?之后的字符 var searchArr= window.location.href.split('#')[0].sp ...
- Sqlite可视化工具sqliteman安装(转)
Sqlite可视化工具sqliteman安装 1.安装前准备 系统要求:RedHat 6.9 Qt库版本:4.2及以上 2.安装文件 采用源码方式安装 可用下面地址自行下载 https://s ...
- QString::arg()//用字符串变量参数依次替代字符串中最小数值
QString i = "iTest"; // current file's number QString total = "totalTest&qu ...
- SQL注入备忘录
备忘录(一) 拿起小本本记下常考知识点. 常用连接词 and && %23%23 且 or || %7c%7c 或 xor 非 Access 数据库: 只能爆破表名.列名获取数据.无法 ...
- 一列道出yield和生成器的真谛
均匀大小的块 def chunks(l, n): """Yield successive n-sized chunks from l.""" ...
- [ 转载 ] Centos 安装mysql后启动失败 出现 ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’
MySQL Daemon failed to start Mysql出问题一定要学会查看log https://blog.csdn.net/shuai825644975/article/details ...
- Redis在Window服务下的安装
Redis 安装 1.首先在Windows下下载安装Redis 下载地址:https://github.com/MicrosoftArchive/redis/releases 根据你电脑系统的实际情况 ...
- python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐(二)
在上一篇blog:python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 中介绍了python中的tkinter的一些东西,你可能对tkinter有一定的了解了.这篇b ...