使用Windbg静态分析dump文件(实战经验总结)
来源:http://www.tudoupe.com时间:2022-07-02
目录
1、概述
2.静态分析垃圾档案的一般步骤
3、分析实例说明
用Windbg打开垃圾文件进行初始分析
找到pdb文件,将它设置为windbg,并查看全功能调用堆栈
6.设置C++源路径到Windowsbg,Windowsbg将自动跳到源行数
有时需要在函数调用堆中查看函数的局部变量或C++类对象中的变量值
有时我们需要使用IDA来打开一个二进制文件来查看编译代码的上下文
8.介绍IDA工具
8.使用IDA打开二进制文件
8.3,找到编译命令的位置,当有pdb文件时,在IDA中出现异常
8.4,在没有pdb文件时在IDA中出现的编译命令的位置
8.阅读编译的代码上下文
9、最后
C++软件例外从初级课程到高级课程的列表(栏目条目列表,欢迎订阅,持续更新..)
https://blog.csdn.net/chenlycly/article/details/125529931
在分析C++软件异常的日常工作中,我们通常使用Windowsbg静态分析垃圾文件来检测软件异常。今天我们将讨论如何使用Windowsbg静态分析垃圾文件作为参考。

1、概述
大多数软件都内置例外捕获模块,当软件崩溃时,相关的通知框会显示出来。例如,当WeChat的PC版本崩溃时,其内置例外捕获模块会捕获并生成日志和垃圾文件,并显示下列错误报告通知框:

