我是靠谱客的博主 温柔钢笔,最近开发中收集的这篇文章主要介绍利用32位PEB结构实现从进程ID中得到进程完整路径,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

//PEB.h
#pragma once
#include <windows.h>
#include <iostream>
using namespace std;
//宏,结构体定义,函数声明;
//#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
//要自己定义PEB结构:
//PEB结构中的查找进程完整路径的结构体
typedef struct _UNICODE_STRING
{
UINT16 Length;//short型
UINT16 MaximumLength;
PWCHAR Buffer;//WCHAR*型(四字节大小的指针)
}UNICODE_STRING,PUNICODE_STRING;
//UNICODE_STRING在Ring3层不公开,(在驱动层才公开)
typedef struct _RTL_USER_PROCESS_PARAMETERS_X86
{
UINT32 MaximumLength;
UINT32 Length;
UINT32 Flags;
UINT32 DebugFlags;
PVOID
ConsoleHandle;
UINT32 ConsoleFlags;//UINT 4B
PVOID
StandardInput;
PVOID
StandardOutput;
PVOID
StandardError;
ULONG32 CurrentDirectory[3];//原来是十二字节的结构体CURDIR
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;//完整路径
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS_X86, *PRTL_USER_PROCESS_PARAMETERS_X86;
typedef struct _PEB_X86
{
UINT8 InheritedAddressSpace;
UINT8 ReadImageFileExecOptions;
UINT8 BeingDebugged;
UINT8 BitField;//联合体(位域第一位的成员)
PVOID Mutant;//互斥体
PVOID ImageBaseAddress;//模块加载基地址
PVOID Ldr;//结构体(Ldr实际上为结构体类型指针)
PRTL_USER_PROCESS_PARAMETERS_X86 ProcessParameters;
}PEB_X86,*PPEB_X86;
#ifdef _WIN32
#define RTL_USER_PROCESS_PARAMETERS RTL_USER_PROCESS_PARAMETERS_X86
#define PPEB PPEB_X86
#define PEB
PEB_X86
#else
#define PPEB PPEB_X64
#define PEB
PEB_X64
#endif
//有关查找PEB地址的属于进程内存的结构体
typedef struct _PROCESS_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PPEB
PebBaseAddress;
//地址
ULONG
AffinityMask;
LONG
BasePriority;
ULONG
UniqueProcessId;
ULONG
InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;
//函数指针原型定义:
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
// Note: this is kernel mode only
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessResourceManagement,
ProcessCookie,
ProcessImageInformation,
MaxProcessInfoClass
} PROCESSINFOCLASS;
typedef
NTSTATUS(NTAPI *pfnNtQueryInformationProcess)(
IN HANDLE ProcessHandle,//,进程句柄,查谁
IN PROCESSINFOCLASS ProcessInformationClass,//枚举类型结构体,查什么信息
OUT PVOID ProcessInformation,//结构体首地址,查出来的东西放在哪里
IN UINT32 ProcessInformationLength,//结构体大小
OUT PUINT32 ReturnLength);//校验值
//#define NTAPI __stdcall,指调用约定
//定义函数指针
//
BOOL GetProcessFullPathByProcessID(ULONG32 ProcessID, WCHAR* BufferData, ULONG BufferLegnth);


