《格蠹汇编》调试笔记

之前也就是把Windbg做为一个调试所写驱动的调试器。只进行源码级的调试,运用的比较浅显。函数

最近研读张银奎老师的《软件调试》获益良多,恰好与之配套的《格蠹汇编》提供了老师大量的调试经验以及实验环境。不拿来好好实践一番简直浪费。工具

 

0X01调试笔记之侦查广告插件测试

俗话说:工欲善其事,必先利其器。对于调试领域来讲,更是如此。咱们不但要在本身的计算机中安装有WinDbg,还应当使用JIT调试的方法。由于对于Windows系统中的应用程序的崩溃问题,JIT调试是很是有效的办法,并且JIT调试仍是Windows系统和WinDbg密切配合,从而实现高效调试的典范。这样,当咱们的程序崩溃时,调试器就可以自动地执行,配合以相应的指令,就可以很快地定位程序出错的位置,从而进行修改。编码

本节叫侦查广告插件,其实是用JIT肯定老发生崩溃的错误框是哪一个程序弹出来的。spa

 

第一步 在注册表中设置JIT调试
咱们首先须要设置JIT调试。这里须要打开注册表,对于32位的Windows系统而言,其位置在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug:插件

这里的Auto表示是否启动JIT调试,若是这个值为1,则是启动JIT调试,若是为0,说明不启动。而下面的Debugger保存的是欲启动的调试器的路径及参数信息。线程

在执行 AcsVio.exe(人为制造一个崩溃,弹出错误提示框) 以前需设置WinDbug为默认的即时调试器,设置为在cmd行输入C:\WinDbg\windbg_CN.exe -I 命令调试

 

 

这是咱们执行提供的AcsVio.exe(一个崩溃的exe文件)code

 

第二步 利用JIT调试来分析软件问题blog

能够看到WinDbg已经自动弹出了,而且在出问题的位置断了下来。上图中第一个红框说明了程序的问题:Access violation,也就是访问违例。而第二个红框则是给出了出问题位置的反汇编代码。能够看到,程序将0赋给了[ecx],这个地址读写发生了错误,就出现了访问违例的状况。

下面输入指令:
0:000>.symfix c:\Symbols
这条语句用于设置符号路径。而后输入:
0:000>kPL

其中k表示显示栈回溯的信息,P表示将全部参数也显示出来,L用于隐藏原始代码:

 

能够看到问题就在main函数里面。经过栈的回溯,咱们就可以看到系统都调用了那些函数,从而进行进一步的分析。

 

0X02从堆里抢救丢失的博客

相信不少使用计算机的朋友都曾经遇到过在编辑文章时,因为本身的不当心或者是计算机的问题,而丢失了刚刚编辑好的文档的状况。 虽说如今的文字编辑软件通常也渐渐支持了自动存盘的功能,使得出现这样的“悲剧”的概率大大下降了,可是数据丢失的状况,偶尔仍是会发生的, 并且自动存盘的功能也会有失灵的时候。一旦出现了这种状况,那么这就须要咱们掌握必定的调试技术来尝试恢复这些数据。由于通常来讲,这些数据是保存在咱们的内存中的, 理论上来讲,只要这块内存区域的数据没有被改写,那么咱们就有办法找到那些丢失的数据。

 

第一步 打开目标文件

咱们首先打开WinDbg,而后选择File菜单下的Open Crash Dump,载入咱们此次所研究的文件ieblog.dmp。可见WinDbg已经为咱们打开了文件,而且已经停下来了:

虽说做者是在网上写的博客文章,可是事实上这篇文章的本体依旧是存在于本地计算机内存中的某个区域中的。因为做者很清楚本身的博客中有哪些内容,所以咱们能够在内存中检索博文中相应的字符串。这里能够输入以下指令:

>s –u 0 L800 “当年在交大”

上述命令的意思是,以Unicode的形式在内存中查找“当年在交大”这几个字,查找范围是从0到800。

回车后发现WinDbg并无返回结果,那么说明咱们这里所指定的800这个范围过小了,这里修改一下,将上述语句中的800改为8000000,而后再次尝试查找:

 

能够看到此次检索出了不少个结果。之因此可以在内存中搜索到这么多的结果,有多是做者在写做的过程当中对文章进行了屡次保存,或者说是系统自动进行了保存,因而就在内存中留下了痕迹。那么咱们下一步的操做就是确认到底是哪一个位置保存的是完整的博文。固然这里咱们依旧可使用s -u命令来查找博文中最后的几个字符,从而定位博文的范围。或者可使用以下命令:

>du 001b5942 L1000

上述命令的意思是从内存地址为0x001b5942的位置开始,以Unicode的形式显示内存中的内容,一共显示800个结果。WinDbg输出以下:

 

 很显然已经找到了!

第二步 提取内存中文章

能够发现,这个地址正是博文真实存放的地址。既然已经在内存中找到了这篇文章,那么下一步就是 将其从内存中提取出来。可使用以下命令:

>.writemem e:\blog_1.txt 001b5942 L1458

这行命令的意思是,将内存起始位置为0x001b5942处的内容读取出来,一共读取1458个字符,并命名为blog_1.txt,保存在E盘根目录下:

而后来到E盘根目录下,打开blog_1.txt文件:

 

 

可见虽然咱们已经把博文提取出来了,可是倒是以乱码的形式显示的。并且虽说是乱码,可是能够发现这些文字已经很接近于咱们的中文字了。其实之因此会出现这样的结果,就是由于咱们的系统没能有效地识别这些编码。为了解决这个问题,这里能够利用十六进制编辑工具,好比WinHex打开blog_1.txt文件,而后在文件开头加上Unicode的标识符FFFE,这样系统就可以以Unicode字符的形式进行解析了。

 

