• 先写一个程序,用来查看进程的内核对象,这样我们就能比较子进程是否继承了父进程的某个句柄:
#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. Kylin使用笔记-1: 安装

    2016年1月14日 9:57:23 星期四 背景介绍     Apache Kylin是一个开源的分布式分析引擎,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最 ...

  2. 浅谈jvm

    1 .说起jvm,很多人感觉jvm离我们开发实际很远.但是,我们开发缺每时每刻都离不开jvm. a: java源码 编译后成.class字节码文件, b:根据classpath找到这个字节码文件, c ...

  3. 回文树练习 Part1

    URAL - 1960   Palindromes and Super Abilities 回文树水题,每次插入时统计数量即可. #include<bits/stdc++.h> using ...

  4. 2017 ACM Amman Collegiate Programming Contest 题解

    [题目链接] A - Watching TV 模拟.统计一下哪个数字最多即可. #include <bits/stdc++.h> using namespace std; const in ...

  5. 跑对抗样本库 CleverHans 的例子时,遇到的问题

    环境:Ubuntu+TensorFlow 首先是GPU被其他人占用了,怎么也跑不起来最简单的TensorFlow小例子. 所以先学会如何查看显卡使用情况,转去使用其他空闲显卡. Linux查看Nvid ...

  6. Kotlin in Action 笔记

    Kotlin 参考 官网 reference kotlin实战 Try Kotlin Kotlin China Github 简介 Kotlin是一门把Java平台作为目标的新的编程语言.它简洁.安全 ...

  7. 自定义JSP标签示例

    我们以一个例子来讲解如何自定义JSP标签,假如我们需要在页面中输出当前的时间,按照最简单的JSP脚本,需要在JSP里面写很多Java代码,那么如何来使用自定义标签实现这个功能呢? 首先,我们要先创建一 ...

  8. Revit二次开发示例:DeleteDimensions

    在本例中,创建一个命令,实现删除所选中的尺寸标注. #region Namespaces using System; using System.Collections.Generic; using S ...

  9. SKLearn数据集API(一)

    注:本文是人工智能研究网的学习笔记 数据集一览 类型 获取方式 自带的小数据集 sklearn.datasets.load_ 在线下载的数据集 sklearn.datasets.fetch_ 计算机生 ...

  10. [UOJ#245][UER#7]天路(近似算法)

    允许5%的相对误差,意味着我们可以只输出$\log_{1.05} V$种取值并保证答案合法.并且注意到答案随着区间长度而单增,故取值不同的答案区间是$O(\log_{1.05} V)$的. 于是初始x ...