首页
社区
课程
招聘
如何抓住程序在哪里退出的?想用于出错时生成Dump
发表于: 2021-5-20 10:09 5196

如何抓住程序在哪里退出的?想用于出错时生成Dump

2021-5-20 10:09
5196

我们都知道,程序经常会因为各种错误而退出

大家最常见的方法,就是用过SetUnhandledExceptionFilter配合MiniDumpWriteDump来生成转储文件,方便分析闪退原因

但是也会发现有些情况下,程序出错后自己直接退了,异常根本没被我们捕获到,所以无法抓住时机生成dump

我甚至Hook了ExitProcess函数,发现有那些情况下也没有调用。


也就是说,有些错误可能是vc的runtime内部检测到错误,自己直接退出进程了,这就可恶了,但又不知道调用的是哪个函数退出的我也抓不到。


此种情况下,有办法Hook到某些特定的函数并完成生成Dump吗?


测试代码(以下代码无法备捕获到):

LONG WINAPI CreateMiniDump(_EXCEPTION_POINTERS *pExceptionInfo)
{
    MessageBoxA(0, 0, 0, 0);
    return 0;
}
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
    // function、file、line在Release下无效
    //wprintf(L"Invalid parameter detected in function %s." L" File: %s Line: %d\n", function, file, line);
    //wprintf(L"Expression: %s\n", expression);
    // 必须抛出异常,否则无法定位错误位置
    throw 1;
}
void myPurecallHandler(void)
{
    //printf("In _purecall_handler.");
    // 必须抛出异常,否则无法定位错误位置
    throw 1;
}
void my_terminate_handler()
{
    //MessageBox(0, L"my_terminate_handler", 0, 0);
    // Abnormal program termination (terminate() function was called)
    // Do something here
    //std::cout << "terminate.\n";
    exit(1);
}
int main()
{
    std::cout << "Hello World!\n";
    ::SetUnhandledExceptionFilter(CreateMiniDump);
    _invalid_parameter_handler oldHandler;
    oldHandler = _set_invalid_parameter_handler(myInvalidParameterHandler);
    _purecall_handler old_pure_handle;
    old_pure_handle = _set_purecall_handler(myPurecallHandler);
    set_terminate(my_terminate_handler);
    void* p = malloc(100);
    free(p);
    free(p);
    MessageBoxA(0, "程序执行完成!", 0, 0);
    exit(0);
}



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-5-21 13:43 被sunbinjin编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (31)
雪    币: 246
活跃值: (4507)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
2
建立一个新的进程监视,MSDN本来就不推荐自己的程序里MiniWriteDump
2021-5-20 13:22
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
ookkaa 建立一个新的进程监视,MSDN本来就不推荐自己的程序里MiniWriteDump
抓不住的情况下,另一个进程就能抓住了吗?这块没区别吧?
2021-5-20 14:25
0
雪    币: 1278
活跃值: (1265)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
以调试方式启动程序不行?奔溃直接断点分析
2021-5-20 14:28
0
雪    币: 4650
活跃值: (5286)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
5
你这种估计是程序内存满了导致的异常,你此时再想写文件保存,可是写入操作也需要分配内存,进而导致了还没写成功就被系统提前终止运行了。
2021-5-20 14:30
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
10ngvv 以调试方式启动程序不行?奔溃直接断点分析
生成dump是为了在别的机器上抓回来分析,调试不可行的。
有可能是在客户机器上。
2021-5-20 15:32
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
sonyps 你这种估计是程序内存满了导致的异常,你此时再想写文件保存,可是写入操作也需要分配内存,进而导致了还没写成功就被系统提前终止运行了。
应该是某些runtime内部出错直接退出来,我是想如何抓住错误生成dump,我上面的代码示例就证明有些错误我现在没办法捕获。
2021-5-20 15:33
0
雪    币: 246
活跃值: (4507)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
8
MiniDumpWriteDump should be called from a separate process if at all possible, rather than from within the target process being dumped. This is especially true when the target process is already not stable. For example, if it just crashed. A loader deadlock is one of many potential side effects of calling MiniDumpWriteDump from within the target process.
2021-5-20 16:26
0
雪    币: 246
活跃值: (4507)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
9
你的谷歌浏览器就有GoogleCrashHandler.exe 
2021-5-20 16:30
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
ookkaa 你的谷歌浏览器就有GoogleCrashHandler.exe
我现在的问题不是生成不了dump,而是捕获不到异常
2021-5-20 16:34
0
雪    币: 246
活跃值: (4507)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
11
https://gclxry.com/article/catch-all-exceptions-in-visual-cpp/
都说了在开一个进程,这么多异常不说能不能处理,万一前面的exptionfilter都给你处理了,还怎么writedump
2021-5-20 17:09
0
雪    币: 4650
活跃值: (5286)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
12
sunbinjin 应该是某些runtime内部出错直接退出来,我是想如何抓住错误生成dump,我上面的代码示例就证明有些错误我现在没办法捕获。

最后一句改成

	int i=0;
	exit(100/i);

