聊一聊 .NET高级调试 内核模式堆泄露
一:背景
1. 讲故事
前几天有位朋友找到我,说他的机器内存在不断的上涨,但在任务管理器中查不出是哪个进程吃的内存,特别奇怪,截图如下:
在我的分析旅程中都是用户态模式的内存泄漏,像上图中的异常征兆已经明确告诉你了,不是用户态程序吃的内存,那就是内核态程序吃的,比如:
- 某些驱动程序
- 操作系统
从概率上来说一般都是某些第三方程序内存泄露导致的,这一篇我们就来聊一聊这种问题该如何解决。
二:内核模式堆泄露分析
1. 驱动程序是如何分配内存的
相信有很多朋友都知道,用户态的程序是直接或者间接的调用 VirtualAlloc
方法来向操作系统要内存,包括 C# 的 GC 堆也是一样,它的方法签名如下:
LPVOID VirtualAlloc([in, optional] LPVOID lpAddress,[in] SIZE_T dwSize,[in] DWORD flAllocationType,[in] DWORD flProtect
);
那内核中的驱动程序是如何向操作系统要内存的呢?一般都是调用 ExAllocatePool2
方法来要内存的,签名如下:
DECLSPEC_RESTRICT PVOID ExAllocatePool2(POOL_FLAGS Flags,SIZE_T NumberOfBytes,ULONG Tag
);
上面有两个参数要详细解释一下:
- Flags 参数
一般用的多的就是 POOL_FLAG_NON_PAGED
和 POOL_FLAG_PAGED
两种,前者表示分配的内存是需要永久驻留内存,不可以交换到硬盘的。后者分配的内存是可以交换到硬盘的。
- Tag 参数
这个参数的本意就是方便日后洞察内存泄露的,它强行让一块内存和这个 Tag(4byte的ascii 字符串)
做了强绑定,到时候通过这个 tag 就知道是谁分配的内存。
2. 制造内核模式堆泄露
为了能够让驱动程序泄露,可以使用微软提供的 NotMyFault
工具,这个工具利用 myfault.sys
驱动不断的向操作系统分配内存。官方网址为:https://learn.microsoft.com/zh-cn/sysinternals/downloads/notmyfault
打开 myfault 工具然后输入 40M/s 的泄露,并分配在非换页池
中,同时配置下内核态转储dump
, 代码和截图参考如下:
ExAllocatePool2(POOL_FLAG_NON_PAGED,40*1024*1024,"Leak");
在泄露的过程中,通过 Process Explorer 很明显的发现提交了 6.7G 的内存,其中有 4.9G 是在 NonPaged 中,即通过上图中的 POOL_FLAG_NON_PAGED 标记分配的,截图如下:
接下来在 MyFault 上切换到 Crash 选项卡,强行让操作系统蓝屏来生成 dump 文件。
3. dump 分析
拿到dump后,先通过 !vm 观察下操作系统级的虚拟内存的分布情况。
3: kd> !vm
...
Physical Memory: 2069421 ( 8277684 Kb)
Available Pages: 445015 ( 1780060 Kb)
ResAvail Pages: 707292 ( 2829168 Kb)
Locked IO Pages: 0 ( 0 Kb)
Free System PTEs: 4295052431 (17180209724 Kb)
...
Modified Pages: 11479 ( 45916 Kb)
Modified PF Pages: 11479 ( 45916 Kb)
Modified No Write Pages: 0 ( 0 Kb)
NonPagedPool Usage: 1219892 ( 4879568 Kb)
NonPagedPoolNx Usage: 24512 ( 98048 Kb)
NonPagedPool Max: 4294967296 (17179869184 Kb)
PagedPool Usage: 32907 ( 131628 Kb)
PagedPool Maximum: 4294967296 (17179869184 Kb)
...
NonPagedPool Commit: 1246469 ( 4985876 Kb)
...
Sum System Commit: 1409562 ( 5638248 Kb)
Total Private: 279673 ( 1118692 Kb)********** Sum of individual system commit + Process commit exceeds overall commit by 1952 Kb ? ********
Committed pages: 1688747 ( 6754988 Kb)
Commit limit: 4166573 ( 16666292 Kb)
从卦中的 NonPagedPool Usage
指标可以看到,当前的 非换页池
占用了 4.8G 内存,总计 121w 的内存页。
接下来就是要深挖下 非换页池
,看看到底都是什么 Tag 分配的,可以使用 !poolused 2
命令。
3: kd> !poolused 2
....Sorting by NonPaged Pool ConsumedNonPaged PagedTag Allocs Used Allocs UsedLeak 119 4991221760 0 0 UNKNOWN pooltag 'Leak', please update pooltag.txtConT 238 14499840 0 0 UNKNOWN pooltag 'ConT', please update pooltag.txtKETR 16410 8117664 0 0 UNKNOWN pooltag 'KETR', please update pooltag.txtEtwB 196 7565568 2 131072 Etw Buffer , Binary: nt!etw2872 6 5660864 0 0 UNKNOWN pooltag '2872', please update pooltag.txt287R 1026 4183040 0 0 UNKNOWN pooltag '287R', please update pooltag.txtFile 9734 3877408 0 0 File objects Thre 1257 3217920 0 0 Thread objects , Binary: nt!psEtwR 12141 2672640 0 0 Etw KM RegEntry , Binary: nt!etw
...
从卦中数据看,有一个神秘的 Tag=Leak
的内存分配,它分配了 119 次,总大小 4.99G。 哈哈,其实就是刚才通过 MyFault 做的 40M/s 的内存分配。
接下来的问题是:这个 Leak 是哪一个驱动程序所为呢?最简单的办法就是在各个驱动的内存空间中做内存搜索,看看谁里面有 Leak
的asc硬编码,对吧,有了这个思路,先用 lm 看看里面都有哪些 sys 。
3: kd> lm
start end module name
ffffc25c`891b0000 ffffc25c`89480000 win32kbase (deferred)
ffffc25c`8a190000 ffffc25c`8a545000 win32kfull (deferred)
...
fffff807`22600000 fffff807`23646000 nt (pdb symbols)
fffff807`23c00000 fffff807`23d16000 clipsp (deferred)
fffff807`47f30000 fffff807`47f4b000 monitor (deferred)
fffff807`47f50000 fffff807`47f59000 myfault (deferred)
... Unloaded modules:
fffff807`3c6e0000 fffff807`3c6ec000 360Sensor64.sys
fffff807`31550000 fffff807`31560000 dump_storport.sys
fffff807`315a0000 fffff807`315d3000 dump_storahci.sys
fffff807`31000000 fffff807`3101e000 dump_dumpfve.sys
fffff807`26b80000 fffff807`26bac000 luafv.sys
fffff807`26b20000 fffff807`26b30000 dump_storport.sys
fffff807`26b70000 fffff807`26ba3000 dump_storahci.sys
fffff807`26bd0000 fffff807`26bee000 dump_dumpfve.sys
fffff807`28130000 fffff807`2814c000 dam.sys
fffff807`24200000 fffff807`2420a000 360elam64.sys
fffff807`25230000 fffff807`25241000 hwpolicy.sys
接下来就是写脚本在每个 sys 的 start ~ end
区间做 s 搜索,这个脚本我就不放了,非常简单,最终就在 myfault.sys 中成功找到了 Leak
硬编码,参考如下:
3: kd> lmvm myfault
Browse full module list
start end module name
fffff807`47f50000 fffff807`47f59000 myfault (deferred) Image path: \??\C:\Windows\system32\drivers\myfault.sysImage name: myfault.sysBrowse all global symbols functions dataTimestamp: Fri Sep 30 00:17:31 2022 (6335C51B)CheckSum: 00010CEDImageSize: 00009000Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4Information from resource tables:3: kd> ? fffff807`47f59000 - fffff807`47f50000
Evaluate expression: 36864 = 00000000`000090003: kd> s -a fffff807`47f50000 L?0x9000 "Leak"
fffff807`47f51559 4c 65 61 6b 0f 42 c1 41-8d 49 fd 8b d0 ff 15 0c Leak.B.A.I......
fffff807`47f515c7 4c 65 61 6b 0f 42 c1 33-c9 8b d0 ff 15 a0 1a 00 Leak.B.3........
三: 总结
在过往的dump分析中都是用户态程序的泄露,内核态模式堆的的泄露还是第一次分析,不是朋友提供的这次机会,真的就没缘分啦!在这次dump分析过程中,也让大家看到了 windbg 是多么的强大!
相关文章:

