DbgHelp教程4——Minidump自定义信息

MiniDumpWriteDump的MINIDUMP_TYPE可以控制往dump里面写入什么信息。不过MINIDUMP_TYPE只是一些固定的类型信息,比如内存、句柄、进程、线程信息,有时候为了定位问题,我们想收集一些其他的数据,然后写入到dump里面。恰好PMINIDUMP_USER_STREAM_INFORMATION参数可以做这个事情。 注意:自定义信息的MINIDUMP_USER_STREAM_INFORMATION的MINIDUMP_USER_STREAM的Type值必须大于MINIDUMP_STREAM_TYPE::LastReservedStream,因为之前这些值都是保留的标准类型。 可惜的是Windbg不能直接读取MINIDUMP_USER_STREAM_INFORMATION的信息,我们只好通过MiniDumpReadDumpStream接口去读取dump里面的数据。 根据MINIDUMP_STREAM_TYPE的描述,我们还可以从dump文件里面读取一些预置的信息,比如线程列表、模块列表、内存列表、异常信息、系统信息、句柄信息、函数表信息、等等。   ... Read More | Share it now!

windbg调试内存破坏之栈溢出

当线程覆盖了为其他用途所保留的桟空间时,就是发生了栈溢出Overflow.桟溢出包括覆盖桟帧的返回地址,覆盖整个桟帧,或者消耗尽桟空间等情况。桟溢出将带来各种后果,包括程序崩溃,未预期的行为,甚至严重的安全漏洞。 运行这个程序,如果输入一些短的字符串,那么程序似乎运行起来没有问题。如果输入一个很长的字符串就会导致崩溃。 我们看下崩溃时的状态很奇怪: 乍一看,桟破坏的很严重。我们看下当前的指令指针eip   这块内存的内容是一系列?,代表这不可访问的内存。我们可以假设程序中用于控制执行流程的指令指针可能被破坏了。 我们再看看桟上的内容:   桟上的内容是aaaaaaaaaaaaaaaaa是我们输入的命令行参数。看上去桟上的内容还是正确的。 桟的ret指令会把00610061当作指令的返回地址,程序将从这个返回地址继续执行。但是我们知道00610061是无效的地址。所以崩溃的原因是执行ret指令将导致eip被设置成一个错误的返回地址,如果程序从这个错误的返回地址开始执行,将发生访问违例。 看代码,用字符串复制函数之前的桟是正确的,因此在执行字符串复制期间肯定发生了某个事件导致桟被破坏。从代码中看出HelperFunction如果复制超过MAX_CONN_LEN的字符串将发生桟溢出。 windows驱动开发包里面包含一个PREfast的工具,可以在编译时检测一些代码缺陷。从vs2008开始,已经集成了这个功能。 ... Read More | Share it now!

windbg调试符号与源代码

设置符号路径 查看现有的符号路径 重置本地符号路径 增加一个本地符号路径 增加一个指向微软符号服务器的路径 重置一个指向微软符号服务器的路径 加载调试符号 加载某个符号 重新加载所有符号 重新加载某个符号 打开、关闭显示加载符号过程的详情模式 查看加载的文件与符号 lm命令显示加载模块的信息:lm... Read More | Share it now!

死锁排查

在做这个实验之前,需要先构建数据。 首先是声明两个全局临界区和两个互斥对象 四个线程 全局变量初始化以及线程创建: 整个代码比较简单,就是4个线程,会进入临界区和互斥对象。由于进入顺序不一样,就会导致死锁。 编译好后,生成了EXE:deadlocks.exe 用windbg启动调试。 并观察屏幕输出。由于每个线程都会打印日志。如果不再打印日志了就证明死锁了。 (死锁的明显现象就是线程停止,处在等待状态。调入NtWaitForSingleObject等函数中不出来。所以当产生死锁时,CPU占用一定不高。) 楼主发现屏幕只打印了两条日志就停止打印了(由于死锁发生的时机跟线程调度有关,你在测试时可能输出的日志与楼主不同,死锁时堆栈也不同,不过排错的原理是一样的)。 看样子是锁住了。 按Ctrl+Break,进入调试状态 楼主要看都有哪些线程锁住了,查一下所有线程的调用栈 通过观察调用栈,发现如下信息 0号线程是主线程,正在等待用户输出,死锁和他没关系 1号线程在等待进入临界区 2号线程也在等待进入临界区 3号线程在等待一个对象,可能是互斥量 4号线程也在等待进入临界区 5号线程是调试线程,忽略之 问题只能出在... Read More | Share it now!