利用32位PEB结构实现从进程ID中得到进程完整路径
2017-11-20 19:51
441 查看
//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 ID\r\n"); scanf_s("%d", &ProcessID); bOk = GetProcessFullPathByProcessID(ProcessID,BufferData, MAX_PATH); //用自定义函数实现从进程ID得到进程完整路径的过程(进程ID,完整路径(存放的数组名),数组长度) cout << bOk << endl; if (bOk==TRUE) { printf("%S\r\n", 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, Bu 4000 fferData,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的结构了。
相关文章推荐
- <原创> 通过PEB获得进程路径 (附完整工程)
- R3;在32位进程中得到64位进程映像路径
- 关于进程PEB结构的修改实现
- 如何在驱动程序(sys)中得到当前进程的完整路径和进程名?
- 如何在 Windows 2000 的驱动程序(SYS)中得到当前进程的进程名和完整路径?
- 驱动层得到进程的完整路径
- 如何在驱动程序(SYS)中得到当前进程的完整路径和进程名?
- 如何在驱动程序(SYS)中得到当前进程的完整路径和进程名
- 线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。 进程拥有这
- Linux下获取进程完整路径(包括进程名)——完整实例代码实现
- 软件调试笔记10 - Windows概要:进程结构:令牌,PEB,ID, 句柄
- C++和python利用struct结构传输二进制数据实现
- 进程peb结构、获得peb的方法
- Linux查看进程运行的完整路径方法:
- C++中利用堆栈得到一条已知起点与终点的可通行的路径并输出
- hibernate利用mysql的自增张id属性实现自增长id和手动赋值id并存
- 得到进程路径方法之汇总,需要的直接cp吧
- Android 利用Java实现压缩与解压缩(zip、gzip)支持中文路径
- LDR_DATA_TABLE_ENTRY结构得不到完整路径?
- 利用dbcp数据库连接池连接数据库,并利用dbtuils框架对数据库test中book表进行插入、删除、修改、查询的操作。book表结构如下:(id,name,price,author,descrip