伪句柄转换为真正的句柄

  HANDLE  GetCurrentProcess();     返回值 0XFFFFFFFF   -1

  HANDLE  GetCurrentThread();      返回值 0XFFFFFFFE   -2

  这两个函数都返回到主调线程的进程或线程内核对象的一个伪句柄(pseudohandle )。GetCurrentProcess得到得到的只是伪句柄,一个标识,可以发现,其实就是返回$FFFFFFFF(-1),每个进程得句柄都是一样的,只是适用于进程内部使用。同样道理,GetCurrentThread也是伪句柄,其返回值永远是$FFFFFFFE(-2),只是适用于线程内部使用。而"伪句柄"的存在,就是使用简单,不用CloseHandle关闭,不会造成内存泄漏。它们不会在主调进程的句柄表中新建句柄。而且,调用这两个函数,不会影响进程或线程内核对象的使用计数。如果调用closehandle,将一个伪句柄作为参数传入,closehandle只是简单地忽略此调 用,并返回false。在这种情况下,getlasterror将返回error_invalid_handle。

  如果想得到实际得句柄,在进程间进行通讯,必需要进行转化,DuplicateHandle函数就可以执行这个转换。

  WINBASEAPI

  BOOL

  WINAPI

  DuplicateHandle(

   _In_ HANDLE hSourceProcessHandle,

   _In_ HANDLE hSourceHandle,

  _In_ HANDLE hTargetProcessHandle,

   _Outptr_ LPHANDLE lpTargetHandle,

  _In_ DWORD dwDesiredAccess,

  _In_ BOOL bInheritHandle,

  _In_ DWORD dwOptions

    );

   现在,想要通过父进程的句柄,在子进程当中操作父进程,或者获取父进程的相关消息,当父线程执行时,它会把标识父线程的有歧义的伪句柄转换为一个新的、真正的句柄,后者明确、无歧义地标识了父线程。然后,它将这个真正的句柄传给createthread。当子线程开始执行时,其pvparam参数就会包含这个真正的线程句柄。在调用任何函数时,只要传入这个句 柄,影响的就将是父线程,而非子线程。 因为duplicatehandle递增了指定内核对象的使用计数,所以在用完复制的对象句柄后,有必要 把目标句柄传给closehandle,以递减对象的使用计数。

父进程:

//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
	HANDLE RealProcessHandle = NULL;
	HANDLE PseudoProcessHandle = GetCurrentProcess();  //获得一个伪句柄

	DuplicateHandle(
		GetCurrentProcess(),   //源进程内核句柄(即负责传递内核对象句柄的进程句柄)
		PseudoProcessHandle,   //进程伪句柄 GetCurrentProcess()
		GetCurrentProcess(),   //目标进程内核句柄
		&RealProcessHandle,    //接受新的,真实句柄!
		0,                     //TargetHandle句柄使用何种访问掩码,这个参数将被忽略,因为DUPLICATE_SAME_ACCESS
		FALSE,                 //新的句柄不可继承
		DUPLICATE_SAME_ACCESS);//新句柄拥有与原始句柄相同的安全访问特征

	//通过上面的函数就可以将一个进程中的一个线程的伪句柄转换成正真的句柄
    //DuplicateHandle  递增了内核对象的句柄数最好要调用CloseHandle();

	//改变句柄能够被继承
	if (SetHandleInformation(
		RealProcessHandle,          //句柄
		HANDLE_FLAG_INHERIT,        //更改继承标志
		HANDLE_FLAG_INHERIT)==FALSE)//将标志修改为可继承
	{
		int LastError = GetLastError();
	}

	ULONG_PTR*  v1 = (ULONG_PTR*)PseudoProcessHandle;
	ULONG_PTR*  v2 = (ULONG_PTR*)RealProcessHandle;

	printf("父进程句柄值:%d	%d\r\n", v1,v2);

	//将存有句柄值的BufferData作为命令行传给子进程
	WCHAR BufferData[20] = { 0 };
	swprintf_s(BufferData, L"%d %d", v1,v2);

	STARTUPINFO StartupInfo = { 0 };
	StartupInfo.cb = sizeof(STARTUPINFO);
	PROCESS_INFORMATION ProcessInfo = { 0 };
	ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
	BOOL IsOk = CreateProcess(L"ChildProcess.exe",
			(LPWSTR)BufferData,NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo);
	if (IsOk == FALSE)
	{
		printf("CreateProcess\r\n失败");
		goto Exit;
	}
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);

	printf("Input AnyKey To Exit\r\n");
	getchar();
Exit:

	if (RealProcessHandle!=NULL)
	{
		CloseHandle(RealProcessHandle);
		RealProcessHandle = NULL;
	}

	return 0;
}

  子进程:

// ChildProcess.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

//定义参数
int main(int argc, char* argv[])
{
	ULONG_PTR  v1 = 0;
	//接收CommandLine的数据实际上是单字的
	sscanf_s((CHAR*)argv[0], "%d", &v1);
	HANDLE PseudoProcessHandle = (HANDLE)v1;
	sscanf_s((CHAR*)argv[1], "%d", &v1);
	HANDLE RealProcessHandle = (HANDLE)v1;

	printf("继承的父进程句柄值:PseudoProcessHandle: %d	RealProcessHandle: %d\r\n", PseudoProcessHandle,RealProcessHandle);
	Sleep(3000);

	//TerminateProcess(PseudoProcessHandle,0);  //把自己杀死了
	CloseHandle(RealProcessHandle);   //减少引用计数
	if (TerminateProcess(RealProcessHandle, 0)==FALSE)
	{
		int LastError = GetLastError();

		printf("LastError:%d", LastError);
	}

	printf("Input AnyKey To Exit\r\n");
	getchar();
	ExitProcess(0);
	return 0;
}

  