0X03拯救发疯的Windows 7

在咱们的平常生活中,会接触到各类各样的软件。这些软件的编写者在开发该软件时,每每并不会对其作很是全面的测试,这就致使了当这款软件被不一样的用户所使用时,不可避免地会出现各类各样的问题。若是只是功能上出现问题,那么危害每每不大。可是若是是软件中存在着致命的漏洞,那么极可能就会被别有用心者所利用,从而危害到用户的计算机系统。甚至还可能出现这样一种状况,有时候用户的一些无意的输入,而软件中没有相应的处理机制,因而也就致使了软件乃至系统的崩溃。那么这些问题,其实均可以利用调试技术进行解决。

 

首先打开WinDbg,而后在File菜单下选择Open Crash Dump,打开WERA7FB.tmp.mdmp文件。此时WinDbg就已经帮咱们断下来了:

 

在上图的红框中能够发现,出现问题的位置在280号进程中的2a4号线程。所出现的问题是缓冲区的溢出。因为缓冲区的溢出是与咱们的栈空间紧密相关的,所以咱们如今能够看一下栈上的状况。在WinDbg中输入如下命令:

>kn

 其中的k用于显示给定的线程中的栈帧的信息,而参数n能够显示帧的编号。WinDbg获得以下输出:

 

能够看到这里出现了几个以Wer开头的函数,wer的意思是Windows Error Report,说明这个进程在终止前调用了WER设施,这正是咱们可以获得这个转储文件的缘由。8号栈帧中的函数是UnhandledExceptionFilter,这是位于kernel32.dll中的用于处置未处理异常的核心函数,它也是系统在终止掉一个进程前作最后处理的地方,应用程序错误对话框和JIT调试都是从这个函数发起的。

由张银奎老师所编写的《软件调试》的第12章就深刻地讨论了这个问题。而在这个函数的下方,通常就是咱们所要查找的致使异常的函数位置了。看一下9号栈帧,这个函数的名称叫作_report_gsfailure,其所在的模块为umpo.dll。说到这里我想要强调的是,咱们在之后的分析过程当中,若是说遇到了咱们并不熟悉的模块,那么我建议你们应当查看一下模块的基本信息,能够在WinDbg输入以下指令:

>lmvm umpo

上述命令中lm表示列出模块的信息,v表示将详细信息显示出来,最后的m表示须要进行模块名称的匹配。

WinDbg的输出以下:

 

可见,这里已经列出了关于umpo这个模块的比较详细的信息。我之因此强调让你们多关注一些不太常见的模块,就是由于不少恶意模块每每是“三无”产品,好比对于没有版本号、没有厂家、没有产品名称等,但却存在于Windows的重要目录,那么这个模块就很值得怀疑了。固然这里的umpo模块是没有问题的。

那么咱们继续分析栈帧。简单来讲,是umpo这个模块中的UmpoAlpcSendPowerMessage函数出现了缓冲区溢出的状况。当这个函数要返回的时候,编译在函数中的溢出检查代码检测出了溢出,因而调用_report_gsfailure函数来报告错误。这种检测溢出的方式一般称为基于Cookie的溢出检查,简称为GS机制。

简单来讲,GS机制就是在可能发生溢出的函数所使用的栈帧起始处(EBP-4的位置)存放一个称为Cookie的整数,在函数返回时检查这个Cookie是否无缺,若是被破坏了,就说明函数中发生了溢出。部署和检查Cookie的代码都是编译器在编译时加入到函数中的。

由于咱们已经知道函数UmpoAlpcSendPowerMessage出现了缓冲区溢出的错误,那么咱们能够具体看一下当前的Cookie以及EBP等的值都是多少。能够在WinDbg中输入以下命令:

>dd 009afb30-4 L4

上述命令中的dd表示以双字的形式显示内存中的内容,009afb30表示出问题函数的EBP,减去4则是Cookie值的位置,L4代表显示4个结果。WinDbg的输出以下:

 

 能够看到第一个00640064就是Cookie值,父函数的EBP也是00640064,而返回地址则是006a002e。能够发现,这些值都不像是正规的内存地址,反而像是ASCII码值。看来因为出现了缓冲区溢出的问题,使得一些重要的数据都被冲掉了,变成了其它的数值。下面咱们能够看一下出问题的函数的变量空间的状况。那么该如何肯定这个范围呢?首先用两个函数的保存有EBP的位置的地址相减,也就是0x009AFB30减去0x009AF924,得出的结果为0x20C。可是对于_report_gsfailure这个函数而言,它的下方还包含有Cookie值以及EBP的地址,一共占据了8个字节的空间,因此还应当用0x20C减去8,也就是0x204,就是问题函数UmpoAlpcSendPowerMessage的变量空间了。那么下面就来看一下这个空间中发生了什么:

>db 009afb30-204 L210

上述命令的意思是以字节的形式显示内存地址为0x009AFB30减去0x204位置的内容,显示210个结果:

 

 

能够看到这里出现了一个超长的文件名,那么咱们就能够知道,这就是出现缓冲区溢出问题的源头了。可见上图中第一个红框就是EBP,而第二个红框则是返回地址的位置。如今能够知道,由于Umpo模块中的函数UmpoAlpcSendPowerMessage接收到了一个比预想长度还要长的参数,因而就发生了缓冲区的溢出状况,从而触发了GS机制。既然知道了缘由,那么咱们如今只要把文件的名称改短,问题也就可以解决了。

相关文章
相关标签/搜索