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的特征码,以及根据索引计算函数地址的公式,还 ...
随机推荐
- 2020年12月-第02阶段-前端基础-CSS Day05
CSS Day05 1. 学成在线页面制作 理解 能够说写单页面我们基本的流程 能说出常见的css初始化语句 能说出我们CSS属性书写顺序 应用 能利用ps切图 能引入外部样式表 能把psd文件转换为 ...
- CVE-2019-11043-Nginx PHP 远程代码执行
漏洞原因 Nginx 上 fastcgi_split_path_info 在处理带有 %0a 的请求时,会因为遇到换行符 \n 导致 PATH_INFO 为空.而 php-fpm 在处理 PATH_I ...
- WPF 基础 - 在模板中找元素
1. 在 ControlTemplate 中寻找元素 <Window.Resources> <ControlTemplate x:Key="cTmp"> & ...
- 用 Numba 加速 Python 代码
原文出自微信公众号:Python那些事 一.介绍 pip install numba Numba 是 python 的即时(Just-in-time)编译器,即当你调用 python 函数时,你的全部 ...
- ch2_8_2求解幸运数问题
思路:f(x)进行十进制每位相加,g(x)进行二进制每位相加,比较是否相等即可. 小明同学学习了不同的进制之后,拿起了一些数字做起了游戏.小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中 ...
- CobaltStrike 和 Metasploit 联动
出品|MS08067实验室(www.ms08067.com) 本文作者:掉到鱼缸里的猫(Ms08067内网安全小组成员) 个人觉得CobaltStrike图形化的界面和丰富的功能,是一个超强的后渗透框 ...
- Dynamics CRM绑定表单查看当前表单的数据参数传递
我们做报表的时候,报表运行的位置可以在列表.也可以在报表区同时也可以在表单界面 其他两个都还好,不需要进行过滤,但是在表单界面运行报表需要将表单的GUID传给报表获取数据,否则就得手动去输入ID 具体 ...
- Java 时间日期系列
Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(1) Calendar Java Calendar,Date,DateFormat ...
- DDD实战让中台和微服务的落地如虎添翼
微服务到底怎么拆分和设计才算合理,拆多小才叫微服务?有没有好的方法来指导微服务和中台的设计呢? 深入DDD的核心知识体系与设计思想,带你掌握一套完整而系统的基于DDD的微服务拆分与设计方法,助力落地边 ...
- hello world!goodbye world~
我有个朋友,做ios开发做了5年,年前回家转行赚大钱去了,这个标题,其实就是因他而生. 我本人做的.net开发,也差不多快5年时间了,在这个时候暂借博客园这个平台说几句心里话,骚了勿喷:) 其实我是个 ...