Win64 驱动内核编程-3.内核里使用内存
内核里使用内存
内存使用,无非就是申请、复制、设置、释放。在 C 语言里,它们对应的函数是:malloc、memcpy、memset、free;在内核编程里,他们分别对应 ExAllocatePool、RtlMoveMemory、
RtlFillMemory、ExFreePool。它们的原型分别是:
需要注意的是,RtlFillMemory 和 memset 的原型不同、ExAllocatePool 和 malloc 的原型也不同。前者只是参数前后调换了一下位置,但是后者则多了一个参数:PoolType。这个PoolType 也是必须了解的。PoolType 在 在 MSDN 的介绍上有 N 种, 其实 常用有 的只有 2 种 :
PagedPool 和 和 NonPagedPool。PagedPool 是 分页内存,简单来说就是物理内存不够时,会把这片内存移动 到硬盘上,而 NonPagedPool 是 无论物理内存如何紧缺,都绝对不把 这片内存的内容移动到硬盘上。在往下讲之前,先补充一个知识, 就是我们操作的内存,都是虚拟内存,和物理内存是两码事。 但虚拟内存 的数据是 放在 物理内存上的,两者存在映射关系 , 一般来说,一 片 物理内存可以映射为多片虚拟内存 , 但一片虚拟内存必定只对应一片物理内存。假设虚拟内存是 0Xfffff80001234567 在物理内存的地址是 0x123456,当物理内存不够用时,物理内存 0x123456 的原始内容就挪到硬盘上,然后把另外一片急需要用的内容移到物理内存里。此时,当你再读取 0Xfffff80001234567 的内容时,就会引发缺页异常,系统就会把在硬盘上的内容再次放到物理内存中(如果这个过程失败,一般就死机了)。以上说了这么多废话,总结两句:1.NonPagedPool 的 总量 是有限的( 具体 大小和你物理内存的大小相) 关) ,而 而 PagedPool 的 总量较多 。申请了 内存忘记释放 都会造成 内存泄漏,但是很明显忘记放 释放 NonPagedPool 的 后果要严重 得多 ;2. 一般来说 ,PagedPool 用来放 数据 (比如 你用ZwQuerySystemInformation 枚举片 内核模块,可以申请一大片 PagedPool 存放) 返回的数据) ,而 而 NonPagedPool 用来放 代码 (你 写内核 shellcode 并 需要执行时, 必须 使用 NonPagedPool存放 shellcode) ) 。 以我 的经验来说,访问到切换出去的内存没事,但是 执行到 切换出去的内存必然蓝屏 ( 这) 只是我的经验,正确性待定)。3. 在 用户态 ,内存 是有 属性的, 有的 内存 片只 能 读 不 能 写 不 能 执行 ( ( PAGE_READ) ) , 有的 内 存 片 可 以 读 可 以 写 也 可 以 执 行(PAGE_READ_WRITE_EXECUTE)。在内核里,PagedPool 和 和 NonPagedPool 都 是 可读可写可执行的 , 而且没有类似 VirtualProtect 之类的函数。示例代码:
void Test() {
PVOID ptr1 = ExAllocatePool(PagedPool ,0x100);
PVOID ptr2 = ExAllocatePool(NonPagedPool ,0x200);
RtlFillMemory(ptr2 ,0x200 ,0x90);
RtlMoveMemory(ptr1 ,ptr2 ,0x50);
ExFreePool(ptr1);
ExFreePool(ptr2);
DbgPrint("[KrnlHW64]tttttttttt\n");}
到这里顺便提醒下大家,驱动里面的SEH很多时候都是在自己骗自己,该蓝还得蓝。我随便测试了下。
在内核里想要写入“别人的”内存(一般指 NTOS 等系统模块的内存空间),还有另外的规矩,这里又涉及到另外两个概念:IRQL 和内存保护。IRQL 称为中断请求级别,从 0~31 共32 个级别;内存保护可以打开和关闭,如果在内存处于保护状态时写入,会导致蓝屏。 一般来说 ,要写入“ 别人 的” 内核内存 , 必须关闭内存写保护,并把 IRQL 提升到 2 才行 (绝大多数候 时候 IRQL 都为 为 0 ,当 当 IRQL=2 时,会阻断大部分线程执行, 防止 执行出错) )。内存是否处于写保护的状态记录在 CR0 寄存器上,因此直接修改 CR0 寄存器的值即可;而提升或降低IRQL 则使用 KeRaiseIrqlToDpcLevel 和 KeLowerIrql 实现(WIN64 的 IRQL 值记录在 CR8 寄存器上,而 WIN32 的 IRQL 值记录在 KPCR 上)。代码如下:
KIRQL WPOFFx64() {
KIRQL irql = KeRaiseIrqlToDpcLevel();
UINT64 cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
return irql;
}
void WPONx64(KIRQL irql) {
UINT64 cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
KeLowerIrql(irql);
}
void Test() {
KIRQL irql = WPOFFx64();
PVOID HookCode = ExAllocatePool(NonPagedPool, 0x200);
RtlFillMemory(HookCode, 0x200, 0x90);
RtlMoveMemory(HookCode, NtOpenProcess, 0x3);
RtlMoveMemory(NtOpenProcess ,HookCode , 0x3);
WPONx64(irql);
}
注意:如果不调用WPOFFx64,WPONx64直接去写内存会蓝屏,直接往上面的那个位置写0也会蓝屏。
至于写入“别人的”内存,还有一种微软推荐的安全方式,就是 MDL 映射内存的方式。
这个比较麻烦,大概方法是 申请一个 MDL (类似 句柄的 玩意) ) ,然后 尝试 锁定页面 ,如果 成功,则 让 系统分配一个 “ 安全 ” 的虚拟地址再行 写入, , 写入 完毕 后 解锁页面 并释放掉 MDL。以下是某人写的 SafeCopyMemory
BOOLEAN SafeCopyMemory(PVOID pDestination, PVOID pSourceAddress, SIZE_T SizeOfCopy)
{
PMDL pMdl = NULL;
PVOID pSafeAddress = NULL;
if (!MmIsAddressValid(pDestination) || !MmIsAddressValid(pSourceAddress))
return FALSE;
pMdl = IoAllocateMdl(pDestination, (ULONG)SizeOfCopy, FALSE, FALSE, NULL);
if (!pMdl)
return FALSE;
__try
{
MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(pMdl);
return FALSE;
}
pSafeAddress = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
if (!pSafeAddress)
return FALSE;
__try
{
RtlMoveMemory(pSafeAddress, pSourceAddress, SizeOfCopy);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{;}
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
return TRUE;
}
void Test() {
PVOID HookCode = ExAllocatePool(NonPagedPool, 0x200);
RtlFillMemory(HookCode, 0x200, 0x90);
RtlMoveMemory(HookCode, NtOpenProcess, 0x3);
SafeCopyMemory(NtOpenProcess, HookCode, 0x3);
}
声明:上面的代码都是来源于一个网上资料,作者是 胡文亮。感谢这位前辈。之后的内容也是,我在看着这本书学习整理东西,在这里说是要表达我们要最终他人劳动成果。
Win64 驱动内核编程-3.内核里使用内存的更多相关文章
- Win64 驱动内核编程-8.内核里的其他常用
内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- Win64 驱动内核编程-5.内核里操作文件
内核里操作文件 RING0 操作文件和 RING3 操作文件在流程上没什么大的区别,也是"获得文件句柄->读/写/删/改->关闭文件句柄"的模式.当然了,只能用内核 A ...
- Win64 驱动内核编程-6.内核里操作注册表
内核里操作注册表 RING0 操作注册表和 RING3 的区别也不大,同样是"获得句柄->执行操作->关闭句柄"的模式,同样也只能使用内核 API 不能使用 WIN32 ...
- Win64 驱动内核编程-4.内核里操作字符串
内核里操作字符串 字符串本质上就是一段内存,之所以和内存使用分开讲,是因为内核里的字符串太有花 样了,细数下来竟然有 4 种字符串!这四种字符串,分别是:CHAR*.WCHAR*.ANSI_STRIN ...
- WIN64内核编程-的基础知识
WIN64内核编程基础班(作者:胡文亮) https://www.dbgpro.com/x64driver 我们先从一份"简历"说起: 姓名:X86或80x86 性别:? 出生 ...
- Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)
驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...
- Win64 驱动内核编程-18.SSDT
SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...
- Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)
SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...
随机推荐
- 关于windows下服务一直处于启动ing的处理办法
1,找到服务名称,xxxx 进入cmd 2,sc queryex xxxx,找到pid 3,taskkill /f /pid 123 就可以终止这个启动中的进程了
- 解决新版谷歌浏览器在http请求下无法开启麦克风问题
1.在浏览器地址栏中输入"chrome://flags/#unsafely-treat-insecure-origin-as-secure", 2.将该选项置为Enabled, 3 ...
- [virtualenv][python] 环境管理——对 virtualenv 更轻便的封装
virtualenv_simple_wrapper 如有错误,欢迎指出 Char-z 项目地址 gitee: virtualenv_simple_wrapper 使用说明 下载文件 virtualen ...
- 如何下载Image Properties Context Menu(图片)插件
如何下载Image Properties Context Menu(图片)插件 可以通过:http://www.cnplugins.com/zhuanti/four-image-processing. ...
- Vulkan移植GpuImage(一)高斯模糊与自适应阈值
自适应阈值效果图 demo 这几天抽空看了下GpuImage的filter,移植了高斯模糊与自适应阈值的vulkan compute shader实现,一个是基本的图像处理,一个是组合基础图像处理聚合 ...
- 《Selenium自动化测试实战:基于Python》之 Python与Selenium环境的搭建
第2章 Python与Selenium环境的搭建 购买链接: 京东:https://item.jd.com/13123910.html 当当:http://product.dangdang.co ...
- 「HTML+CSS」--自定义按钮样式【001】
前言 Hello!小伙伴! 首先非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 哈哈 自我介绍一下 昵称:海轰 标签:程序猿一只|C++选手|学生 简介:因C语言结识编程,随后转入计算机 ...
- 灵魂拷问!浏览器输入「xxxxhub」的背后.....
Hey guys 各位读者姥爷们大家好,这里是程序员 cxuan 计算机网络连载系列的第 13 篇文章. 到现在为止,我们算是把应用层.运输层.网络层和数据链路层都介绍完了,那么现在是时候把这些内容都 ...
- Spring IOC 特性有哪些,不会读不懂源码!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 多线程.锁.JVM调优,都背出花啦,怎么一写代码还是乱糟糟? 为什么这些无论从书本. ...
- Java利用线程工厂监控线程池
目录 ThreadFactory 监控线程池 扩展线程池 扩展线程池示例 优化线程池大小 线程池死锁 线程池异常信息捕获 ThreadFactory 线程池中的线程从哪里来呢?就是ThreadFoct ...