进程共享内核对象之 复制内核对象句柄

来源:互联网 发布:三星数据恢复软件大师 编辑:程序博客网 时间:2024/06/05 04:49

进程共享内核对象的三种方式:

1.     内核对象句柄继承

2.     为内核对象命名

3.     复制内核对象句柄

今天写一下第三种方式。

跨进程边界共享内核对象可以使用DuplicateHandle函数来实现,这个函数会获取某一进程的句柄表中的一个记录项,然后在另一个进程的句柄表中创建这个记录项的一个副本,于是该进程也拥有了该内核对象的访问权。

函数原型如下:

DuplicateHandle(    _In_ HANDLE hSourceProcessHandle,    _In_ HANDLE hSourceHandle,    _In_ HANDLE hTargetProcessHandle,    _Outptr_ LPHANDLE lpTargetHandle,    _In_ DWORD dwDesiredAccess,    _In_ BOOL bInheritHandle,    _In_ DWORD dwOptions    );

参数说明:

第一个参数:

hSourceProcessHandle,源进程句柄,即拥有源内核对象句柄的进程。如源句柄从属于当前进程,则使用GetCurrentProcess。

第二个参数:

hSourceHandle,源内核对象的句柄,也就是欲共享的内核对象的句柄。

第三个参数:

hTargetProcessHandle,目的进程句柄。

第四个参数:

lpTargetHandle,复制到目的进程句柄表中的内核对象句柄的指针。

第五个参数:

dwDesiredAccess,新句柄要求的安全访问级别。如dwOptions已指定了DUPLICATE_SAME_ACCESS,那么忽略这里的设置。

第六个参数:

bInheritHandle,新句柄是否可由hSourceProcessHandle的子进程继承。

第七个参数:

dwOptions,以下两个标志的任意组合

DUPLICATE_SAME_ACCESS 新句柄拥有与原始句柄相同的安全访问特征

DUPLICATE_CLOSE_SOURCE 关闭源进程中的句柄,该标识可以将一个内核对象传递给另外一个进程,即该内核对象的使用计数不会发生变化。

下面给出一个实例,在该实例中,mypro.exe进程创建了一个线程,并将该线程的句柄复制到mytest.exe进程中,后者将该线程终止。

mypro.exe源码:

#include<stdio.h> #include<stdarg.h>#include<windows.h>#include<winioctl.h>#include<tchar.h>#include<Shlwapi.h>#include<math.h>#include<time.h>#include<string>#include <TlHelp32.h>#include <process.h>#include<iostream>using namespace std;//#pragma comment(lib,"Shlwapi.lib")//#pragma comment(lib,"Kernel32.lib")void GetErrorMessage(DWORD dwErrCode, DWORD dwLanguageId){DWORD dwRet = 0;LPTSTR szResult = NULL;setlocale(LC_ALL, "chs");dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,NULL,dwErrCode,dwLanguageId,(LPTSTR)&szResult,0,NULL);if (dwRet == 0){szResult = NULL; wprintf(L"No such errorCode\n");}else { wprintf(L"%ls", szResult); }return;}UINT _stdcall testThread(PVOID para) {while (TRUE) {Sleep(1000);wprintf(L"RUNNING.......\n");}return 0;}HANDLE GetProcessHandle(LPCTSTR szName){HANDLE hSanpshot;hSanpshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//所有进程的快照if (INVALID_HANDLE_VALUE == hSanpshot) { GetErrorMessage(GetLastError(),0); return NULL; }PROCESSENTRY32 pe;//保存某个进程快照的结构体BOOL bOk;pe.dwSize = sizeof(pe);bOk = Process32First(hSanpshot, &pe);//第一个进程if (!bOk) { GetErrorMessage(GetLastError(), 0); return NULL; }do {if (!wcscmp(pe.szExeFile, szName)){return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);}bOk = Process32Next(hSanpshot, &pe);//下一个进程} while (bOk);CloseHandle(hSanpshot);return NULL;}int   main(int   argc, char   *argv[]) {HANDLE hThread;hThread = (HANDLE)_beginthreadex(NULL, 0, testThread, NULL, 0, NULL);wcout << L"hThread is " << hThread << endl;HANDLE hTarget;if (DuplicateHandle(GetCurrentProcess(), hThread, GetProcessHandle(L"mytest.exe"), &hTarget, 0, FALSE, DUPLICATE_SAME_ACCESS)) {wprintf(L"DuplicateHandle SUCCEED\n");wcout << L"hTarget is " << hTarget << endl;}else { GetErrorMessage(GetLastError(), 0); TerminateThread(hThread, 0); return 0; }WaitForSingleObject(hThread, INFINITE);wprintf(L"hThread is end\n");system("pause");return 0;}

mytest.exe源码:

#include<stdio.h> #include<stdarg.h>#include<windows.h>#include<winioctl.h>#include<tchar.h>#include<Shlwapi.h>#include<math.h>#include<time.h>#include<string>#include <TlHelp32.h>#include <process.h>#include<iostream>using namespace std;//#pragma comment(lib,"Shlwapi.lib")//#pragma comment(lib,"Kernel32.lib")void GetErrorMessage(DWORD dwErrCode, DWORD dwLanguageId){DWORD dwRet = 0;LPTSTR szResult = NULL;setlocale(LC_ALL, "chs");dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,NULL,dwErrCode,dwLanguageId,(LPTSTR)&szResult,0,NULL);if (dwRet == 0){szResult = NULL; wprintf(L"No such errorCode\n");}else { wprintf(L"%ls", szResult); }return;}int   main(int   argc, char   *argv[]) {HANDLE hRecv;cout << "input hRecv : " << endl;cin >> hRecv;TerminateThread(hRecv, 0);GetErrorMessage(GetLastError(), 0);system("pause");return 0;}

需要先运行mytest.exe,否则句柄复制会失败。另外需要注意:复制内核对象的句柄与内核对象句柄的继承有些相似,即目的进程本身无法感知到其已经拥有了该内核对象的访问权限。由于目的进程已经运行,所以使用命令行参数或者更改目的进程的环境变量是无法做到的。上面的实例我是手动输入的...



阅读全文
0 0