时间: 2024-10-04 07:07:21

伪句柄转换为真正的句柄的相关文章

句柄表(私有句柄表)

 Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 句柄表(私有句柄表) 我们在R3环编程中,会接触到句柄HANDLE的概念. 比如OPENPROCESS,打开进程获取其进程句柄,这些被称为“内核句柄”. 注意,与GUI图形界面不同,那些 画刷句柄 被称为“用户句柄”,不在我们讨论范围之列. 一. 句柄表的基本概念 句柄表分为私有私有句柄表和全局句柄表,我们这一节只讨论私有句柄表. 每一个进程都有自己的私有句柄表

imp导入备份时报:无法转换为环境字符集句柄 ...

在imp 还原数据库的时候出现问题如下: 这个问题是 你用 expdp导出的 却用客户端的 imp 导入:换成impdp导入即可. 当用impdp 导入 (impdp EMMS/EMMS123 directory=expdir dumpfile=EMMS2.dmp)  却发现 [IMPDP]使用工具IMPDP导入数据时ORA-39002.ORA-39070错误排查      其中 RA-39070   错误指出 没有expdir 对象. expdir 需要你重新再创建一次如下: sqlplus

.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子

上一篇文章介绍了句柄的基本概念,也描述了C#中创建文件句柄的过程.我们已经知道句柄代表Windows内部对象,文件对象就是其中一种,但显然系统中还有更多其它类型的对象.本文将简单介绍Windows对象的分类. 句柄可以代表的Windows对象分为三类,内核对象(Kernel Object).用户对象(GDI Object)和GDI对象,上一篇文章中任务管理器中的“句柄数”.“用户对象”和“GDI对象”计数就是与这几类对象对应的.为什么要这样分类呢?原因就在于这几类对象对于操作系统而言有不同的作用

易语言超文本浏览框取真实句柄(可消息句柄)

很多朋友想做网页 鼠标键盘后台消息的软件,但是苦于找不到超文本浏览狂的真实句柄. 如果你用  超文本浏览框.取窗口句柄()  那么你取到的是图1的句柄,这个句柄是无法操作的 图中2的句柄才是真正可以发送消息和模拟操作的句柄,也是用窗口助手真正查到的句柄 具体操作看下图. 用的是精易模块的窗口枚举所有子窗口命令 然后匹配出类名为"Internet Explorer_Server"的那个句柄就是真实句柄了. 方案二,一个最最简单的方法就是直接调用精易模块 窗口_取IE浏览框句柄() 原文地

伪句柄

一.什么是伪句柄 在使用很多函数的时候,我们都需要获得一个对象的句柄,而某些函数返回的是伪句柄.伪句柄本身不会打开内核对象的句柄表,因此内核对象的使用计数就不会增加.它本身就只指向调用它的主调进程或线程.会因为调用者的不同而改变,比如:调用者A使用一个伪句柄,这个句柄指向调用者A,而调用者A将该句柄传递给调用者X,则这个句柄就指向调用者X.我们可以通过调试的方式查看伪句柄,可以得知,进程的伪句柄总是0xffffffff,而线程的伪句柄总是0xfffffffe. 通过使用DuplicateHand

windows下进程与线程剖析

进程与线程的解析 进程:一个正在运行的程序的实例,由两部分组成: 1.一个内核对象,操作系统用它来管理进程.内核对象也是系统保存进程统计信息的地方. 2.一个地址空间,其中包含所有可执行文件或DLL模块的代码和数据.此外,它还包含动态内存分配,比如线程堆栈和堆的分配. 进程要做任何事情,都必须让一个线程在它的上下文中运行.该线程负责执行进程地址空间包含的代码.事实上,一个进程可以有多个线程,所有线程都在进程的地 址空间中"同时"执行代码.为此,每个线程都有它自己的一组CPU寄存器和它自

获取真正的进程/线程句柄

首先在开始正文之前先介绍最简单的获取进程/线程句柄方法.那就是可以在创建进程/线程时获取句柄. 创建进程/线程是获取句柄. //进程创建函数 BOOL CreateProcess( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURITY_ATTRIBUTES psaProcess, PSECURITY_ATTRIBUTES psaThread, BOOL bInheritHandles, DWORD fdwCreate, PVOID

.NET对象与Windows句柄(三):句柄泄露实例分析

在上篇文章.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子中,我们有一个句柄泄露的例子.例子中多次创建和Dispose了DataReceiver和DataAnalyzer对象,但由于忘记调用DataAnalyzer的Stop方法,导致产生句柄泄露.本文假定我们已经发现了泄露现象但还不知道原因,讨论如何在这种情况下分析问题. 一.发现问题 在程序运行约一个小时以后,通过任务管理器发现句柄数超过5000,线程数也超过1000.对于一段只需要并行接收和分析数据的简易代码来说,这

句柄和指针的区别和联系

所谓 句柄实际上是一个数据,是一个Long (整长型)的数据.句 柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等.WINDOWS句柄有点象C语言中的文件句柄. 从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人.从数据类型上来看它只是一个16位的无符号整数.应用程序几乎总是