首页 > 系统相关 >5.3 Windows驱动开发:内核取应用层模块基址

5.3 Windows驱动开发:内核取应用层模块基址

时间:2023-11-21 20:13:46浏览次数:36  
标签:ENTRY32 5.3 Windows pPeb pEProcess 内核 模块 KAPC 应用层

在上一篇文章《内核取ntoskrnl模块基地址》中我们通过调用内核API函数获取到了内核进程ntoskrnl.exe的基址,当在某些场景中,我们不仅需要得到内核的基地址,也需要得到特定进程内某个模块的基地址,显然上篇文章中的方法是做不到的,本篇文章将实现内核层读取32位应用层中特定进程模块基址功能。

上一篇文章中的PPEB32,PLIST_ENTRY32等结构体定义依然需要保留,此处只保留核心代码,定义部分请看前一篇文章,自定义读取模块基址核心代码如下,调用GetModuleBaseWow64()用户需传入进程的PROCESS结构该结构可通过内核函数PsLookupProcessByProcessId获取到。

对于函数内部执行过程如下:

  • 1.根据传入的EProcess结构调用KeStackAttachProcess附加到该进程内。
  • 2.调用内核函数PsGetProcessWow64Process此函数可得到该进程空间内PEB结构数据。
  • 3.通过for循环遍历整个pPeb->Ldr链表,并在遍历过程中通过RtlEqualUnicodeString判断是否是我们需要的模块。
  • 4.如果判断是我们需要取出的模块名,则将LdrEntry->DllBase取出,此处取出的基地址也即是我们所需要的。
  • 5.比较结束后,通过调用KeUnstackDetachProcess这个内核模块脱离进程空间。
ULONGLONG GetModuleBaseWow64(_In_ PEPROCESS pEProcess, _In_ UNICODE_STRING usModuleName)
{
    ULONGLONG BaseAddr = 0;
    KAPC_STATE KAPC = { 0 };
    KeStackAttachProcess(pEProcess, &KAPC);
    PPEB32 pPeb = (PPEB32)PsGetProcessWow64Process(pEProcess);
    if (pPeb == NULL || pPeb->Ldr == 0)
    {
        KeUnstackDetachProcess(&KAPC);
        return 0;
    }

    for (PLIST_ENTRY32 pListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)pPeb->Ldr)->InLoadOrderModuleList.Flink;
        pListEntry != &((PPEB_LDR_DATA32)pPeb->Ldr)->InLoadOrderModuleList; pListEntry = (PLIST_ENTRY32)pListEntry->Flink)
    {
        PLDR_DATA_TABLE_ENTRY32 LdrEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);

        if (LdrEntry->BaseDllName.Buffer == NULL)
        {
            continue;
        }

        // 当前模块名链表
        UNICODE_STRING usCurrentName = { 0 };
        RtlInitUnicodeString(&usCurrentName, (PWCHAR)LdrEntry->BaseDllName.Buffer);

        // 比较模块名是否一致
        if (RtlEqualUnicodeString(&usModuleName, &usCurrentName, TRUE))
        {
            BaseAddr = (ULONGLONG)LdrEntry->DllBase;
            KeUnstackDetachProcess(&KAPC);
            return BaseAddr;
        }
    }
    KeUnstackDetachProcess(&KAPC);
    return 0;
}

如上就是如何得到特定模块基址的方法,如下是入口函数的调用方法,首先通过传入6164这个PID号,得到进程EProcess结构,其次使用RtlInitUnicodeString(&unicode, wchar_string)初始化得到kernel32.dll字符串,最终调用GetModuleBaseWow64函数获取到进程6164kernel32.dll的模块基地址信息。

