• 先写一个程序,用来查看进程的内核对象,这样我们就能比较子进程是否继承了父进程的某个句柄:
#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复制相关实验的更多相关文章

  1. windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题

    // 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ...

  2. windows核心编程 第5章job lab示例程序 解决小技巧

    看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里”         用process explorer程序查看 ...

  3. Windows核心编程 第十一章 线程池的使用

    第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...

  4. Windows核心编程 第三章 内核对象

    第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...

  5. 《windows核心编程》 17章 内存映射文件

    内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以 ...

  6. Windows核心编程 第27章 硬件输入模型和局部输入状态

    第27章 硬件输入模型和局部输入状态 这章说的是按键和鼠标事件是如何进入系统并发送给适当的窗口过程的.微软设计输入模型的一个主要目标就是为了保证一个线程的动作不要对其他线程的动作产生不好的影响. 27 ...

  7. Windows核心编程 第十七章 -内存映射文件(下)

    17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...

  8. Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)

    7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...

  9. Windows核心编程 第四章 进程(中)

    4.2 CreateProcess函数 可以用C r e a t e P r o c e s s函数创建一个进程: BOOL CreateProcessW( _In_opt_ LPCWSTR lpAp ...

随机推荐

  1. sql server2014 企业版 百度云下载

    sql server2014 企业版 百度云下载 链接: https://pan.baidu.com/s/1j7a6RWwpvSzG-sF7Dnexfw 提取码: 关注公众号[GitHubCN]回复获 ...

  2. day7 面向对象进阶

    面向对象高级语法部分 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例 ...

  3. 成功实施的APS项目故事分享---我们数据治理的心路历程

    一.故事背景 A企业是易普优APS重要客户之一,是某行业的龙头企业:APS项目历时7个月顺利上线,十个月验收!通过易普优APS的顺利实施,建成了集团的精益计划管控运营平台,树立计划的权威与指挥棒作用, ...

  4. JSP的学习三(中文乱码)

    1). 在 JSP 页面上输入中文, 请求页面后不出现乱码: 保证 contentType="text/html; charset=UTF-8", pageEncoding=&qu ...

  5. ServletConfig对象和ServletContext对象

    (1)ServletConfig:用来保存一个Servlet的配置信息的(比如 : name, class, url ... ) 这些配置信息没什么大用处,我们还可以在ServletConfig中保存 ...

  6. [leetcode trie]212. Word Search II

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  7. Django的Form机制小问题

    使用Django,我们可以以声明式的方式来定义一个Form,如下: 1 2 3 4 5 # -*- coding: utf-8 -*- from django import forms class S ...

  8. android 实现 view 滑动

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 1,通过view 的  滑动到 方法 或者 通过什么滑动  方法 实现.  适合 视图 ...

  9. css选择器(第n个类选择器)的坑

    css选择器选择第n个子元素,共有两种写法: .parent span:nth-child(n) 选择parent下的第n个子元素(不管前边是不是span,都算在内) .parent span:nth ...

  10. luoguP3952 [NOIP2017]时间复杂度 模拟

    原本只是想看下多久能码完时间复杂度 然后在30min内就码完了,然后一A了???? 首先,这题完全可以离线做 我们先把所有的操作读完,判断合不合法之后,再去判断和标准答案的关系 具体而言 把所有的操作 ...