5.3 Windows驱动开发:内核取应用层模块基址
在上一篇文章《内核取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函数获取到进程6164中kernel32.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;
}
这段代码输出效果如下所示:

5.3 Windows驱动开发:内核取应用层模块基址的更多相关文章
- Windows驱动开发-内核常用内存函数
搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool
- Windows驱动开发(中间层)
Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- [Windows驱动开发](一)序言
笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓——内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...
- windows驱动开发推荐书籍
[作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...
- Windows驱动——读书笔记《Windows驱动开发技术详解》
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- Windows驱动开发-IRP的完成例程
<Windows驱动开发技术详解 >331页, 在将IRP发送给底层驱动或其他驱动之前,可以对IRP设置一个完成例程,一旦底层驱动将IRP完成后,IRP完成例程立刻被处罚,通过设置完成例程 ...
- C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载
基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...
- C++第三十三篇 -- 研究一下Windows驱动开发(一)内部构造介绍
因为工作原因,需要做一些与网卡有关的测试,其中涉及到了驱动这一块的知识,虽然程序可以运行,但是不搞清楚,心里总是不安,觉得没理解清楚.因此想看一下驱动开发.查了很多资料,看到有人推荐Windows驱动 ...
- Windows 驱动开发 - 5
上篇<Windows 驱动开发 - 4>我们已经完毕了硬件准备. 可是我们还没有详细的数据操作,比如接收读写操作. 在WDF中进行此类操作前须要进行设备的IO控制,已保持数据的完整性. 我 ...
随机推荐
- Tomcat--多实例
配置信息 centos:7.8 tomcat:7.0.3 instans1:/usr/local/tomcat/instans1 8081 instans2:/usr/local/tomcat/ins ...
- [kuangbin带你飞]专题十二 基础DP1 题解+总结
kuangbin带你飞:点击进入新世界 文章目录 目录 文章目录 1.Max Sum Plus Plus 2.Ignatius and the Princess IV 3.Monkey and Ban ...
- POJ - 3180 The Cow Prom ( korasaju 算法模板)
The Cow Prom POJ - 3180 题意: 奶牛圆舞:N头牛,M条有向绳子,能组成几个歌舞团(团内奶牛数 n >= 2)?要求顺时针逆时针都能带动舞团内所有牛. 分析: 所谓能带动, ...
- Java 8 Stream原理解析
说起 Java 8,我们知道 Java 8 大改动之一就是增加函数式编程,而 Stream API 便是函数编程的主角,Stream API 是一种流式的处理数据风格,也就是将要处理的数据当作流,在管 ...
- Android内存泄露检测 LeakCanary2.0(Kotlin版)的实现原理
本文介绍了开源Android内存泄漏监控工具LeakCanary2.0版本的实现原理,同时介绍了新版本新增的hprof文件解析模块的实现原理,包括hprof文件协议格式.部分实现源码等. 一.概述 L ...
- 版本升级 | 兼容VSCode及全系IDE,代码风险一键查询
OpenSCA插件上新啦~ Jetbrains IDE插件全新升级,很多朋友提了需求的VSCode咱也支持上啦~ 当然,CEC-IDE也是兼容的(手动狗头). OpenSCA-VSCode-plugi ...
- 从“预见”到“遇见”SAE 引领应用步入 Serverless 全托管新时代
--黛忻 阿里云SAE产品经理 近年来,企业的数字化随着互联网的普及发展越来越快,技术架构也是几经更迭,尤其是在线业务部分.从最初的单体应用到分布式应用再到云原生应用,出现了进阶式的变化. 带来便利的 ...
- docker容器常用操作
1.查看运行容器 docker ps: 2.查看所有容器 docker ps -a: 3.查看容器的日志 docker logs 容器名称/容器ID: 4.运行镜像 docker run --na ...
- java基础(4)--javadoc文档与命令
一.Javadoc文档 javadoc是Sun公司提供的一个技术,它从程序源代码中抽取类.方法.成员等注释形成一个和源代码配套的API帮助文档.也就是说,只要在编写程序时以一套特定的标签作注释,在程序 ...
- SV 数据类型
system verilog可以用于设计也可以进行验证 语法规则 SV新数据类型 SV数据类型 bit - 0-255 byte - -127 - 128 # 快速进行sv文件仿真 VCS -R -s ...