提示框的底部将自动显示与崩溃有关的文件,最后一个是我们要讨论的垃圾档案。点击OK将发送这些文件到Tencent的远程服务器。Tencent的后台职员将收到通知,然后下载垃圾文件到服务器并对其进行分析。
某些软件可能不能将 crash log 上传到服务器上。当它捕获异常时,垃圾文件将自动保存到指定路径上,然后, 可以从路径中提取相应的垃圾文件.如果客户端的机器崩溃,可以和客户联系,让客户端帮助从相应的路径中删除文件.
这里是如何使用Windbg静态分析垃圾文件在获取垃圾文件后。
2.静态分析垃圾档案的一般步骤
用Windbg打开垃圾文件,首先使用. ecxr命令将转换为异常的上下文,然后根据成功切换后显示的例外类型(例外代码值的意义,例如,0xC005是AccessViolation内存访问侵犯的值(英语:AccessViolation memory access violation),是编译失败的命令(英语:Compiled command)和相应的注册表的值。通过查看编译指令和注册表的值,可以 初步 确定 目前 的 情况 。例如,C++类空指针,内存访问侵犯。

接着,使用kn/kv/kp查看函数调用堆栈,看看被调用函数触发的异常。调用堆显示函数的模块信息,一般来说,我们需要获取这些模块的pdb文件,指定的函数名称和行数将在装载pdb文件后显示在函数堆栈中。我们需要使用 lm命令查看这些模块的时间标记,然后为这些模块找到相应的pdb文件,然后设置pdb文件的路径为windbg。
然后,根据函数调用堆栈中显示的函数名称和行数,通过查看源代码来分析异常的原因.有时为了澄清异常的性质,我们还需要使用IDA来查看相关二进制文件的编译代码,请看编译指令的上下文,其中出现异常,对照着C++源码,让我们看看为什么编译指令是异常的。
3、分析实例说明
为了使我们更容易解释,我们特别创建了一个基于MFC对话框的exec程序项目,使用VisualStudio。对话框包含一个名为“按钮”的按钮,如下面所示:

为了响应这个按钮,我们添加了触发崩溃的测试代码,故意导致程序崩溃,然后在它崩溃时测试并获取垃圾文件。
具体测试代码如下:
SHELLEXECUTEINFO代码中使用的结构定义如下:
在测试代码中定义了SHELLEXECUTEINFO结构指针pShExeInfo,并初始化为 NULL,然后没有有效的结构对象地址被分配到指针上,然后使用pShExeInfo访问结构的cbSize成员内存,因为pShExeInfo中的值是零,因此结构cbSize成员的内存地址是结构对象的初始地址。因为结构对象地址是 NULL,cbSize成员位于结构的顶部,因此cbSize成员是结构对象的第一个地址,就是NULL,所以除了访问64KB小地址内存块,引发内存访问违例,使程序崩溃和滑翔.
至于如何在程序中设置异常捕获模块来捕获异常,自动生成垃圾文件,你可以尝试使用谷歌的开源CrashRpt库,我们的产品已经可用,如何取得具体尚未研究,如果你需要的话,你可以在互联网上搜索。
用Windbg打开垃圾文件进行初始分析
使用Windowsbg打开垃圾文件(直接拖到Windowsbg)并输入它。 ecxr命令,将更改到异常的上下文,允许异常类型发生,异常崩溃发生时的编译,以及各种注册表的值。
首先,我们研究了出现的异常类型,例如AccessViolation内存访问侵犯、StackOverflow线程堆栈的堆栈溢出,因此我们对异常的初步了解如下:

然后,看看发生异常的指令,看看指令的组成,以及在事故发生时的各个注册表的值,这可能对异常的原因作出初步估计。 如果命令访问一个非常小的地址或一个大的地址,它会触发记忆访问侵犯。
1)访问64KB小地址内存区,触发访问侵犯
在Windows系统中,64KB以内的内存地址被禁止访问,如果一个程序访问这个范围内的内存,它触发了内存访问侵犯,系统迫使进程终止。
2)访问了内核状态的大地址存储区,触发了访问漏洞
对于32位程序,系统将4GB的虚拟内存分配给进程,一般来说,用户状态和内核状态占每个状态的一半,即各占2GB,我们写的代码基本上在用户模式中运行,用户状态代码不能访问内核状态内存地址(内核地址由系统内核模块使用),如果在崩溃指令中访问一个大的内存地址,地址范围超过用户模式 0-2GB,存储地址大于0x800,则会触发内存违例,因为用户状态代码禁止访问内核状态内存地址。
如果编译命令使用ecx注册表来计算地址,访问计算的内存地址,如果您访问一个小存储地址, ecx注册表为0,因此,这次撞击可能是由空的指针触发的。在C++中,当调用C++类成员函数时,C++对象地址通过 theecx注册表传递,因此,当通过C++类对象调用错误函数(调用错误函数时的二级地址)和通过C++对象访问对象中的数据成员时,它将在 ecx 登记册上使用.
上面故意添加的测试代码会在运行后造成故障并生成垃圾文件。 让我们分析这个垃圾文件。

首先,这是 Access Violation缓存访问侵犯的一个例外。其次,从这个编译指令的崩溃开始,访问小地址0x00地址,这是访问不到64KB的小型地址内存区域,禁止访问该区域的地址,因此, memory access violation 被触发。从编译的指令和注册表的值,没有明显的迹象。
然后我们输入了k命令,打印出函数调用堆栈。函数调用堆栈从下到上看,上行是最后调用函数,它也是编译指令崩溃的函数。从函数调用堆栈的最后帧调用函数,程序崩溃发生在TestDlg文件模块中,不是其他DLL模块。显示的函数地址是测试Dlg文件模块的初始地址,为什么我不能在模块中看到特定的函数名称?这是因为Windbg无法找到与TestDlg有关的pdb文件,pdb文件包含相应的二进制文件中函数名称和变量的信息,将Windbg载入pdb文件以显示完整的函数名称.
为了查看函数调用堆栈命令,除了k之外,还有kv和kp命令,kv还可以看到在函数调用堆栈中调用函数时传递的参数:
我们需要取得pdb编码库文件以寻找特定的函数名称和行数,以便我们能够找到直接线索。
找到pdb文件,将它设置为windbg,并查看全功能调用堆栈
如何找到与TestDlg文件相对应的dpb文件?我们可以通过查看TestDlg文件的时间标记来找到该文件的编译时间,通过编译时间找到相应的pdb文件.在Windbg中,输入 lm vm TestDlg*命令,您可以查看TestDlg文件的详细信息,包含该文件的时标是:(使用当前lm命令中的m-符合参数,因此TestDlg的后面是*)

