C語言驅(qū)動(dòng)開發(fā)之內(nèi)核通過PEB獲取進(jìn)程參數(shù)
PEB結(jié)構(gòu)(Process Envirorment Block Structure)其中文名是進(jìn)程環(huán)境塊信息,進(jìn)程環(huán)境塊內(nèi)部包含了進(jìn)程運(yùn)行的詳細(xì)參數(shù)信息,每一個(gè)進(jìn)程在運(yùn)行后都會(huì)存在一個(gè)特有的PEB結(jié)構(gòu),通過附加進(jìn)程并遍歷這段結(jié)構(gòu)即可得到非常多的有用信息。
在應(yīng)用層下,如果想要得到PEB的基地址只需要取fs:[0x30]即可,TEB線程環(huán)境塊則是fs:[0x18],如果在內(nèi)核層想要得到應(yīng)用層進(jìn)程的PEB信息我們需要調(diào)用特定的內(nèi)核函數(shù)來獲取,如下案例將教大家如何在內(nèi)核層取到應(yīng)用層進(jìn)程的PEB結(jié)構(gòu)。
首先在開始寫代碼之前需要先定義好PEB進(jìn)程環(huán)境快結(jié)構(gòu)體,用于對(duì)內(nèi)存指針解析,新建peb.h文件并保存如下代碼,這些是微軟的結(jié)構(gòu)定義分為32位與64位,官方定義規(guī)范而已不需要費(fèi)工夫。
#pragma once
#include <ntifs.h>
typedef struct _CURDIR // 2 elements, 0x18 bytes (sizeof)
{
/*0x000*/ struct _UNICODE_STRING DosPath; // 3 elements, 0x10 bytes (sizeof)
/*0x010*/ VOID* Handle;
}CURDIR, *PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR // 4 elements, 0x18 bytes (sizeof)
{
/*0x000*/ UINT16 Flags;
/*0x002*/ UINT16 Length;
/*0x004*/ ULONG32 TimeStamp;
/*0x008*/ struct _STRING DosPath; // 3 elements, 0x10 bytes (sizeof)
}RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef enum _SYSTEM_DLL_TYPE // 7 elements, 0x4 bytes
{
PsNativeSystemDll = 0 /*0x0*/,
PsWowX86SystemDll = 1 /*0x1*/,
PsWowArm32SystemDll = 2 /*0x2*/,
PsWowAmd64SystemDll = 3 /*0x3*/,
PsWowChpeX86SystemDll = 4 /*0x4*/,
PsVsmEnclaveRuntimeDll = 5 /*0x5*/,
PsSystemDllTotalTypes = 6 /*0x6*/
}SYSTEM_DLL_TYPE, *PSYSTEM_DLL_TYPE;
typedef struct _EWOW64PROCESS // 3 elements, 0x10 bytes (sizeof)
{
/*0x000*/ VOID* Peb;
/*0x008*/ UINT16 Machine;
/*0x00A*/ UINT8 _PADDING0_[0x2];
/*0x00C*/ enum _SYSTEM_DLL_TYPE NtdllType;
}EWOW64PROCESS, *PEWOW64PROCESS;
typedef struct _RTL_USER_PROCESS_PARAMETERS // 37 elements, 0x440 bytes (sizeof)
{
/*0x000*/ ULONG32 MaximumLength;
/*0x004*/ ULONG32 Length;
/*0x008*/ ULONG32 Flags;
/*0x00C*/ ULONG32 DebugFlags;
/*0x010*/ VOID* ConsoleHandle;
/*0x018*/ ULONG32 ConsoleFlags;
/*0x01C*/ UINT8 _PADDING0_[0x4];
/*0x020*/ VOID* StandardInput;
/*0x028*/ VOID* StandardOutput;
/*0x030*/ VOID* StandardError;
/*0x038*/ struct _CURDIR CurrentDirectory; // 2 elements, 0x18 bytes (sizeof)
/*0x050*/ struct _UNICODE_STRING DllPath; // 3 elements, 0x10 bytes (sizeof)
/*0x060*/ struct _UNICODE_STRING ImagePathName; // 3 elements, 0x10 bytes (sizeof)
/*0x070*/ struct _UNICODE_STRING CommandLine; // 3 elements, 0x10 bytes (sizeof)
/*0x080*/ VOID* Environment;
/*0x088*/ ULONG32 StartingX;
/*0x08C*/ ULONG32 StartingY;
/*0x090*/ ULONG32 CountX;
/*0x094*/ ULONG32 CountY;
/*0x098*/ ULONG32 CountCharsX;
/*0x09C*/ ULONG32 CountCharsY;
/*0x0A0*/ ULONG32 FillAttribute;
/*0x0A4*/ ULONG32 WindowFlags;
/*0x0A8*/ ULONG32 ShowWindowFlags;
/*0x0AC*/ UINT8 _PADDING1_[0x4];
/*0x0B0*/ struct _UNICODE_STRING WindowTitle; // 3 elements, 0x10 bytes (sizeof)
/*0x0C0*/ struct _UNICODE_STRING DesktopInfo; // 3 elements, 0x10 bytes (sizeof)
/*0x0D0*/ struct _UNICODE_STRING ShellInfo; // 3 elements, 0x10 bytes (sizeof)
/*0x0E0*/ struct _UNICODE_STRING RuntimeData; // 3 elements, 0x10 bytes (sizeof)
/*0x0F0*/ struct _RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
/*0x3F0*/ UINT64 EnvironmentSize;
/*0x3F8*/ UINT64 EnvironmentVersion;
/*0x400*/ VOID* PackageDependencyData;
/*0x408*/ ULONG32 ProcessGroupId;
/*0x40C*/ ULONG32 LoaderThreads;
/*0x410*/ struct _UNICODE_STRING RedirectionDllName; // 3 elements, 0x10 bytes (sizeof)
/*0x420*/ struct _UNICODE_STRING HeapPartitionName; // 3 elements, 0x10 bytes (sizeof)
/*0x430*/ UINT64* DefaultThreadpoolCpuSetMasks;
/*0x438*/ ULONG32 DefaultThreadpoolCpuSetMaskCount;
/*0x43C*/ UINT8 _PADDING2_[0x4];
}RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB_LDR_DATA // 9 elements, 0x58 bytes (sizeof)
{
/*0x000*/ ULONG32 Length;
/*0x004*/ UINT8 Initialized;
/*0x005*/ UINT8 _PADDING0_[0x3];
/*0x008*/ VOID* SsHandle;
/*0x010*/ struct _LIST_ENTRY InLoadOrderModuleList; // 2 elements, 0x10 bytes (sizeof)
/*0x020*/ struct _LIST_ENTRY InMemoryOrderModuleList; // 2 elements, 0x10 bytes (sizeof)
/*0x030*/ struct _LIST_ENTRY InInitializationOrderModuleList; // 2 elements, 0x10 bytes (sizeof)
/*0x040*/ VOID* EntryInProgress;
/*0x048*/ UINT8 ShutdownInProgress;
/*0x049*/ UINT8 _PADDING1_[0x7];
/*0x050*/ VOID* ShutdownThreadId;
}PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _PEB64
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG64 Mutant;
ULONG64 ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
ULONG64 SubSystemData;
ULONG64 ProcessHeap;
ULONG64 FastPebLock;
ULONG64 AtlThunkSListPtr;
ULONG64 IFEOKey;
ULONG64 CrossProcessFlags;
ULONG64 UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
ULONG64 ApiSetMap;
} PEB64, *PPEB64;
#pragma pack(4)
typedef struct _PEB32
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG Mutant;
ULONG ImageBaseAddress;
ULONG Ldr;
ULONG ProcessParameters;
ULONG SubSystemData;
ULONG ProcessHeap;
ULONG FastPebLock;
ULONG AtlThunkSListPtr;
ULONG IFEOKey;
ULONG CrossProcessFlags;
ULONG UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
ULONG ApiSetMap;
} PEB32, *PPEB32;
typedef struct _PEB_LDR_DATA32
{
ULONG Length;
BOOLEAN Initialized;
ULONG SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
ULONG EntryInProgress;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
ULONG DllBase;
ULONG EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY32 HashLinks;
ULONG SectionPointer;
}u1;
ULONG CheckSum;
union
{
ULONG TimeDateStamp;
ULONG LoadedImports;
}u2;
ULONG EntryPointActivationContext;
ULONG PatchInformation;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
#pragma pack()
接著就來實(shí)現(xiàn)對(duì)PEB的獲取操作,以64位為例,我們需要調(diào)用PsGetProcessPeb()這個(gè)內(nèi)核函數(shù),因?yàn)樵搩?nèi)核函數(shù)沒有被公開所以調(diào)用之前需要頭部導(dǎo)出,該函數(shù)需要傳入用戶進(jìn)程的EProcess結(jié)構(gòu),該結(jié)構(gòu)可用PsLookupProcessByProcessId函數(shù)動(dòng)態(tài)獲取到,獲取到以后直接KeStackAttachProcess()附加到應(yīng)用層進(jìn)程上,即可直接輸出進(jìn)程的PEB結(jié)構(gòu)信息,如下代碼。
#include "peb.h"
#include <ntifs.h>
// 定義導(dǎo)出
NTKERNELAPI PVOID NTAPI PsGetProcessPeb(_In_ PEPROCESS Process);
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
}
// LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS eproc = NULL;
KAPC_STATE kpc = { 0 };
PPEB64 pPeb64 = NULL;
__try
{
// HANDLE)4656 進(jìn)程PID
status = PsLookupProcessByProcessId((HANDLE)4656, &eproc);
// 得到64位PEB
pPeb64 = (PPEB64)PsGetProcessPeb(eproc);
DbgPrint("PEB64 = %p \n", pPeb64);
if (pPeb64 != 0)
{
// 驗(yàn)證可讀性
ProbeForRead(pPeb64, sizeof(PEB32), 1);
// 附加進(jìn)程
KeStackAttachProcess(eproc, &kpc);
DbgPrint("進(jìn)程基地址: 0x%p \n", pPeb64->ImageBaseAddress);
DbgPrint("ProcessHeap = 0x%p \n", pPeb64->ProcessHeap);
DbgPrint("BeingDebugged = %d \n", pPeb64->BeingDebugged);
// 脫離進(jìn)程
KeUnstackDetachProcess(&kpc);
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
PEB64代碼運(yùn)行后,我們加載驅(qū)動(dòng)即可看到如下結(jié)果:

而相對(duì)于64位進(jìn)程來說,獲取32位進(jìn)程的PEB信息可以直接調(diào)用PsGetProcessWow64Process()函數(shù)得到,該函數(shù)已被導(dǎo)出可以任意使用,獲取PEB代碼如下。
#include "peb.h"
#include <ntifs.h>
// 定義導(dǎo)出
NTKERNELAPI PVOID NTAPI PsGetProcessPeb(_In_ PEPROCESS Process);
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
}
// LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS eproc = NULL;
KAPC_STATE kpc = { 0 };
PPEB32 pPeb32 = NULL;
__try
{
// HANDLE)4656 進(jìn)程PID
status = PsLookupProcessByProcessId((HANDLE)6164, &eproc);
// 得到32位PEB
pPeb32 = (PPEB32)PsGetProcessWow64Process(eproc);
DbgPrint("PEB32 = %p \n", pPeb32);
if (pPeb32 != 0)
{
// 驗(yàn)證可讀性
ProbeForRead(pPeb32, sizeof(PEB32), 1);
// 附加進(jìn)程
KeStackAttachProcess(eproc, &kpc);
DbgPrint("進(jìn)程基地址: 0x%p \n", pPeb32->ImageBaseAddress);
DbgPrint("ProcessHeap = 0x%p \n", pPeb32->ProcessHeap);
DbgPrint("BeingDebugged = %d \n", pPeb32->BeingDebugged);
// 脫離進(jìn)程
KeUnstackDetachProcess(&kpc);
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
PEB32代碼運(yùn)行后,我們加載驅(qū)動(dòng)即可看到如下結(jié)果:

到此這篇關(guān)于C語言驅(qū)動(dòng)開發(fā)之內(nèi)核通過PEB獲取進(jìn)程參數(shù)的文章就介紹到這了,更多相關(guān)C語言驅(qū)動(dòng)開發(fā)獲取進(jìn)程參數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言編程數(shù)據(jù)在內(nèi)存中的存儲(chǔ)詳解
本篇文章是C語言編程篇,主要為大家介紹C語言編程中數(shù)據(jù)在內(nèi)存中存儲(chǔ)解析,有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09
c語言?數(shù)據(jù)存儲(chǔ)與原碼?反碼?補(bǔ)碼詳細(xì)解析
不知道你是否和我一樣好奇,學(xué)習(xí)編程語言的同時(shí)想,各個(gè)數(shù)據(jù)類型是怎樣在我們的內(nèi)存中儲(chǔ)存的呢,如果你仔細(xì)深入了解的話,你會(huì)了解其中的樂趣,了解科學(xué)家們的偉大,了解c語言2022-02-02
C++ Vector 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)
這篇文章主要介紹了C++ Vector 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
C++實(shí)現(xiàn)順序表的常用操作(插入刪出查找輸出)
實(shí)現(xiàn)順序表的插入,刪除,查找,輸出操作在C語言中經(jīng)常用到。下面小編給大家整理實(shí)現(xiàn)代碼,一起看下吧2016-08-08
vscode配置遠(yuǎn)程開發(fā)環(huán)境并遠(yuǎn)程調(diào)試運(yùn)行C++代碼的教程
這篇文章主要介紹了vscode配置遠(yuǎn)程開發(fā)環(huán)境并遠(yuǎn)程調(diào)試運(yùn)行C++代碼的教程,本文通過截圖實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
C語言數(shù)據(jù)結(jié)構(gòu)超詳細(xì)講解單向鏈表
鏈表可以說是一種最為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)了,而單向鏈表更是基礎(chǔ)中的基礎(chǔ)。鏈表是由一組元素以特定的順序組合或鏈接在一起的,不同元素之間在邏輯上相鄰,但是在物理上并不一定相鄰。在維護(hù)一組數(shù)據(jù)集合時(shí),就可以使用鏈表,這一點(diǎn)和數(shù)組很相似2022-03-03
C++ 動(dòng)態(tài)數(shù)組模版類Vector實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了C++動(dòng)態(tài)數(shù)組模版類Vector實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02

