zoukankan      html  css  js  c++  java
  • 内核中PID_HANDLE_OBJECT等互相转换

    一丶简介

    在内核中我们一般会使用各种 HANDLE Object 以及 ID等等.
    那么有时候就需要互相转换.这里记录一下.

    下面以进程为例进行说明.

    1.进程pid 转化为 HANDLE

    原理就是 跟ring3一样. 使用打开进程的函数来获取HANDLE

    核心原理就是在内核中使用 ZwOpenProcess 传入PID 传出一个HANDLE.

    代码如下:

        ULONG pid;
    	HANDLE hProcessHandle;
    	OBJECT_ATTRIBUTES obj;
    	CLIENT_ID clientid;
    	//必须初始化
    	pid = 2378;
    	clientid.UniqueProcess = (HANDLE)pid;
    	clientid.UniqueThread = 0;
    	InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
    	ZwOpenProcess(&hProcessHandle, PROCESS_ALL_ACCESS, &obj, &clientid);
    		
    

    此时ProcessHandle就是我们所要的Handle
    关于文件你就可以使用 ZwOpenFile or ZwCreateFile 注册表类似.

    2.Handle --------> 转化为 PID

    Handle转化为PID就要使用跟进程相关的特有API.

    如进程则使用 ** ZwQueryInformationProcess ** 遍历进程的基础信息即可得到PID

    但是注意,此函数在内核中不能直接使用.因为是未公开的函数.所以我们必须进行声明.并且使用 内核API来动态获取此函数的地址才可以

    代码如下:
    声明与定义:

    typedef NTSTATUS(*PfnZwQueryInformationProcess) (
    	__in HANDLE ProcessHandle,
    	__in PROCESSINFOCLASS ProcessInformationClass,
    	__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    	__in ULONG ProcessInformationLength,
    	__out_opt PULONG ReturnLength
    	);
    
    PfnZwQueryInformationProcess ZwQueryInformationProcess;
    
    

    核心实现,ProcessHandle就是你所获得的句柄.

    
    PROCESS_BASIC_INFORMATION ProcessBasicInfor;
    	//动态获取.
    	UNICODE_STRING UtrZwQueryInformationProcessName =
    		RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
    	ZwQueryInformationProcess = 
    		(PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);
    	//check...
    	//核心代码
    	/*
    	1.利用PID
    	*/
    	PROCESS_BASIC_INFORMATION ProcessBasicInfor;
    	ZwQueryInformationProcess(
    		ProcessHndle, 
    		ProcessBasicInformation,
    		(PVOID)&ProcessBasicInfor,
    		sizeof(ProcessBasicInfor),
    		NULL);
    	/*
    	ProcessBasicInfor.UniqueProcessId; 则为你所求
    	*/
    

    3.Pid ------> Object(EPROCESS)

    pid转化为EPROCESS说下原理.

    原理就是通过 PsLookUpProcessByProcessId 传入PID.传出EPROCESS.

    但是内核中你使用了这个函数. 那么获得的EPROCESS就会引用计数+1根据内核面向对象的设计.你要进行解引用.所以还需要一个API 进行解引用

    核心代码如下:

    PEPROCESS pEpro;
    PsLookUpProcessByProcessId((HANDLE)pid,&pEpro);
    ObDereferenceObject(pEpro);
    PEpro即为你所求.
    

    4. HANDLE -------------> EPROCESS

    这个也是很常用的.在内核编程中.当你获得一个HANDLE 首先就要把其转化为对应的OBJECT对象.

    而内核函数也为我们提供了.

    如下:

    ObReferenceObjectByHandle(ProcessHandle, GENERIC_ALL,*PsProcessType,KernelMode,&pEprocess,NULL);
    
    

    5.EPROCESS ---------> pid

    在EPROCESS中本身就记录着PID. 直接获取PID即可.
    EPROCESS.UniqueProcessId;

    6.EPROCESS --------->HANDLE

    这个倒是没有常用.但是内核也提供了API给我们使用

    ObOpenObjectByPoint(Process,attributes,&AccessState,0,*PsProcessType,PreviousMode,&Handle);
    
  • 相关阅读:
    进位制 与成熟表示
    例题 3-6 环状序列
    -------------------开启我的手残之旅---------我就是喜欢写笔记-------咋滴啦?-----
    图的遍历---------开始开始-------o(∩_∩)o 哈哈
    -----------什么是图?------------
    并查集-----集合以及计算----
    ----堆----希望这是一个容易上手的工具--------
    kafka-docker----(how to setup http proxy in container??)
    FW: Dockerfile RUN, CMD & ENTRYPOINT
    telnet --- no route to host solution "iptables -F " in the target machine
  • 原文地址:https://www.cnblogs.com/iBinary/p/11370584.html
Copyright © 2011-2022 走看看