您可以看到,该文件于2022年6月25日8:26:23生成,并且您可以在相应的时间找到pdb文件。
一般来说,在公司正式项目中,软件版本通过一个自动软件编译系统自动编译,软件安装包和相关模块pdb文件存储在文件服务器上,如下所示:
因此我们可以根据模块的编译时间找到pdb文件的相应的版本。
我们找到了相应的pdb文件TestDlg.pdb,设置路径到Windowsbg中的位置。点击Windbg菜单栏中的File->Symbol File Path...,打开窗口设置pdb文件路径,插入pdb文件的路径,如下所示:

点击OK按钮之前,最好选择“重载”选项,然后Windowsbg将自动下载pdb文件。但有时候选择是正确的,它似乎没有自动加载.我们需要使用它。 重载/f TestDlg命令迫使Windowsbg重载pdb文件(该命令必须包含包含文件末尾的文件的完整名称)。
安装完毕后,我们可以再次运行 lm vm TestDlg*命令,查看pdb文件是否已加载:

如果已上传,上传的pdb文件的完整路径将显示在图表的顶部,如上面所示。
在将相应的pdb文件载入TestDlg文件后,我们可以再次执行k命令,以包含具体函数名称和代码行数信息,如下:

我们可以看到具体的函数名称CTestDlgDlg::OnBnClickedButton1和相应的代码行 312。 通过这些信息,我们可以在源代码中找到相应的位置,如下面所示:

通过访问空指针生成的异常。 当然,上面的代码是有意编写的来构造一个异常,详细说明如何使用Windowsbg来动态调试跟踪。
6.设置C++源路径到Windowsbg,Windowsbg将自动跳到源行数
为了方便查看,我们可以在Windowsbg中直接设置C++源路径,因此,Windowsbg将自动跳到相应的源位置。点击Windbg菜单栏的File->Source File Path...,设置源路径:

然后Windowsbg将自动跳到相应的函数和行数:

然后单击在函数调用堆中的每个行前面的数字过链接,您可以自动切换到相应的功能。上述图中的函数调用堆中的许多模块都在系统库中,例如mfc100u、User32等,这些库是系统库,是没有源码的。我们可以点击下面的第23个链接,它在我们的应用程序的模块中,将自动跳到相应的代码,如下:

有时需要在函数调用堆中查看函数的局部变量或C++类对象中的变量值
有时,我们通过查看变量的价值来找出问题的线索,例如一个平均值0的变量或一个大的异常值。
您可以查看该函数中的局部变量值,或该函数所在的类对象中的变量值,该指针指向该类对象的变量值。 查看我们想要寻找的函数,请按函数调用堆栈的每个行前面的数值过链接,如下面所示:

我们看到局部变量pShExeInfo的值:
我们可以点击这个对象的连结:

您可以在C++类对象中查看与当前函数相对应的成员变量值,如下:

但是有时候很难看到变量的值,因为当前由异常捕获模块自动生成的垃圾文件通常是一个小型垃圾文件,这个文件大约有几MB,不可能包含所有变量的值。那么,看一下 minidump文件中的变量值,要看运气的,有时能查看到,有时是看不到的。这是垃圾档案的分类,它主要分为小垃圾文件和完整的垃圾文件。
我们将将windbg添加到使用的过程中。 由 dump命令生成的垃圾文件是一个完整的垃圾文件,包含了全部垃圾文件中的信息,可以与所有变量的信息一起查看。 此外,垃圾文件可以通过任务管理器输出:

