WinDbg. From A to Z! 笔记(一)

原文链接: WinDbg. From A to Z!

文章目录

  • 为什么使用WinDbg
  • 为什么通过本书学习
  • 底层原理简述
    • Windows的调试工具一览
      • dbghelp.dll -- Windows 调试助手
      • dbgeng.dll -- 调试引擎接口
    • 调试符号 (Debug Symbols)
      • 有哪些调试信息
      • 生成调试信息
      • 匹配调试信息
      • 调用堆栈
    • 侵入式与非侵入式
    • 异常机制
      • 异常分发
      • AeDebug? Postmortem Debugging!
  • 使用WinDbg
    • WinDbg 命令
    • 主要的扩展插件
    • WinDbg 使用符号
    • WinDbg 使用源代码
    • Windows 上的进程与线程 (Processes and Threads on Windows NT)
      • PEB 与 TEB
        • 示例 -- 输出完整的PEB
      • 用于显示进程信息和模块信息的WinDbg命令
        • 示例 -- 模块信息
      • 用于显示线程信息的WinDbg命令
        • 示例 -- 线程相关
    • WinDbg的窗口与菜单
    • 调试器标记语言 (Debugger Markup Language, DML)
    • 内存 -- 栈详情
      • 示例 -- 线程的栈大小
    • 内存 -- 栈增长
    • 查看调用栈信息的WinDbg命令
    • 处理内存的WinDbg命令
      • 示例 -- 进程内存信息
    • 查看堆信息的WinDbg 命令
      • Heap Structs
      • 得到HeapAlloc的调用者
        • 示例 -- 得到HeapAlloc的调用者
      • HeapCreate的调用者
        • 示例 -- 得到HeapCreate的调用者
    • 排查堆内存泄漏
      • 示例 -- 排查堆内存泄漏

为什么使用WinDbg

  • 微软官方开发的调试工具
  • 比visual studio 有更强大的程序调试能力
  • 可以用dll来进行扩展
  • WinDbg的调试引擎是Windows操作系统的一部分

为什么通过本书学习

  • WinDbg的官方文档对新手不友好
  • 没有良好的文档和示例,以致于WinDbg的学习曲线很陡峭,从而很多同鞋安装完WinDbg后就放到硬盘里吃灰。
  • “WinDbg. From A to Z”可以帮助同鞋们快速上手,读完本书后,你就会觉得自己又行了。

底层原理简述

Windows的调试工具一览

在这里插入图片描述

dbghelp.dll – Windows 调试助手

  • 文档在MSDN
  • 从Windows2000开始就被包含在系统中
  • 被以下程序依赖
    • Process Dumping (MiniDumpWriteDump , DbgHelpCreateUSerDump, …)
    • Obtaining Stack Traces (StackWalk64, …)
    • Symbol Handling (SymFromAddr, Sym* …)
    • Obtaining info about executable images (ImageNtHeader, FindDebugInfoFile, …)

dbgeng.dll – 调试引擎接口

  • WinDbg的文档中有说明
  • 从Windows XP开始被包含在系统中
  • 实现了接口如: IDebugAdvanced, IDebugControl, IDebugSystemObjects, …
  • 调试器的所有调试功能都来自于dbgeng.dll

Fact 1: WinDbg is really just a shell on top of a debugging engine.
Fact 2: You can write new standalone tools on top of this engine.

调试符号 (Debug Symbols)

  • 可执行程序就是一堆机器码
  • 高度符号有助于:
    • 机器码映射到源代码
    • 分析应用程序的内部布局与数据
  • Program DataBase -> PDB 文件
    • 与linux系统不一样,调试信息与可执行文件分开存储
    • 需要特殊的API来使用它:DbgHelp.dll和MsDiaXY.dll

有哪些调试信息

  • 公开的函数与变量
  • FPO 即用来检索堆栈的信息
  • 非公开的函数,局部变量,函数参数
  • 源码文件与行数信息
  • 类型信息

生成调试信息

Compiler options: /Z7, /Zi, /ZI
Linker options: /debug, /pdb, /pdbstripped

匹配调试信息

  • 在可执行文件和PDB文件中的有签名信息
  • 调试器会匹配签名信息
  • 搜索pdb文件的算法步骤大概如下:
    * 先会尝试指定的文件夹
    * 再尝试PE文件中记录的路径
    * 最后尝试从环境变量 _NT_SYMBOL_PATH 和_NT_ALT_SYMBOL_PATH中搜索

调用堆栈

