刘收获

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

伪句柄转换为真正的句柄

  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,以递减对象的使用计数

 

父进程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
 
#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;
}
 
 
 
     

  子进程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 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;
}

  

 

          

 

 






posted on   沉疴  阅读(2356)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示