聊一聊 .NET高级调试 内核模式堆泄露
一:背景 1. 讲故事 前几天有位朋友找到我,说他的机器内存在不断的上涨,但在任务管理器中查不出是哪个进程吃的内存,特别奇怪,截图如下: 在我的分析旅程中都是用户态模式的内存泄漏,像上图中的…...

海外代理IP在游戏中有什么作用?
随着科技的飞速发展,手机和电脑等电子产品已成为互联网连接万物的重要工具,深度融入我们的日常生活,我们借助互联网完成工作、休闲和购物等任务,以求提升生活质量。 不仅如此,网络游戏也是人们心中最爱,它…...

高防ip适合防御网站和游戏类的攻击吗?
作为站长,要学会并承受得住网站外来攻击的压力,尤其是所属为 DDoS 攻击高发行业的网站类业务及游戏行业,是很容易被竞争对手或者一些伪黑客爱好者盯上的。 加上,有些站长并没有提前了解,就盲目进军了这两个行业&…...

HTML5和JS实现明媚月色效果
HTML5和JS实现明媚月色效果 先给出效果图: 源码如下: <!DOCTYPE html> <html> <head><title>明媚月光效果</title><style>body {margin: 0;overflow: hidden;background-color: #000; /* 添加一个深色背景以便看到…...
Django5+DRF序列化
概述 本教程将介绍如何创建一个简单的粘贴板代码高亮 Web API。在此过程中,它将介绍构成 REST 框架的各种组件,让你全面了解所有组件是如何组合在一起的。 本教程相当深入,因此在开始学习之前,你可能需要先吃一块饼干࿰…...
什么是编译程序和解释程序
一、编译程序 1、编译器接收源代码作为输入,它会一次性地将整个源代码程序转换成目标代码(通常是机器语言或汇编语言),这个过程包括词法分析、语法分析、语义分析、优化以及最终的目标代码生成。2、编译后的目标代码是一个独立的…...

文档审阅批注的合并和对比
#创作灵感# 最近在改论文,Feedback返回的时候,把之前的批注都删了,这就增加了工作量,看起来不方便,所以就需要将删掉的批注全部复原。 那在原来的文档重新在修改一遍,工作量还是很大的,所以这里…...

广义零样本学习综述的笔记
1 Title A Review of Generalized Zero-Shot Learning Methods(Farhad Pourpanah; Moloud Abdar; Yuxuan Luo; Xinlei Zhou; Ran Wang; Chee Peng Lim)【IEEE Transactions on Pattern Analysis and Machine Intelligence 2022】 2 conclusion Generali…...

java每日一题——输出9x9乘法表(答案及编程思路)
前言: 打好基础,daydayup! 题目:输出下图9x9乘法表 编程思路:java只能输出行,不能输出列,所以考虑好每一行输出的内容即可 public class demo {public static void main(String[] args) {for (int i 1; i…...
Android 车联网——基础简介(一)
传统的车载功能单一,无太多娱乐性,而随着智能化时代的发展,车载系统也被赋予了在系统中预装 Android 应用的能力,基于Android平台的车载信息娱乐系统 —— Android AutoMotive 应运而生。 一、AutoMotive简介 Android Automotive OS 车载操作系统,是一个基本 Android 平台…...
自动驾驶货车编队行驶系统功能规范
货车编队行驶功能规范 Truck Platooning Functional Specification 目录 1 概述... 7 1.1 目的... 7 1.2 范围... 7 1.3 术语及缩写... 7 1.4 参考法规标准... 8 2 功能规范... 9 2.1 功能描述... 9 2.1.1 功能用途…...

javafx
JavaFX JavaFX简介 JavaFX是一个用于创建富客户端应用程序的图形用户界面(GUI)框架。它是Java平台的一部分,从Java 8开始成为Java的标准库。 JavaFX提供了丰富的图形和多媒体功能,使开发人员能够创建具有吸引力和交互性的应用程…...
玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 编译构建及此过程中的踩坑填坑(3)
接前一篇文章:玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 编译构建及此过程中的踩坑填坑(2) 上一篇文章结束时在等待提示的各依赖包下载安装后的编译结果,但是很遗憾,编译并没有最终完成,既未成功也没有失…...
SQL ORDER BY 关键字
ORDER BY 关键字用于对结果集进行排序。 SQL ORDER BY 关键字 ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。 ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 DESC 关键字。 SQL ORDER BY 语法 SELECT …...

多线程-生产者消费者模型
一、基本信息 1、场景介绍:厨师和吃货的例子,吃货吃桌子上的面条,吃完让厨师做,厨师做完面条放桌子上,让吃货吃,厨师如果发现桌子上有面条,就不做,吃货发现桌子上没有面条就不吃。 …...
解压命令之一 gzip
文章目录 解压命令之一 gzip更多信息 解压命令之一 gzip gzip用于对后缀为gz文件进行解压: $ gzip -d data.gz这个命令将解压examplefile.gz,并且在当前目录下生成一个名为data的解压后的文件。 但特别需要留意的是,这个操作会删除源文件&…...

力扣:438. 找到字符串中所有字母异位词 题解
Problem: 438. 找到字符串中所有字母异位词 438. 找到字符串中所有字母异位词 预备知识解题思路复杂度Code其它细节推荐博客或题目博客题目滑动窗口哈希表 预备知识 此题用到了双指针算法中的滑动窗口思想,以及哈希表的运用。c中是unordered_map。如果对此不了解的u…...
QT 高DPI解决方案
一、根据DPI实现动态调整控件大小(三种方式) 1、QT支持高DPI(针对整个进程中所有的UI) // main函数中 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling)tips:(1)如果不想全局设置&am…...
SLB、DMZ、Nginx、Ingress、Gateway、Kibana和Grafana
SLB、DMZ、Nginx、Ingress、Gateway、Kibana和Grafana虽然有一些相似之处,但是它们的功能和适用场景还是有所不同。 SLB主要用于将大流量的请求分配到多个服务器上进行处理,从而提高系统的可伸缩性和可靠性。它适用于需要处理大流量的应用,如…...

【已解决】Invalid bound statement (not found)
报错讯息 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.casey.mapper.SysRoleMapper.getUserRoleCode at org.apache.ibatis.binding.MapperMethod S q l C o m m a n d . < i n i t > ( M a p p e r M e t h o d . j a v a :…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...