在这里插入图片描述

侵入式与非侵入式

  • 侵入式附加

    • 会调用DebugActiveProcess 接口
    • 会创造一个break-in thread ,就是可以中断进程
    • 在WindowsXP之前,调试器分离进程或结束调试时,进程会结束
    • 同一时间只能有一个侵入式附加来调试同一个进程
  • 非侵入式调试

    • 会调用 OpenProcess 接口
    • 不会创建一个break-in thread
    • 无法作为一个调试器附加到进程
    • 目标进程的所有线程都冻结
    • 可以改变与测试内存
    • 不能设置断点
    • 无法单步调试程序
    • 可以在一个进程上附加几个非侵入性调试器

异常机制

  • 是操作系统的机制而不是编程语言的特性
  • 可以通过语言扩展来使用异常机制,如VC++的__try __except 语句
  • 不要在需要高效执行的部分使用try catch 语句,因为比较低效。

异常分发

  1. 系统首先尝试通知进程的调试器(如果有的话)
  2. 如果进程未被调试,或者关联的调试器未处理异常
    (Winge->gN==Go with Exception Not Handled),系统尝试定位基于帧的异常处理程序
  3. 如果找不到基于帧的处理程序,或者没有基于帧的处理器处理异常,UnhandledException Filter会再次尝试通知进程的调试器。这被称为第二次机会或最后一次机会通知。
  4. 如果进程未被调试,或者关联的调试器未处理异常,则将启动AeDebug中指定的Postmortem调试器。
    在这里插入图片描述

AeDebug? Postmortem Debugging!

在这里插入图片描述
注册表项 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

使用WinDbg

WinDbg 命令

  • 常规命令

    • 用于调试进程
    • 如: k, lm, g
  • 元命令(点命令)

    • 通常用于控制调试器的行为
    • 如: .cls, .sympath, .lastevent, .detach
  • 扩展命令

    • dll扩展中的函数
    • 通常用于丰富调试器
    • 可以自行开发扩展插件
    • 如: !address, !analyze

主要的扩展插件

在这里插入图片描述

WinDbg 使用符号

  • 必须设置 _NT_SYMBOL_PATH 环境变量
    如MS symbols:
    _NT_SYMBOL_PATH=srv*C:\Symbols\MsSymbols*http://msdl.microsoft.com/download/symbols;
    如此设置,WinDbg会自动下载需要的符号
    可以设置缓存目录
    cache*E:\MyTemp\SymbolCache;SRV*https://msdl.microsoft.com/download/symbols

  • 在WinDbg 界面可以如此设置
    在这里插入图片描述

  • 常用的命令

在这里插入图片描述

WinDbg 使用源代码

  • 可以通过设置环境变量 _NT_SOURCE_PATH
  • 在WinDbg界面
    在这里插入图片描述
  • 常用的命令
    在这里插入图片描述

Windows 上的进程与线程 (Processes and Threads on Windows NT)

先解释一下NT是什么意思
NT 就是New Technology, 是1993年首次发布的windows内核架构,之前使用的是9x内核架构,从windows xp开始Windows统一到NT内核上,9x被弃用。因为历史原因,许多Windows的库会有nt前缀。

  • 每个Windows进程都由内核模式下的执行进程块(EPROCESS)表示
  • EPROCESS指向了许多相关的数据结构;例如,每个进程都有一个或多个由执行线程块(ETHREAD)表示的线程
  • EPROCESS指向进程地址空间中的进程环境块(PEB)
  • ETHREAD指向进程地址空间中的线程环境块(TEB)

PEB 与 TEB

  • PEB (Process Environment Block)

    • 包含基础信息如:基址,版本号,模块列表
    • 进程堆信息
    • 环境变量
    • 命令行参数
    • DLL搜索路径
    • 在WinDbg 使用命令显示: !peb , dt nt!_PEB
  • TEB (Thread Environment Block)

    • 线程栈信息如: 栈基址和栈长度上限
    • TLS(Thread Local Storage)数组
    • 在WinDbg上的输出命令: !teb, dt nt!_TEB

事实上WinDbg的诸多命令如: lm, !dlls, !imgreloc, !tls, !gle 等,都是从数据结构PEB与TEB中得到的。

示例 – 输出完整的PEB

在这里插入图片描述