// PEB.cpp : 定义控制台应用程序的入口点。
//
#include "PEB.h"
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
int main()
{
BOOL bOk = FALSE;
ULONG32 ProcessID = 0;
WCHAR
BufferData[MAX_PATH] = { 0 };
//定义完整路径数组,
//windows规定存放完整路径的数组最大为260个字节;
printf("Input Process IDrn");
scanf_s("%d", &ProcessID);
bOk = GetProcessFullPathByProcessID(ProcessID,BufferData, MAX_PATH);
//用自定义函数实现从进程ID得到进程完整路径的过程(进程ID,完整路径(存放的数组名),数组长度)
cout << bOk << endl;
if (bOk==TRUE)
{
printf("%Srn", BufferData);
//BufferData双字,故用大S输出字符串;
}
return 0;
}
BOOL GetProcessFullPathByProcessID(ULONG32 ProcessID,WCHAR* BufferData,ULONG BufferLegnth)
//先找到peb结构在进程中的地址,再从peb结构中找到完整路径所在的地址;
//GetPebByProcessID,GetProcessFullPathByPeb,
{
BOOL
bOk = FALSE;
NTSTATUS
Status = 0;
//一种int型返回值
PEB
Peb = { 0 };
//PEB结构体初始化
HANDLE
ProcessHandle = NULL;
//*打开目标进程空间
ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ, FALSE, ProcessID);
//ProcessHandle值是目标进程的进程句柄,是一个正数(-1是GetCurrentProcess函数,代表自己进程的伪句柄);
//OpenProcess为Windows库函数,“打开(对方)进程空间”(想要行使的权限(查询|读),BOOL型,目标进程ID)
if (ProcessHandle == NULL)
{
return FALSE;
}
pfnNtQueryInformationProcess	NtQueryInformationProcess =
(pfnNtQueryInformationProcess)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess");
//GetModuleHandle为Windows库函数(GetModuleHandleW),“返回加载模块的基地址”(所以模块名字传为双字!)
//GetProcAddress为Windows库函数,“从当前进程的导出表中获得目标函数地址”(实际上就是遍历导出表来搜索这个函数)
//
本语句意思是从ntdll.dll的导出表中搜索NtQueryInformationProcess函数!
//此时函数地址得到的是自己的,(1自己的基地址,2自己的函数)//没有用目标函数进程
//
//GetProcAddress从当前函数的导出表搜索函数	//从当前进程空间的ntdll模块的导出表中获得一个函数NtQueryInformationProcess的地址
//而不从导入表中获得(直接调用)原因是:
//有可能就没有导入!(涉及到VS编译未公开函数等原因)GetProcAddress返回的是一个泛型,
//得到函数地址以后,发生强制类型转换,
if (NtQueryInformationProcess == NULL)
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
}
//**通过 NtQueryInformationProcess 获得 ProcessBasicInformation
PROCESS_BASIC_INFORMATION	pbi = { 0 };
ULONG32
ReturnLength = 0;
//开始查进程的ProcessBasicInformation
Status = NtQueryInformationProcess(ProcessHandle,
ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION),
(PUINT32)&ReturnLength);
//参数:查谁,查什么,
//Status=0
//NT_SUCCESS(Status)=1
if (!NT_SUCCESS(Status))
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
}
//***通过ReadProcessMemory 从进程里面 PebBaseAddress 内存数据读取出来
bOk = ReadProcessMemory(ProcessHandle, pbi.PebBaseAddress, &Peb, sizeof(PEB), (SIZE_T*)&ReturnLength);
//ReadProcessMemory是Windows库函数,“读进程空间的内存”,
//(目标进程句柄,目标地址,读到peb这个结构体指针里,结构体大小,校验值)
//SIZE_T相当于ULONG_PTR;
if (bOk == FALSE)
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
}
RTL_USER_PROCESS_PARAMETERS RtlUserProcessParameters = { 0 };
bOk = ReadProcessMemory(ProcessHandle, Peb.ProcessParameters, &RtlUserProcessParameters,
sizeof(RTL_USER_PROCESS_PARAMETERS), (SIZE_T*)&ReturnLength);
if (RtlUserProcessParameters.ImagePathName.Buffer!=NULL)
{
ULONG v1 = 0;
if (RtlUserProcessParameters.ImagePathName.Length<BufferLegnth)
{
v1 = RtlUserProcessParameters.ImagePathName.Length;
}
else
{
v1 = BufferLegnth-10;
}
bOk = ReadProcessMemory(ProcessHandle, RtlUserProcessParameters.ImagePathName.Buffer,
BufferData,v1,(SIZE_T*)&ReturnLength);
if (bOk == FALSE)
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
}
}
CloseHandle(ProcessHandle);
return TRUE;
}



本程序只使用于32位!

即只能寻找32位进程的完整路径!

使用PEB结构以得到进程的完整路径(包括从进程ID得到进程PEB地址和从PEB结构得到进程完整路径)

GetProcessFullPathByProcessID相当于两个函数GetPebByProcessID,GetProcessFullPathByPeb的合并。


从PEB结构中得到进程的完整路径:

通过PEB结构中的RTL_USER_PROCESS_PARAMETERS类型的ProcessParameters成员,ProcessParameters成员中有ImagePathName成员。

从进程ID中得到进程PEB结构地址:
使用微软未公开的函数NtQueryInformationProcess,其中用到枚举类型结构体PROCESSINFOCLASS,该结构体的成员PROCESS_BASIC_INFORMATION,从其中再找到PPEB类型的PebBaseAddress成员,该结构体的地址即为peb的地址。找到了peb的地址相当于已经可以开始读取PEB的结构了。


最后

以上就是温柔钢笔为你收集整理的利用32位PEB结构实现从进程ID中得到进程完整路径的全部内容,希望文章能够帮你解决利用32位PEB结构实现从进程ID中得到进程完整路径所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部