首页
课程
问答
CTF
论坛
招聘
看雪峰会
发现
企服
众测
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
论坛
课程
招聘
发现
问答
企服
专栏
CTF
众测
排行榜
知识库
工具下载
看雪峰会
看雪20年
看雪商城
证书查询
专栏首页
安全鸟一起飞
文章详情
怎样分析Windows dump
freakish
举报
2017-05-18 22:33
469297
dump文件从哪里来?
项目工程
一般的项目都会有类似xxxProtect 这样的工程,专门负责项目crash文件的搜集,上传操作。其主要原理就是利用Windows API MiniDumpWriteDump 来生成dump文件, 触发dump抓取时机就是程序发生异常的时候, 当然也可以在任意一个线程中的任意时刻使用这个API进行抓取
专业抓取工具
Windows自带的任务管理就可以抓取,打开资源管理器,在任意一个进程上右键 - 创建转储文件即可
其他类似专业工具
dump文件可以解决那些问题?
程序Crash
当程序需运行发生异常的时候,如果我们的搜集机制正确的完成dump文件搜集并上传到服务器,那么我们就可以从服务器获取到这个dump文件, 这个dump文件记录了程序发生异常的时候程序运行内存现场。因此通过分析这个运行上下文的快照,我们可以尝试查找问题发生的原因。
有的时候,你会发现,用户反馈说程序莫名的就退出了,完全没有任何征兆,也没有弹出你们的dump文件搜集程序,这个时候只有一种原因,那就是程序发生了你们目前的搜集机制无法捕获的异常,这个时候应该怎么办呢?通常大家可以选择两个方案来尝试缩小问题排查范围:
通过客户端日志的最后一条消息输出来确定范围
如果用户肯配合,则可以通过给用户的机器上传Windbg这个轻量级的调试器,让用户在调试器下面运行,这样当用户发生异常的时候,就会被调试器捕获到,可以通过Windbg的dump生成命令生成dump文件来进一步进行问题排查, 参考Windbg dump命令:.dump /ma C:\dumps\myapp.dmp,其中/ma选项说明要生成内容详细的问题现场,但是生成的文件可能比较大。如果选择 /m选项,可能生成文件比较小,但是提供的信息就相对较少了,大家可以自己权衡。
程序运行异常(如:界面卡死)
在项目上线之后,可能我们都会遇到这样一种场景,就是程序没有发生崩溃,但是UI界面却没有响应了,这个时候你急切需要的就是要知道到底UI线程在干什么,为什么不响应我的操作了。你需要的第一手资料就是当前运行进程的内存dump文件,同样你需要先采用前面介绍的方法来进行内存抓取(资源管理器或者专业工具)
有了内存执行快照dump文件,就可以开始根据经验来判断你首先要分析的是哪些对象了。就说界面卡死这种问题, 我们就是要看到底UI在这个时候在干什么这么忙,导致连我们的键盘鼠标这样的高优先级的操作都不响应了,比如我们会看当前UI线程的堆栈,看看最后是在做繁忙的任务,还是干脆发生了死锁。
分析dump之前,你需要哪些准备?
工具
自古是工欲善其事必先利其器, 所以要想从dump文件中获得重要问题信息,没有好的工具显然不行,我推荐 Windbg 和 VisualStudioxxx
Windbg
这个工具其实不用多说了,微软亲儿子,Windows环境下的各种问题分析利器,dump分析其实只是他的一小部分功能,更多强大的功能大家可以自行百度,我们单说他的dump分析功能:
支持Windows系统中系统模块符号自动匹配下载(尤其问题发生在系统模块的时候很有帮助)
轻量级,整个工具包很小,方便传输携带,无论本地使用还是上传到用户环境似乎都是首选
支持pdb符号时间戳模糊匹配,这个很重要,尤其是无法找到当时打包的时候生成的pdb
配套的分析命令和插件,对分析问题很有帮助
Visual Studio
宇宙第一IDE不是浪得虚名,提供了强大的代码编辑环境之外,同样提供了强大的调试支持,这里dump分析也属于她调试功能的一部分
符号文件
这个文件太重要了,对于分析问题能提供极大的帮助,那么问题来了:
pdb文件从哪里来? 在项目编译打包的时候,编译器会根据你的工程配置,在编译输出目录生成 .pdb文件,理论上每个独立的模块(.dll .exe)都会有一个对应名称的pdb文件,比如你的工程主程序是main.exe, 那么你应该会有main.pdb这么个文件,如图1:
pdb文件作用体现在哪里? 我觉得还是直接上图最能说明问题,如图2、3的对比起来就很清楚了(有符号能提供更多的崩溃现场堆栈调用信息):
常见dump场景分析实例
实例场景一:程序崩溃分析
这个例子我们选用Windbg来分析, 这里我假设已经获得了某个崩溃现场的文件,名称为A.dmp, 按如下步骤操作:
打开Windbg工具,选择菜单 File ->Open Crash Dump, 选择你的dump文件并打开,正常打开完毕,应该是这样的界面:
设置pdb符号, 选择菜单 File -> Symbol File Path, 在弹出的设置框中,填入你本地保存的pdb的路径,为了Windbg能够自动加载系统模块的符号,建议在你的pdb的路径之后添加分号,然后加入微软的系统模块符号路径,参考设置结果是这样的: d:\my_project\bin\release\pdb;SRV*c:\mysymbol*
http://msdl.microsoft.com/download/symbols
,前半段是你的工程的pdb目录,后半段是微软模块符号路径
如果分析的机器上有这个崩溃程序版本对应的源代码,那就更好了,你可以继续设置一下源码路径,设置源码路径有什么好处呢?你会很开心的发现,当你通过命令让Windbg分析crash现场的时候,Windbg能够自动化的给你定位到发生问题的那行源代码上, 但是请注意一个问题:如果你的源代码并不是当初编译这个程序的那份源码,Windgbg给你的结果就会迷惑你。举例来说,如果你有一个源码文件,有10行代码,这个源码在2017-06-01已经编译过程序A,并且已经发布上线了,然后你在2017-06-02这一天在这个源码的第2行前面增加了几行代码, 我们假定程序A在第5行发生了Crash, Windbg的自动分析就会给你自动定位到第5行, 但是其实这个时候因为你修改了源码,那么这个时候的第5行已经不是当初的第5行了,Windbg就会迷惑你了, 这同时也显示出了代码版本管理的重要性了。
经过前面的几部操作,我们已经做好了最基本的准备,下面可以尝试一下Windbg的自动化分析了,为了保障符号的正常加载,我们首选让Windbg进入符号模糊匹配的模式,意思就是告诉Windbg我设置的这个pdb的路径是对的,如果pdb的时间戳对不上,你也给我强行加载吧,然后开始进入经典的三步(注意:如果左下角显示
BUSY
, 就要等它一会儿,执行完这一步再进入下一步的命令):
进入符号模糊匹配模式:!sym noisy on,
加载pdb:.reload /i
自动化分析:!analyze -v
如果你不清楚在哪里敲入命令,看我的图4(命令输入框位置),图5(你应该得到的结果):
结果有了, 这个结果怎么看呢? 上面一幅图说过了,很简单,箭头的地方就是输入命令的地方,不说了。看下面的结果分析部分, 图中标出了 第一处 第二处 第三处三个地方:
第一处, 代表当前崩溃的最后一层函数调用是什么地方
第二处代表,根据当前设置的符号和源码路径,是崩溃在这一行了
第三处这里仔细看有一个 > 符号, 就是一个指示箭头,标识当前崩溃的行是在哪一行
工具的帮助有了,下面就是开始依赖个人编程经验来分析了,首先看这一句 m_testPtr->SetEnable(false); 这样一句话的发生了崩溃,只有2中可能, 第一种:m_testPtr = NULL(或野指针); 第二种:m_testPtr所处的环境是一个异常环境,根据这里的实际情况就是, ClientLoginDialog对象的this指针是空(或野指针), 这个时候经过初步的判断,我们就可以选择不同的方法来排查了:
第一种就是直接看代码,查找m_testPtr是否可能为NULL, 或者 ClientLoginDialog对象的this是否可能为空或者是野指针
用Windbg继续排查, 这个时候继续输入一波命令:
切换到异常线程:.ecxr
打印异常堆栈:kvn
这个时候,你应该进入这样的节奏了,看图:
还是进入到了刚才的问题现场,这个时候我们输入 r 命令,接着输入u命令(目的是为了多打印一些崩溃点代码上下文),看崩溃现场详细信息:
这个时候需要一点点汇编知识了,不然的话,你只有第一步中的那种方法来查代码了,我们直接看第二个箭头,
00402fbc 8b01 mov eax,dword ptr [ecx] ds:002b:00000000=????????,观察第一个箭头 ECX = 0, 大家都知道 0地址内存是不能访问的,那到底是什么地方为0了呢, 接着看下面几句代码,从第二个红箭头的地方看到了Call, 这个是函数调用指令, 根据前面Windbg定位的 m_testPtr->SetEnable(false); 这句,我们知道肯定是在调用SetEnable这个函数, 而函数的地址来自 [eax+0ECh], 则只要EAX有效就行, 而EAX的值正是需要 崩溃的那一句 mov eax,dword ptr [ecx] ds:002b:00000000=????????来赋值, 所以这里我们可以知道, 这里的ECX 就是代码中的 m_testPtr 这个变量(这个因为所以的由来技术细节又来源于C++内存对象模型的知识,需要百度自行补充一下), 由此我们确定就是 m_testPtr 这个指针为空导致的问题,定位到这里,没有更多的路子走了,只能死看代码 + log来找问题了,Windbg也尽责完毕了。
光靠dump分析足够吗?
从崩溃分析的部分可以知道, dump分析能告诉你是什么地方出了问题, 但是最后问题发生的具体逻辑原因是找不到的, 你需要继续看代码,然而经常看代码经常是很难找到问题, 所以你需要在开发的时候保持良好的log习惯,这个是关键时刻的救命草,好的log可以直接排查出来大多数问题,甚至都不用dump分析。
所以,需要再强调一下的是,要有相对完善的log
收藏
分享
分享到微信
分享到QQ
分享到微博
声明:该文观点仅代表作者本人,转载请注明来自看雪专栏
最新评论
(
0
)
举报原因
×
广告灌水
涉黄涉暴
反动语言
其他
50
/50
登录后即可评论
安全鸟一起飞
创建者:
freakish
持续关注Windows安全、Andorid安全
205
关注数
31
文章数
关注
该专栏热门文章
1
Frida官方手册 - JavaScript API(篇二)
JavaScript API Int64 new Int64(v): 以v为参数,创建一个Int64对象,v可以是一个数值,也可以是一个字符串形式的数值表示,也可以使用 Int64(v) 这种简单的方式。 a...
2
Frida官方手册 - JavaScript API(篇一)
JavaScript API 目录 Global console rpc Frida Process Module ModuleMap Memory MemoryAccessMonitor Thread Int64 UInt64 NativePoint...
3
Frida官方手册 - 在iOS上使用Frida
在iOS上使用Frida 在iOS设备上,Frida支持两种使用模式,具体使用哪种模式要看你的iOS设备是否已经越狱。 使用场景 已越狱机器 未越狱机器 已越狱机器 在越狱的环境下,是用户权限最大的场景,在这样的环境下你可以很轻松的调用系统服务和基础组件...
4
Frida官方手册 - 安装Frida
安装Frida 从零开始安装使用Frida大概只需要几分钟的时间就可以搞定。如果你安装的过程中发现什么问题,可以告诉我们(请参考原文链接https://www.frida.re/docs/installation),看看我们是否有比较好的解决方案。 安装环境...
5
Frida官方手册 - 函数Hook
函数Hook 这一篇我们看下如何在目标进程中对程序中的函数进行调用监视、参数修改、以及函数的主动调用 准备环境 创建文件 hello.c,内容如下: 使用如下命令进行编译: 启动程序,然后记下函数 f() 的地址(在这个例子中,值是0x400544):...
6
[开源]Android逆向中So模块自动化修复工具+实战一发
前言 Android加固方案经过这么长时间的发展,从开始的整体dex加密压缩方案逐步开始往native层发展,市面上知名的几款商业级加固方案中很容易发现这种方案的身影。这样看来,在今后相当长的一段时间内,Android逆向中不可避免的会频繁接触到与So加固的...