5.4 Windows驱动开发:内核通过PEB取进程参数

news2024/11/16 6:51:43

PEB结构(Process Envirorment Block Structure)其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构,通过附加进程并遍历这段结构即可得到非常多的有用信息。

在应用层下,如果想要得到PEB的基地址只需要取fs:[0x30]即可,TEB线程环境块则是fs:[0x18],如果在内核层想要得到应用层进程的PEB信息我们需要调用特定的内核函数来获取。

在内核层要获取应用层进程的PEB结构,可以通过以下步骤实现:

  • 1.调用内核函数PsGetCurrentProcess获取当前进程的EPROCESS结构。
  • 2.调用内核函数KeStackAttachProcess,附加到目标进程。
  • 3.调用内核函数PsGetProcessWow64Process,获取目标进程的PEB结构信息。
  • 4.通过PEB结构的Ldr成员可以访问到该进程加载的所有模块,遍历整个Ldr链表即可得到需要的模块信息。
  • 5.遍历完成后,通过调用KeUnstackDetachProcess函数脱离进程空间。

首先在开始写代码之前需要先定义好PEB进程环境快结构体,用于对内存指针解析,新建peb.h文件并保存如下代码,这些是微软的结构定义分为32位与64位,官方定义规范而已不需要费工夫。

#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()

接着就来实现对PEB的获取操作,以64位为例,我们需要调用PsGetProcessPeb()这个内核函数,因为该内核函数没有被公开所以调用之前需要头部导出,该函数需要传入用户进程的EProcess结构,该结构可用PsLookupProcessByProcessId函数动态获取到,获取到以后直接KeStackAttachProcess()附加到应用层进程上,即可直接输出进程的PEB结构信息,如下代码。

#include "peb.h"
#include <ntifs.h>

// 定义导出
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 进程PID
        status = PsLookupProcessByProcessId((HANDLE)4656, &eproc);

        // 得到64位PEB
        pPeb64 = (PPEB64)PsGetProcessPeb(eproc);

        DbgPrint("PEB64 = %p \n", pPeb64);

        if (pPeb64 != 0)
        {
            // 验证可读性
            ProbeForRead(pPeb64, sizeof(PEB32), 1);

            // 附加进程
            KeStackAttachProcess(eproc, &kpc);

            DbgPrint("进程基地址: 0x%p \n", pPeb64->ImageBaseAddress);
            DbgPrint("ProcessHeap = 0x%p \n", pPeb64->ProcessHeap);
            DbgPrint("BeingDebugged = %d \n", pPeb64->BeingDebugged);

            // 脱离进程
            KeUnstackDetachProcess(&kpc);
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
    }

    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

PEB64代码运行后,我们加载驱动即可看到如下结果:

而相对于64位进程来说,获取32位进程的PEB信息可以直接调用PsGetProcessWow64Process()函数得到,该函数已被导出可以任意使用,获取PEB代码如下。

#include "peb.h"
#include <ntifs.h>

// 定义导出
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 进程PID
        status = PsLookupProcessByProcessId((HANDLE)6164, &eproc);

        // 得到32位PEB
        pPeb32 = (PPEB32)PsGetProcessWow64Process(eproc);

        DbgPrint("PEB32 = %p \n", pPeb32);

        if (pPeb32 != 0)
        {
            // 验证可读性
            ProbeForRead(pPeb32, sizeof(PEB32), 1);

            // 附加进程
            KeStackAttachProcess(eproc, &kpc);

            DbgPrint("进程基地址: 0x%p \n", pPeb32->ImageBaseAddress);
            DbgPrint("ProcessHeap = 0x%p \n", pPeb32->ProcessHeap);
            DbgPrint("BeingDebugged = %d \n", pPeb32->BeingDebugged);

            // 脱离进程
            KeUnstackDetachProcess(&kpc);
        }
        
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
    }

    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

PEB32代码运行后,我们加载驱动即可看到如下结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1234509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL基础理论篇(九):存储过程

文章目录 简介存储过程的形式定义一个存储过程使用delimiter定义语句结束符存储过程中的三种参数类型流控制语句 存储过程的优缺点参考文献 简介 存储过程Stored Procedure&#xff0c;SQL中的另一个重要应用。 前面说的视图&#xff0c;只能勉强跟编程中的函数相似&#xff…

datagrip只导出表结构

话不多说&#xff0c;直接上教程。 datagrip版本&#xff1a;2022.3 第一步&#xff0c;连接数据库 第二步&#xff0c;右击数据库&#xff0c;复制即可

vivado产生报告阅读分析14-时序报告10

Vivado IDE 中的例外报告 “ Report Exceptions ”对话框 在 AMD Vivado ™ IDE 中 &#xff0c; 选择“ Reports ” → “ Timing ” → “ Report Exceptions ” &#xff08; 报告 > 时序 > 例外报告 &#xff09; 即可打开“Report Exceptions ”对话框。 从“…

做接口自动化遇到的20个难点,记录下我是如何解决的!

我是一名接口自动化测试工程师&#xff0c;在公司中负责接口自动化测试的设计和执行。在公司中&#xff0c;接口自动化测试非常重要&#xff0c;因为公司的业务场景非常复杂&#xff0c;需要保证接口的质量。在这篇文章中&#xff0c;我将分享我在公司中接口自动化测试遇到的20…

Java JSON字符串替换其中对应的值

代码&#xff1a; public static void main(String[] args) { // String theData crmScene.getData();String theData "[{\"type\":1,\"values\":[\"审批中\",\"未交付\"],\"name\":\"status\"}]"…

UE4 基础篇十四:自定义插件