VOID UnDriver(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
    DbgPrint(("hello lyshark \n"));

    PEPROCESS pEProcess;
    HANDLE PID = (HANDLE)6164;

    // 初始化字符串
    UNICODE_STRING unicode;
    wchar_t *wchar_string = L"kernel32.dll";
    RtlInitUnicodeString(&unicode, wchar_string);

    // 取模块句柄
    PsLookupProcessByProcessId((HANDLE)PID, &pEProcess);
    ULONGLONG base32 = GetModuleBaseWow64(pEProcess, unicode);

    DbgPrint("ModuleBaseAddress: 0x%X \n", base32);


    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

这段代码输出效果如下所示:

标签:ENTRY32,5.3,Windows,pPeb,pEProcess,内核,模块,KAPC,应用层
From: https://www.cnblogs.com/LyShark/p/17847446.html

相关文章

  • 5.4 Windows驱动开发:内核通过PEB取进程参数
    PEB结构(ProcessEnvirormentBlockStructure)其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构,通过附加进程并遍历这段结构即可得到非常多的有用信息。在应用层下,如果想要得到PEB的基地址只需要取fs:[0x30]即......
  • 8.3 Windows驱动开发:内核遍历文件或目录
    在笔者前一篇文章《内核文件读写系列函数》简单的介绍了内核中如何对文件进行基本的读写操作,本章我们将实现内核下遍历文件或目录这一功能,该功能的实现需要依赖于ZwQueryDirectoryFile这个内核API函数来实现,该函数可返回给定文件句柄指定的目录中文件的各种信息,此类信息会保存在PF......
  • 7.1 Windows驱动开发:内核监控进程与线程回调
    在前面的文章中LyShark一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以监控进程线程创建为例,在Win10系统中监控进程与线程可以使用微软提供给我们的两个新函数来实现,此类函数的原理是创建一个回调事件,当有进程或线程被创建或者注销时,系统会通过回......
  • Windows CMD常用命令大全
    1.常用命令1.1cd命令//进入d盘D://进入F盘F:cd/?//获取使用帮助cd\//跳转到硬盘的根目录cdC:\WINDOWS//跳转到当前硬盘的其他文件d://跳转到其他硬盘cd/de:\software//跳转到其他硬盘的其他文件夹,注意此处必须加/d参数。否......
  • 8.2 Windows驱动开发:内核解锁与强删文件
    在某些时候我们的系统中会出现一些无法被正常删除的文件,如果想要强制删除则需要在驱动层面对其进行解锁后才可删掉,而所谓的解锁其实就是释放掉文件描述符(句柄表)占用,文件解锁的核心原理是通过调用ObSetHandleAttributes函数将特定句柄设置为可关闭状态,然后在调用ZwClose将其文件关......
  • 计算机科学与技术之网络编程 Windows下VC6.0 网络SOCKET编程C语言实现(服务端)
    在VC6.0平台用C语言实现网络SOCKET通信一.在VC6.0平台创建Win32ConsoleApplication工程工程名称自拟(或输入firstSocket)添加新建项文件C++SourceFile 文件名自拟,后缀.c(如firstSocket.c)在firstSocket.c加入头文件#include<winsock2.h>链接动态库#pragmacomment(l......
  • 【2023潇湘夜雨】WIN10_Pro_22H2.19045.3754软件选装纯净版11.20
    【系统简介】=============================================================1.本次更新母盘来自WIN11_Pro_22H2.19045.3754。2.增加部分优化方案,手工精简部分较多。3.OS版本号为19045.3754。精简系统只是为部分用户安装,个别要求高的去MSDN下。4.集成《DrvCeo-2.15.0.5》网卡版、......
  • 在Linux中快速编译出带图标的windows程序
    1.摘要以前做的一个项目有个需求,需要在Linux系统上的服务后端根据前端配置动态编译出能在Windows平台运行的程序,并且能支持程序带图标,虽然使用Go语言能够方便的编译跨平台运行的代码,但编译带资源图标的Windows可执行程序还未尝试过,本篇文章对这部分内容做一个过程记录......
  • 戴尔PowerEdge R750 机架式服务器初始安装Windows Server 2019 服务器系统
    公司因为业务需求,从戴尔原厂网购三台R750服务器,戴6块a4显卡和6块960G的SSD,由于没有要求配置RAID和操作系统,现记录一下安装过程。SSD:960G,六块服务器型号:R750RAID类型:RAID1+RAID5,具体说明介绍见DELL官网介绍。 ......
  • 如何在Windows端安装scala
    一.首先确保jdk安装成功  首先在安装之前,确保本地已经安装了JDK1.5以上的版本,在此安装的是1.8版本。并且已经设置了JAVA_HOME环境变量及JDK的bin目录。新建环境变量编辑path系统变量,添加%JAVA_HOME%\bin 验证环境变量是否配置成功。 二.下载Scala安装文件接着我们......