就可以捕获了。

2021-5-20 17:12
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
sonyps 最后一句改成 int&nbsp;i=0; exit(100/i);就可以捕获了。
你这是另一种异常,异常类型太多,我上面示例代码里的如何让它捕获到呢?
2021-5-20 18:56
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
再开一个进程,只是处理生成dump的事。
但也得先捕获到异常吧?我现在是捕获不到啊。
我看到别的文章说google跨进程生成dump,但它也是本进程捕获到后才跨进行生成dump的啊。如果捕获不到,vcruntime直接给你退了,跨进程也不能生成dump啊?

另外我看下你的链接,里面多了几个函数,我试一下。
不知道是不是我们两的沟通不在同一个频道?
2021-5-20 18:59
0
雪    币: 4650
活跃值: (5286)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
15
不是不能捕获是你的代码被优化编译了吧,因为调试版就能捕获到。
2021-5-20 19:36
0
雪    币: 36264
活跃值: (7170)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16

@sunbinjin
[img]https://attach.52pojie.cn/forum/202105/19/113942jvfe9vdva9oau9o5.png[/img]

[img]https://attach.52pojie.cn/forum/202105/19/114220wxy1d9901b23fd5g.png[/img]

这是一个delphi的demo组件
效果还是不错的,目录+表格展示
但是有个闪退的坑儿。
试过OllyDbg 批量下断(退出进程等一系列api 函数)
以及api monitor
还有x32dbg都没有找到关键位置
查看了一下调用堆栈
和调试跟踪
经常异常了
也查看过SEH窗口下断,断不到。
下面的地方很可疑,并在第3+次数点击时能断到,不久就会触发闪退。
这个没有搞明白,还希望楼主指点下究竟。

最后于 2021-5-21 08:56 被ninebell编辑 ,原因:
2021-5-21 08:53
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
sonyps 不是不能捕获是你的代码被优化编译了吧,因为调试版就能捕获到。
release没有优化掉,程序会出错,导致后面的代码Messagebox没有被执行。
debug是会被vs捕获到,不知道vs是如何做到的,vs的开发人员肯定这方面都知道如何处理。
2021-5-21 09:25
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
ninebell @sunbinjin[img]https://attach.52pojie.cn/forum/202105/19/113942jvfe9vdva9oau9o5.png[/img][img]https: ...
你也是想知道他在哪退出的是吧?
我所知道的api,自杀式的是ExitProcess
它杀式的就是TerminateProcess,参数传自己
什么exit内部都会调用到ExitProcess
2021-5-21 10:08
0
雪    币: 36264
活跃值: (7170)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
sunbinjin 你也是想知道他在哪退出的是吧? 我所知道的api,自杀式的是ExitProcess 它杀式的就是TerminateProcess,参数传自己 什么exit内部都会调用到ExitProcess

https://wwi.lanzoui.com/i175Zp9gi4h程序地址在这里,希望能给我解惑下,谢谢。

一般我的解决方法是x32dbg利用自动跟踪+公共走位找交集,找非法点位。

还有一个问题比较关心,x32dbg总是C5异常了,即使添加异常列表也不行。
FQ遍访网上的资料也没有说出个所以然的解决办法来。

最后于 2021-5-21 10:50 被ninebell编辑 ,原因:
2021-5-21 10:48
0
雪    币: 164
活跃值: (1823)
能力值: ( LV11,RANK:185 )
在线值:
发帖
回帖
粉丝
20
windbg可行?
2021-5-21 11:21
0
雪    币: 7027
活跃值: (3609)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
这个好像还有一个是runtime在崩溃时会重新调用SetUnhandledExceptionFilter(NULL)之类的将异常处理函数强制重置成默认的,这样你设置的就失效了。很多做法是自己设置完把这个接口给hook了不让runtime恢复。
2021-5-21 14:24
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
22
MSGG05 这个好像还有一个是runtime在崩溃时会重新调用SetUnhandledExceptionFilter(NULL)之类的将异常处理函数强制重置成默认的,这样你设置的就失效了。很多做法是自己设置完把这 ...
这个我在正式程序里也做了,能解决一些其它模块私自修改导致我主程序抓不住的情况
但对一个指针free 2次还是抓不住。
2021-5-22 10:08
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
23
MTRush windbg可行?
不是研发自己抓,而是程序抓了生成dump发回来研发再分析。
2021-5-22 10:09
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
ninebell sunbinjin 你也是想知道他在哪退出的是吧? 我所知道的api,自杀式的是ExitProcess 它杀式的就是TerminateProc ...
我的问题都没搞定的话,貌似也没办法解释你的程序是哪种退出机制。
2021-5-22 10:10
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
25
ninebell sunbinjin 你也是想知道他在哪退出的是吧? 我所知道的api,自杀式的是ExitProcess 它杀式的就是TerminateProc ...

程序自己都检测到堆栈溢出了,应该是字符串复制过界了。

2021-5-22 10:29
0
游客
登录 | 注册 方可回帖
返回
//