分析一个dump的一般步骤
- 看清楚是何种异常导致的崩溃.
- 对齐symbol, 找到发生崩溃的函数名字, 以及对应的汇编代码和源代码.
- 列出callstack
- 检查callstack是否合理
- 检查发生崩溃的函数是否得到了正确的参数.
- 检查发生崩溃的函数使用的数据是否正确.
- 结合上面的信息, 构思来龙去脉, 然后用资料来证明, 或者反驳自己的猜想.
- 通过进一步的操作来获取更有意义的资料. 比如激活pageheap后, 重新抓取dump, 或者干脆进行Live debug
你有没有写过不太正确但足够接近的代码?当一切顺利的时候,你是否不得不编写运行良好的代码,但是你不太确定当出了问题时会发生什么?有一个简单的、不正确的语句可能位于您编写或必须维护的代码中:catch (Exception e)。这似乎是无辜和直截了当的,但这个小小的声明会造成很多问题,当它不能做你期望的。
如果您像下面的代码那样使用异常的代码:
public voidFileSave(String name)
{try{
FileStream fs= newFileStream(name, FileMode.Create);
}catch(Exception)
{throw new System.IO.IOException("File Open Error!");
}
}
硬件异常可以分为三种:
以栈作为基础的SEH本身具有很大的危险性,我们可以利用各种手段对栈上SEH节点进行覆盖重写,再次执行异常处理操作时就会将执行权给到了我们用来覆盖的函数上,这实际上在以前是很常见的windows栈溢出手段,当然,除了这种方法外还有许许多多的利用手段,可见这样的异常处理机制还是不够完善的。为了解决这些问题,微软逐步加入了Safe SEH、SEHOP、VCH等来弥补。
SafeSEH又叫做软件DEP,是一种在软件层面实现的对SEH的保护机制,它需要操作系统和编译器的双重支持,在vs2013及以后的版本中会自动启用 /SafeSEH 链接选项来使用SafeSEH。也正是因为该项技术使得以往简单的覆盖异常处理句柄的漏洞利用几乎失效了
在加载PE文件时,SafeSEH将定位合法的SEH表的地址(如果该映像不支持SafeSEH的话则地址为0),然后是用共享内存中的一个随机数进行加密处理,程序中所有的异常处理函数的地址提取出来汇总放入SEH表,并将该表放入程序映像中,还会将将加密后的SEH函数表地址,IMAGE的开始地址,IMAGE的长度,合法SEH函数的个数,作为一条记录放入ntdll(ntdll模块是进行异常分发的模块)的加载模块数据内存中,每次调用异常处理函数时都会进行校验,只有二者一致才能够正常进行,该处理由RtlDispatchException() 开始,首先会经历两次检查,分别是:
通过两次检查后会调用RtlIsValidHandler() 来进行异常的有效性检查,08年的black hat给出了该函数的细节
BOOL RtlIsValidHandler( handler )
{if (handler is in the loaded image) //是否在loaded的空间内 {if (image has set the IMAGE_DLLCHARACTERISTICS_NO_SEH flag) //是否设置了忽略异常 returnFALSE;if (image has a SafeSEH table) //是否含有SEH表 if (handler found in the table) //异常处理函数地址是否表中 returnTRUE;else returnFALSE;if (image is a .NET assembly with the ILonl y flag set)returnFALSE;
}if (handler is on non-executable page) //handler是否在不可执行页上 {if (ExecuteDispatchEnable bit set in the process flags) //DEP是否开启 returnTRUE;elseraise ACCESS_VIOLATION;
}if (handler is not in an image) //handler是否在未加载空间 {if (ImageDispatchEnable bit set in the process flags) //设置的标志位是否允许 returnTRUE;else returnFALSE;
}return TRUE; /s/允许执行异常处理函数
}