它也是一个完整的垃圾文件。所有的垃圾文件因为它们包含所有信息,所以会比较大,会达到数百MB,甚至上GB的大小。但是如果安装在程序中异常捕获模块CrashReport生成的垃圾文件不是完整的垃圾文件,这是一个小型垃圾档案,大约几MB,因为异常捕获模块在异常之后被捕获,将自动输出垃圾文件,保存到磁盘上,如果所有的垃圾文件有大量的容量,它消耗了大量的用户磁盘空间,我们设法生成一个小型垃圾文件.
在异常捕获模块中,我们通过调用系统API函数 MiniDumpWriteDump,通过设置不同的函数调用参数来控制 mini dump文件的生成。
有时我们需要使用IDA来打开一个二进制文件来查看编译代码的上下文
有时,通过调用堆栈中的函数和行,很难确定 crash 发生的原因,然后我们需要回到源代码,我们需要查看在编译命令中出现异常 crash 的上下文。
编写指令最直接反映问题的性质,通过阅读汇编代码,你可以找出造成事故的原因。通常我们使用它。 当 ecxr命令转换为异常的编译命令时,我们可以直接在文章的上下文编写指令,点击菜单栏的View->Disassembly,你可以打开显示编译代码的页面,如下所示:

但对于那些不熟悉编译代码的人来说,直接查看Windowsbg中的编译代码是非常困难的,而且我们很有可能不会理解它。
一般来说,您需要使用IDA工具打开二进制文件来查看编译的代码,当分析汇编时,IDA将对汇编代码添加一些注释,特别是当有pdb编码器文件时,会添加更多的注释,通过这些注释,我们可以对付C++源代码,你可能可以理解该汇编的上下文。如果你能找到pdb编码库文件,然后您需要将pdb文件置于目标二进制文件的目录中,当IDA打开一个二进制文件时,它会自动装载pdb文件。
8.介绍IDA工具

IDA是一个由比利时公司Hex-Rays开发的交互性静态反向编译器。它可以直接重新组合二进制文件的编译代码,它是软件反向和安全分析领域最好的和最强大的静态反向编译器。它已成为许多软件安全分析员不可或缺的工具!它支持多个平台,如Windows和Linux,它支持数十个CPU指令集,如Intel X84、X64、ARM和MIPS。
在实际工作中,我们通常使用反压缩工具IDA来打开二进制文件,在二进制文件中查看编译代码。IDA支持在Windows.binary文件下打开,例如 dll,也可以在Linux下打开"Bin"这个二进制文件。
8.使用IDA打开二进制文件
在IDA安装完成后,双击启动程序,下列提示框就会出现:

单击“新”创建新对象。 下一步显示您要打开的文件:

你可以找到目标文件的路径,然后打开目标文件。 也可以单击“取消”并直接拖到IDA。

在Windows库中,你可以选择PE模式。 接下来,一个提示会显示是否要下载pdb文件:

如前面所述,必须将pdb文件置于目标二进制文件的同级目录中,以便IDA在打开二进制文件时搜索相应的pdb文件并自动重载pdb文件。
打开后的效果如下:

默认首先是格拉普格视图图关系视图,您需要右击视图区域,在弹出文本菜单中单击文本视图菜单项,然后切换到文本视图文本视图,这样您就可以看到具体的编译代码:

8.3,找到编译命令的位置,当有pdb文件时,在IDA中出现异常
我们需要在IDA中找到相应的位置,然后查看目标位置的编译命令的上下文。 如果目标二进制文件有一个pdb,那么在IDA中更容易找到异常编译命令的位置。
首先在Windowsbg显示的函数调用堆中找到CTestDlgDlg::OnBnClickedButton1的函数名称,该堆的编译命令的位置如下:

然后到IDA中,点击菜单栏的Jump->Jumptofunction...,在打开的函数列表窗口中,点击下方的Search按钮,在搜索框中输入函数名后搜索:

在列表中找到函数,然后双击转换到该函数的组合代码:

这显示了函数的代码字段地址,然后添加在Windowsbg中显示的变换值:

