如何战略性地打败分段故障?

时间:2014-02-19 16:33:02

标签: c linux memory-management segmentation-fault signals

标题具有误导性;让我澄清一下。首先让我们考虑安全上下文。

攻击操作会写入某些未映射/不可访问的内存(例如,由于堆缓冲区溢出)。假设我可以捕获内存访问冲突触发的信号。

在信号处理程序中,我可以策略性地“静音”写操作吗?类比是将stdout重定向到/ dev / null。同时,我需要让写操作完成,否则控制流不能继续(例如,写指针不会在循环中增加)并且程序运行被卡住。

我认为这个想法的意义在于它可以在不崩溃系统的情况下使攻击静音,对吗?

编辑:我无法更改用户代码。我想在我的信号处理程序中操作PC来跳过mov指令。它会起作用吗?

1 个答案:

答案 0 :(得分:1)

你绝对可以做到这一点,但这很难,如果没有设计整个软件堆栈以抵御这些故障,就无法做到这一点。在你完成时,你最终可能会实现Erlang的一半:)

您必须在一个单独的线程中运行调试器,该调试器连接到您自己的应用程序,并使用特定于平台的调试API来获取监视线程中发生的硬件(CPU)异常的通知。

根据此类通知,被监视的线程被挂起,您可以在发生故障时访问寄存器的状态。此时,您可以反汇编指令以确定其长度,并使用NOP重写它。你还需要确定哪种内存空间是出现故障的指令 - 如果它在你自己的代码中,你绝对不应该触摸任何东西并简单地恢复线程,让原生信号/异常处理程序(如果有的话) ) 搞定此事。只有当它们发生在非代码区域时(例如:数据区域),您才应该发现这些问题。

唉,在大多数理智的平台上,数据页面无论如何都不可执行,因此您捕获的硬件异常将指示在非可执行页面中尝试执行代码。在进行堆栈分析并确定代码应该执行的位置时,没有什么简单的方法。通过使页面可执行来打败运行时的数据执行预防非常糟糕的想法

理想情况下,当出现故障时,您应该有一种终止并重新启动相关线程的机制。这是Erlang采用的方法:let it crash并重新启动崩溃的线程/进程。