虽然搞乱了一些x86 asm,但我想知道一个错误导致EIP被设置为00000000
或另一个不存在的内存位置的情况。是否可以通过SEH或类似的错误处理机制捕获这些情况并恢复执行? (假设堆栈,堆和寄存器没有被删除)
答案 0 :(得分:2)
在它发生之前没有很好的方法可以捕获它,但你可以尝试的一件事是检查堆栈(ESP
和/或EBP
处的内存)并检查指向代码的指针。
如果导致此问题的指示是call
,那么您很幸运 - ESP
处的双字将是返回地址,紧跟在违规者之后。
如果它是jmp
,则机会较小,但你仍然可以寻找可能的执行痕迹。
最糟糕的情况是,这是由带有ret
的{{1}}引起的 - 通常此时堆栈完全是假的。您仍然可以检查其他寄存器的值,可能其中一个寄存器将包含一个可能为您提供一些线索的指针,并且您扫描整个堆栈区域以查找堆栈帧图案,如in this post所述。
答案 1 :(得分:0)
您最有可能,也可能是最安全的“解决方案”是使用setjmp
/ longjmp
(或CONTEXT
)可以安全返回的流程状态的快照存储在流程的唯一位置,但不可触及,例如FS
/ GS
/ ES
段,与PEB的存储方式相似。这样可以正确恢复所有寄存器,而不会留下太多可能的漏洞。
当然这对于像游戏这样的东西来说是错误的(取决于爆炸发生的确切位置),但是对于像文字处理器这样的东西,或者说轻微状态丢失不是主要问题的应用程序,它应该可以正常工作(这提醒旧的Dev-C ++ IDE,曾经崩溃过所有其他文件,但不知何故仍然继续运行,尽管它确保了一个“致命”的例外,它无法从...恢复。)。