强制使应用程序崩溃
Posted
技术标签:
【中文标题】强制使应用程序崩溃【英文标题】:Force crash an application 【发布时间】:2011-05-16 03:44:24 【问题描述】:我目前正在测试我公司编写的应用程序。其中一种情况是查看如果该应用程序崩溃,系统状态会发生什么。是否有一个应用程序可以强制我的应用程序崩溃?我宁愿不将崩溃写入代码本身(即空指针取消引用)。使用任务管理器终止进程不会产生相同的结果。
【问题讨论】:
使用 DLL 注入可能是实现这一目标的可行途径,但是我不知道有任何应用程序已经可以处理这个问题。 你不能在你的鳕鱼中间放一个简单的 exit() 吗?或者这不被认为是“崩溃”吗? 系统状态是什么意思?一般当一个进程崩溃时,系统会清理所有使用的资源。但是,这可能不会扩展到数据库句柄之类的东西。您将如何检查系统状态? 崩溃是结果,你应该查明原因。 【参考方案1】:在 Windows 上,您可以将 WinDbg 附加到进程,破坏某些寄存器或内存并分离。例如,您可以将某些活动应用程序线程的指令指针设置为 0。
windbg -pn notepad.exe
attach之后,当前线程设置为debug线程,所以你需要更改为app线程,使其在RIP寄存器更新时崩溃
0:008> ~0s
0:000> rip=0
0:000> qd
【讨论】:
【参考方案2】:假设 Windows,请参阅Application Verifier。
它可以进行故障注入(低资源模拟),以可配置的速率使各种 API 调用失败。例如。堆分配、虚拟分配、WaitForXxx、注册表 API、文件系统 API 等。
您甚至可以指定在启动期间不会注入任何故障的宽限期(以毫秒为单位)。
【讨论】:
很好,我不知道这个工具。看起来它可能非常有用!【参考方案3】:最好的方法是从 windows.h
调用 RaiseException APIRaiseException(0x0000DEAD,0,0,0);
或者你可以从 ntoskrnl.exe 做一个运行时链接到 KeBugCheckEx() 并在你的代码中调用它。
例子:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
HINSTANCE h = LoadLibrary("ntoskrnl.exe");
cout<<h<<endl;
void* a;
a = (void*) GetProcAddress(h,"KeBugCheckEx");
int(*KeBugCheckEx)(ULONG,ULONG_PTR,ULONG_PTR,ULONG_PTR,ULONG_PTR);
KeBugCheckEx = (int(*)(ULONG,ULONG_PTR,ULONG_PTR,ULONG_PTR,ULONG_PTR))a;
cout << a;
KeBugCheckEx(0,0,0,0,0); //crash in module ntoskrnl.exe means that call success!
【讨论】:
RaiseException 是一个稍微不同的问题的合理答案:如果 Windows 应用程序检测到问题,它应该如何自行崩溃?虽然 flags 参数可能应该是EXCEPTION_NONCONTINUABLE
而不是 0。KeBugCheckEx 会导致操作系统崩溃,除非您从内核模式调用它并且崩溃系统是防止损坏所必需的,否则这太过分了。
对于 RaiseException 解决方案,最好使用异常代码 STATUS_FAIL_FAST_EXCEPTION
(0xC0000409)。如果您想使用自己的自定义异常代码,请确保您设置了第 29 位(表示用户定义的代码)并将第 28 位清除(因为它是系统保留的)。换句话说,您的异常代码可能应该以高 nybble 中的 0xE 开头,如 0xE000DEAD。【参考方案4】:
您没有说明您在哪个操作系统上运行,但是,如果它是 Linux(或其他类似 UNIX 的系统),您可以 kill -9
您的进程。这个信号无法被捕捉到,并且会导致地毯很快从您的进程中被拉出。
如果您不在类 UNIX 系统上,我无法帮助您,抱歉,但您可能会找到一些有用的信息 here(查找“taskkill”)。
【讨论】:
【参考方案5】:如果系统在 UNIX/Linux 上运行,您可以向它发送一个信号:SIGQUIT 应该产生一个核心转储,如果您想测试它是否出现“分段错误”,您也可以向它发送 SIGSEGV。分别是信号 3 和 11。
如果系统是 Windows,我不知道如何在不同的应用程序中引发信号,但如果您可以修改应用程序以处理将调用 raise() 的特定 Windows 消息编号,您可以模拟它。 raise() 会引发信号,而无需实际编写执行非法操作的代码。然后,您可以向应用程序发布一条消息,该应用程序将具有引发此信号的处理程序。
【讨论】:
查看我关于 RaiseException 的帖子。打开它的进程,获取一些原始函数指针,或者只是破坏它的堆:)【参考方案6】:您可以覆盖全局 new 运算符。然后,您可以使用计数器并在特定值处执行空指针取消引用以强制您的应用程序崩溃。通过简单地更改执行取消引用的时间值,您可以轻松更改崩溃时间。
【讨论】:
【参考方案7】:您可以为此使用winapiexec
工具:
winapiexec64.exe CreateRemoteThread ( OpenProcess 0x1F0FFF 0 1234 ) 0 0 0xDEAD 0 0 0
将1234
替换为进程id并运行命令,进程会崩溃。
【讨论】:
【参考方案8】:这个“系统状态”在哪里定义?如果这是 unix,您可以向进程发送信号 9...
如果您真的需要,您可以与另一个进程(或线程)共享所有应用程序内存,并让该线程随机写入随机数据一些不幸的内存位置 - 我认为 NASA 为他们的一些太空项目这样做了,但是实在是给不了参考。
真正的问题是你为什么要这样做——你/真正/测试什么?
例如,如果这是控制某些开药的医疗服务的某个程序...改为对该服务进行单元测试,分析 API 并查找缺陷。
【讨论】:
【参考方案9】:自己做一个缓冲区溢出。
#include <string.h>
void doSomething(char *Overflow)
char Buffer[1];
strcpy(Buffer, Overflow);
int main()
doSomething("Muhaha");
你的程序会崩溃
【讨论】:
遗憾的是,它不会以一种可靠的方式运行——这只是未定义的行为,它可能并不总是会导致有保证的崩溃。【参考方案10】:另一种方法是在良好的调试器中运行应用程序,为特定代码行设置断点,然后中提琴,您的应用程序已“崩溃”。现在,这可能不会导致所有线程停止运行,具体取决于所使用的调试器。或者,您可以在调试器中运行应用程序,并在一段时间后简单地“停止”应用程序。
这不一定会导致内核崩溃并杀死应用程序(并可能转储内核),但无论如何它可能会做你想做的事。
【讨论】:
【参考方案11】:从您的代码中调用 abort()
函数。其他程序不能可靠地“崩溃”您的程序 - 它们有自己的进程上下文,与您的程序上下文隔离。您可以在 Windows API 或其他特定于平台的函数中使用 TerminateProcess()
之类的东西,但这与使用任务管理器或多或少相同。
【讨论】:
以上是关于强制使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章