1. 程式人生 > >偽句柄轉換為真正的句柄

偽句柄轉換為真正的句柄

句柄 引用 esp current 進程 後者 ssh 控制 ati

  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;
}

  






偽句柄轉換為真正的句柄