命令组解析

  • dt : Data Type , 用于显示数据结构(如结构体、联合体)的定义及其在内存中的值。
  • nt!_PEB
    • nt! 表示符号属于 ​NT 内核模块​(通常是 ntoskrnl.exe 或 ntdll.dll)。
    • _PEB 是进程环境块的结构体名称。PEB 包含进程的全局信息(如加载的模块、命令行参数、堆信息等)。
  • -r: 递归选项,表示递归展开嵌套的结构体。默认递归一层(相当于 -r1),若需更多层级可指定(如 -r2)。此选项会展开指针指向的子结构。
  • @$peb : 伪寄存器 $peb,存储当前进程的 PEB 地址。@ 符号用于访问伪寄存器。

功能:

  • 显示 PEB 的完整结构,解析 @$peb 地址处的内存,按 _PEB 结构体的定义格式化输出,包括所有成员的值(如 Ldr, ProcessParameters 等)。

  • 递归展开嵌套成员, 如果成员是指向其他结构体的指针(如 PEB_LDR_DATA* Ldr),-r 会进一步展开这些子结构体的内容。

    用于显示进程信息和模块信息的WinDbg命令

    在这里插入图片描述

示例 – 模块信息

在这里插入图片描述

用于显示线程信息的WinDbg命令

在这里插入图片描述

示例 – 线程相关

在这里插入图片描述

WinDbg的窗口与菜单

  • WinDbg的窗口是可以停靠与悬浮的
  • 每个WinDbg的子窗口有其自己的功能菜单

调试器标记语言 (Debugger Markup Language, DML)

  • DML允许调试器输出以标签的形式包含指令和额外的非显示信息
  • 调试器用户界面解析出额外信息以提供新行为
  • DML主要旨在解决以下问题:
    • 相关信息的链接
    • 调试器和扩展功能的可发现性
    • 增强调试器和扩展的输出
  • DML是在调试工具6.6.0.7版本中引入的

内存 – 栈详情

  • 每一个新的线程都会有一个栈空间,是由已经提交的和已经预约的内存组成
  • 默认情况下每个线程有1MB的预约空间和1个分页的已经提交空间

不明白己预约的内存和己提交的内存是什么意思的同学自行搜索Windows中 VirtualAlloc的资料。

示例 – 线程的栈大小

在这里插入图片描述

内存 – 栈增长

  • ESP寄存器指向线程的当前堆栈位置。
  • 如果程序试图访问保护页中的地址,系统会引发 _UNGUARD-PAGE_VIOLATION(0x80000001)异常。保护页面为内存页面访问提供one-shot警报。
  • 如果堆栈一直增长到保留内存的末尾,则会引发STATUS_STACK_OVERFLOW异常。

查看调用栈信息的WinDbg命令

在这里插入图片描述

处理内存的WinDbg命令

在这里插入图片描述

示例 – 进程内存信息

在这里插入图片描述

查看堆信息的WinDbg 命令

在这里插入图片描述

Heap Structs

如果您的应用程序禁用了页面堆,则应用以下结构。
请注意,默认情况下页面堆是禁用的。

  • _HEAP

    • 在ntdll.dll 中定义 : dt ntdll!_HEAP
    • 每成功调用一次HeapCreate就会产生一个_HEAP
    • 可以使用!heap -p -all来得到进程中所有_HEAP 结构体的地址
  • _HEAP_ENTRY

    • 在ntdll.dll 中定义: dt ntdll!_HEAP_ENTRY
    • 每成功调用一次HeapAlloc就会产生一个_HEAP_ENTRY
    • 使用!heap -p -all来得到地址

如果为应用程序启用了页堆,则应用以下结构。
您可以使用全局标志(gflags.exe)启用页面堆。

  • _DPH_HEAP_ROOT

    • 在ntdll.dll 中定义: dt ntdll!_DPH_HEAP_ROOT
    • HeapCreate时产生
    • !heap -p -all查看
  • _DPH_HEAP_BLOCK

    • ntdll.dll 中定义
    • HeapAlloc产生
    • !heap -p a-all查看

得到HeapAlloc的调用者

  • 为您的应用程序启用堆栈跟踪和页面堆
    使用Global Flags, 在Windows SDK里面有
    在这里插入图片描述

  • 重启应用,WinDbg重新附加进程

  • WinDbg的命令序列:

    1. !heap -p -a <UserAddr>
    2. dt ntdll!_DPH_HEAP_BLOCK StackTrace<MyHeapBlockAddr>
    3. dds <StackTrace>
示例 – 得到HeapAlloc的调用者