即:
发生故障的编译指令是当前二进制系统中的地址,因为编译指令可以通过拖拉当前函数下鼠标找到,这样可以找到发生异常的编译指令。
事实上,还有一个快速的操作,在计算生成的编译命令的地址后,按短cut键G,在弹出窗口中输入地址0x00401A62,然后可以直接进入生成的命令的位置,如下:

8.4,在没有pdb文件时在IDA中出现的编译命令的位置
在没有目标二进制文件的pdb文件中,在IDA中找到异常编译命令的位置相对困难。
编写异常指令的地址,是程序实际运行时代码节地址,在Windowsbg中必须计算条目编译指令的地址,与模块所在的初始地址的偏移值有关,然后在IDA中添加模块的默认装载地址,您可以在IDA中获取当前编译指令的静态地址,然后直接go过去,你可以看到产生异常的编译指令的上下文在这个例子中,异常发生编译命令的地址为0x00401a62,如下:(异常发生编译命令的这个行前面的地址是当前编译命令的地址)

从函数调用堆栈中,当前该异常编译命令发生的函数是:
所以这个命令属于TestDlg模块,所以使用 lm命令查看TestDlg模块的初始地址:

测试Dlg模块的地址实际上是0x00400(这是系统将测试Dlg模块装入进程空间中的初始地址,代码段地址 ),因此,与TestDlg模块的出发地址有关的例外的编译指令如下:
然后进入打开TestDlg二进制文件的IDA,查看TestDlg模块的默认上传地址:(您可以通过滚动滚轮到顶部,注意这是默认预装地址,而不是上传后实际地址)

因此,基于先前计算的偏差,加上TestDlg模块的默认装载地址,异常指令的发生位于IDA打开的静态文件中:
然后按IDA上的G短cut,然后到0x00401a62地址,在那里你会找到编译命令,在那里出现异常:

在IDA中找到异常发生的编译命令可以在附近的编译代码上下文中查看的位置。
8.阅读编译的代码上下文
当我们阅读编译代码的上下文时,一般是用C++源代码进行的,然后依靠编译代码上下文中的注释,找出编译代码和C++源代码之间的相关性。在阅读汇编代码时,要了解一些通用的编译指令和使用通用的注册表(例如用于存储函数的EAX返回值),ECX用于传输C++对象地址),熟悉参数堆栈、堆栈分布和调用函数时参数处理,了解编译的内存拷贝代码的实现以及调用虚构函数的二次地址过程。将编译的代码在发生异常的编译指令的上下文中切断。
有许多编译指令,我们只需要知道一些常见的编译指令,如果你遇到一些不熟悉的编译指令,就只要搜索。分析C++软件异常所需的编译知识参见前面的文章:
理解C++软件异常分析的编译知识摘要
https://blog.csdn.net/chenlycly/article/details/124758670此外,应该指出,编译器将优化当前的C++源代码,部分C++源代码可能被删除,而C++源代码可能与编译代码不完全兼容,但这并不影响编译代码上下文的读取。
如何使用IDA工具的详细说明 ,你可以看到以前的文章:
IDA反编译工具的使用说明
https://blog.csdn.net/chenlycly/article/details/120635120
9、最后
本文通过实例介绍Windowsbg对垃圾文件的静态分析的全过程。
如Windbg和IDA等工具的下载链接如下:
链接: https://pan.Baidu.com/s/1ID6_0RSYKbiy_tzfYDX3Ew
提取码:tn6i
相关新闻
- 2022-08-04 WPF的由来
- 2022-08-04 Win11勒索软件防护怎么打开?Win11安
- 2022-08-04 Windows系统jdk的配置
- 2022-08-04 Windows10 OneNote怎么重新登录?如何重
- 2022-08-04 超好用的 Windows 效率工具推荐
- 2022-08-04 Windows如何在CMD或PowerShell中配置代理
- 2022-08-04 powershell和cmd对比
- 2022-08-04 【QT】Windows下QT下载安装
- 2022-08-04 windows下 C++ 实现类属性的get和set方
- 2022-08-04 Win11快速助手在哪里?Win11打开快速
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