文末有视频地址和git地址 一、概念 虚幻里插件都是用C++写的,C++包括.h文件和.cpp文件,.h头文件通常包含函数类型和函数声明,cpp文件包含这些类型和函数的实现, 你为项目编写的所有代码文件都必须位于模块中,模块就是硬盘里的一个文件夹,包含名为“Build.cs”的C#文件…

政府采购变数大,联想还值不值得代理渠道商们“跟”?

文&#xff5c;新熔财经 作者&#xff5c;余一 “事业单位更换纯国产电脑”、“联想被排除在大订单之外”等消息下&#xff0c;联想硬件终端产品面临的问题日益严峻。 早在今年年初&#xff0c;联想集团&#xff08;下称联想&#xff09;掌门人杨元庆坦承&#xff0c;“智能…

深入了解Java 8 新特性:Stream流的实践应用(一)

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概一万多字&#xff0c;预计阅读时间长需要10分钟&#xff08;不要害怕字数过多&#xff0c;其中有一大部分是示例代码&#xff0c;读起…

关于在3dsmax中制作的模型导入UE后尺寸大小不对的问题

现象 在3dsmax中的基本单位为毫米 在UE中基本单位是厘米 我在3dsmax中创建一个长宽高均为1000mm的方块 然后导入到UE中的世界坐标原点 方块向X轴正方向移动100个单位100cm1000mm&#xff0c;按理来说&#xff0c;新方块的此时应该和旧方块是贴着的&#xff0c;但是现象确是两者…

厦门城市内涝的落地解决方案,城市内涝积水监测系统

有来过厦门的都知道这是一座让人想要扎根的城市&#xff0c;但是这座城市在受2023年第11号台风“海葵”影响&#xff0c;9月份连续3天出现大暴雨天气&#xff0c;厦门受强降水影响&#xff0c;全市共有积水点位24处&#xff0c;造成了极大的交通阻塞&#xff0c;却没有及时进行…

P9232 [蓝桥杯 2023 省 A] 更小的数(区间DP)

求大数字某连续部分反转后&#xff0c;比原数字小的个数 思路&#xff1a;自前向后遍历 ai是位于数字第i位的数字 aj是位于数字第j位的数字&#xff08;i<j&#xff09; ai>aj f[ai][aj]1; ai<aj f[ai][aj]0; aiaj f[ai][aj]f…

1688开放平台API接口获取商品详情信息

一、API接口简介 1688开放平台提供了丰富的API接口&#xff0c;帮助开发者快速实现各种业务需求。其中&#xff0c;商品详情信息的获取是很多业务场景中的基础功能。通过调用相应的API接口&#xff0c;您可以获取到商品的基本信息、价格、库存等数据&#xff0c;为您的业务提供…

【Android Jetpack】理解ViewModel

文章目录 ViewModel实现ViewModelViewModel的生命周期在Fragments间分享数据ViewModel和SavedInstanceState对比ViewModel原理ViewModel与AndroidViewModel ViewModel Android系统提供控件&#xff0c;比如Activity和Fragment&#xff0c;这些控件都是具有生命周期方法&#x…

鸿蒙系统扫盲(二):再谈鸿蒙是不是安卓套壳?

最近小米发布了澎湃OS&#xff0c;vivo发布了蓝OS&#xff0c;好像自从华为回归后&#xff0c;大伙都开始写自己的OS了&#xff0c;小米官方承认是套壳安卓&#xff0c;然后被大家喷了&#xff0c;于是鸿蒙是不是安卓套壳的话题又回到了大众的视野&#xff0c;今天在讨论下这个…

HarmonyOS ArkTS开发语言介绍(三)

1 引言 Mozilla创造了JS&#xff0c;Microsoft创建了TS&#xff0c;Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力&#xff0c;到具备类型系统的高效工程开发能力&#xff0c;再到融合声明式UI、多维状态管理等丰富的应用开发能力&#xff0c;共同组成了相关的演进脉…

vue3 uniapp h5 安卓和iOS开发适配踩坑记录

font-size适配屏幕大小及iOS和安卓状态栏及安全距离的处理 App.vue <script setup lang"ts"> import { onLaunch, onShow, onHide } from "dcloudio/uni-app"; import ./main.scss onLaunch(() > {console.log("App Launch");var wid…

gitlab设置项目clone地址

直接在线修改地址 虽然是个小问题但是我查了很多都是说要去修改配置文件&#xff0c;可是我是docker部署的&#xff0c;修改配置文件之后我还要重新打包镜像想想都不咋规范&#xff0c;后才终于知道可以直接设置&#xff0c;不要改配置文件&#xff01;&#xff01;&#xff0…

亚马逊运营中动态/静态住宅IP代理的应用有哪些?跨境电商必备

作为全球最大的电商平台之一&#xff0c;亚马逊已经成为许多商家的首选销售平台。而代理IP作为近几天互联网的热门工具&#xff0c;在跨境电商界也起着非常强大的作用。那么在亚马逊运营中&#xff0c;适合动态住宅代理还是静态住宅代理呢&#xff1f;下面我们一起来探索&#…

C语言for循环实现斐波那契数列

斐波那契数列指的是这样一个数列 0,1, 1, 2, 3, 5, 8, 13, 21… 这个数列从第3项开始&#xff0c;每一项都等于前两项之和。 int main(){//前两项分别定义为i&#xff0c;j 两项之和我们定义为k//由于从第三项开始&#xff0c;所以先将前两项打印出来0和1int i0,j1,k;printf(&…

解决requests库进行爬虫ip请求时遇到的错误的方法

目录 一、超时错误 二、连接错误 三、拒绝服务错误 四、内容编码错误 五、HTTP错误 在利用requests库进行网络爬虫的IP请求时&#xff0c;我们可能会遇到各种错误&#xff0c;如超时、连接错误、拒绝服务等等。这些错误通常是由目标网站的限制、网络问题或我们的爬虫代码中…