在这里插入图片描述
先通过!heap -p -all来找到一个DPH_HEAP_BLOCK,这里得到些结构体的地址是 144e1f3c, UserAddr 是 144e7c00

在这里插入图片描述
然后直接查询栈跟踪StackTrace的地址。
在这里插入图片描述
打印出栈!

HeapCreate的调用者

与HeapAlloc同理

示例 – 得到HeapCreate的调用者

在这里插入图片描述
找到一个DPH_HEAP_ROOT
在这里插入图片描述
直接找到跟踪栈
在这里插入图片描述
打印跟踪栈,找到源码位置。

排查堆内存泄漏

  • !address –summary
    进程内存使用情况摘要。如果RegionUsageHeap或RegionUsagePageHeap不断增长,那么堆上可能会出现内存泄漏。继续执行以下步骤
  • 使用Global Flags 开启 stack traces 与 page heap
  • 重启应用,重连WinDbg

命令序列:
!heap –stat –h 0 : 将列出每个AllocSize的特定分配统计信息。对于每个AllocSize,都会列出以下内容:AllocSize、#blocks和TotalMem。
!heap –flt –s <size>
!heap -p -a <UserAddr>

示例 – 排查堆内存泄漏

先运行起来查看内存统计
在这里插入图片描述

再运行段时间后查看内存统计
在这里插入图片描述
对比前后内存在增长, 其中 heap @ 147d0000 从 0x2b 个 块长到 0x40 个块
在这里插入图片描述
打印出该堆的信息
抽取其中一个Busy allocations 的UserAddr
在这里插入图片描述
通过一系统命令找到源码进而分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41937.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axure RP 9.0教程: 基于动态面板的元件跟随来实现【音量滑块】

文章目录 引言I 音量滑块的实现步骤添加底层边框添加覆盖层基于覆盖层创建动态面板添加滑块按钮设置滑块拖动效果引言 音量滑块在播放器类APP应用场景相对较广,例如调节视频的亮度、声音等等。 I 音量滑块的实现步骤 添加底层边框 在画布中添加一个矩形框:500 x 32,圆…

Eclipse IDE for ModusToolbox™ 3.4环境通过JLINK调试CYT4BB

使用JLINK在Eclipse IDE for ModusToolbox™ 3.4环境下调试CYT4BB&#xff0c;配置是难点。总结一下在IDE中配置JLINK调试中遇到的坑&#xff0c;以及如何一步一步解决遇到的问题。 1. JFLASH能够正常下载程序 首先要保证通过JFLASH(我使用的J-Flash V7.88c版本)能够通过JLIN…

黑马点评项目

遇到问题&#xff1a; 登录流程 session->JWT->SpringSession->tokenRedis &#xff08;不需要改进为SpringSession&#xff0c;token更广泛&#xff0c;移动端或者前后端分离都可以用&#xff09; SpringSession配置为redis模式后&#xff0c;redis相当于分布式se…

wgcloud怎么实现服务器或者主机的远程关机、重启操作吗

可以&#xff0c;WGCLOUD的指令下发模块可以实现远程关机和重启 使用指令下发模块&#xff0c;重启主机&#xff0c;远程关机&#xff0c;重启agent程序- WGCLOUD

深度解析Spring Boot可执行JAR的构建与启动机制

一、Spring Boot应用打包架构演进 1.1 传统JAR包与Fat JAR对比 传统Java应用的JAR包在依赖管理上存在明显短板&#xff0c;依赖项需要单独配置classpath。Spring Boot创新的Fat JAR&#xff08;又称Uber JAR&#xff09;解决方案通过spring-boot-maven-plugin插件实现了"…

deepseek(2)——deepseek 关键技术

1 Multi-Head Latent Attention (MLA) MLA的核心在于通过低秩联合压缩来减少注意力键&#xff08;keys&#xff09;和值&#xff08;values&#xff09;在推理过程中的缓存&#xff0c;从而提高推理效率&#xff1a; c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKV​WDKVht​…

突破反爬困境:SDK架构设计,为什么选择独立服务模式(四)

声明 本文所讨论的内容及技术均纯属学术交流与技术研究目的&#xff0c;旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。 作者不支持亦不鼓励任何未经授…

自然语言处理,能否成为人工智能与人类语言完美交互的答案?

自然语言处理&#xff08;NLP&#xff09;作为人工智能关键领域&#xff0c;正深刻改变着人机交互模式。其发展历经从早期基于规则与统计&#xff0c;到如今借深度学习实现飞跃的历程。NLP 涵盖分词、词性标注、语义理解等多元基础任务&#xff0c;运用传统机器学习与前沿深度学…

蓝桥杯备考:八皇后问题

八皇后的意思是&#xff0c;每行只能有一个&#xff0c;每个对角线只能有一个&#xff0c;每一列只能有一个&#xff0c;我们可以dfs遍历每种情况&#xff0c;每行填一个&#xff0c;通过对角线和列的限制来进行剪枝 话不多说&#xff0c;我们来实现一下代码 #include <ios…

HDR(HDR10/ HLG),SDR

以下是HDR&#xff08;HDR10/HLG&#xff09;和SDR的详细解释&#xff1a; 1. SDR&#xff08;Standard Dynamic Range&#xff0c;标准动态范围&#xff09; • 定义&#xff1a;SDR是传统的动态范围标准&#xff0c;主要用于8位色深的视频显示&#xff0c;动态范围较窄&…

【MySQL】验证账户权限

在用户进行验证之后&#xff0c;MySQL将提出以下问题验证账户权限&#xff1a; 1.谁是当前用户&#xff1f; 2.该用户有何权限&#xff1f; 管理权限比如&#xff1a;shutdown、replication slave、load data infile。数据权限比如&#xff1a;select、insert、update、dele…

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍&#xff1a; DMA控制器可以生成单次传输或增量突发传输&#xff0c;传输的节拍数为4、8或16。 为了确保数据一致性&#xff0c;构成突发传输的每组传输都是不可分割的&#xff1a;AHB传输被锁定&#xff0c;AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…

GaussDB数据库表设计与性能优化实践

GaussDB分布式数据库表设计与性能优化实践 引言 在金融、电信、物联网等大数据场景下&#xff0c;GaussDB作为华为推出的高性能分布式数据库&#xff0c;凭借其创新的架构设计和智能优化能力&#xff0c;已成为企业核心业务系统的重要选择。本文深入探讨GaussDB分布式架构下的…

npm install 卡在创建项目:sill idealTree buildDeps

参考&#xff1a; https://blog.csdn.net/PengXing_Huang/article/details/136460133 或者再执行 npm install -g cnpm --registryhttps://registry.npm.taobao.org 或者换梯子

【MySQL】从零开始:掌握MySQL数据库的核心概念(五)

由于我的无知&#xff0c;我对生存方式只有一个非常普通的信条&#xff1a;不许后悔。 前言 这是我自己学习mysql数据库的第五篇博客总结。后期我会继续把mysql数据库学习笔记开源至博客上。 上一期笔记是关于mysql数据库的增删查改&#xff0c;没看的同学可以过去看看&#xf…

抖音矩阵系统源码开发与部署技巧!短视频矩阵源码搭建部署

在短视频蓬勃发展的时代&#xff0c;短视频矩阵已成为内容创作者和企业扩大影响力、提升传播效果的重要策略。而一个高效、易用的前端系统对于短视频矩阵的成功运营至关重要。本文将深入探讨短视频矩阵前端源码搭建的技术细节&#xff0c;为开发者提供全面的技术指导。 一、技…

ESP32S3 WIFI 实现TCP服务器和静态IP

一、 TCP服务器代码 代码由station_example_main的官方例程修改 /* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an &q…

物质与空:边界中的确定性,虚无中的无限可能——跨学科视角下的存在本质探析

一、哲学框架&#xff1a;二元性与超越性 1. 物质的边界性&#xff1a;有限世界的确定性法则 在人类认知的起点&#xff0c;物质以"非0即1"的绝对姿态显现。一块石头、一滴水、乃至微观粒子&#xff0c;都以明确的边界定义自身存在。这种确定性映射着&#xff1a; 亚…

linux常用指令(10)

那么我们就继续来学习linux指令的使用,来了解搜索查找类的相关指令,话不多说,来看. 搜索查找类 1.find指令 find将从指定目录向下遍历其各个子目录,将满足条件的条件或目录显示在终端 基本语法 find[搜索范围][项项] 选项说明 -name<查询方式> 按照指定的文件名查找…

AWTK-WEB 快速入门(6) - JS WebSocket 应用程序

WebSocket 可以实现双向通信&#xff0c;适合实时通信场景。本文介绍一下使用 Javacript 语言开发 AWTK-WEB 应用程序&#xff0c;并用 WebSocket 与服务器通讯。 用 AWTK Designer 新建一个应用程序 先安装 AWTK Designer&#xff1a; https://awtk.zlg.cn/web/index.html …