使用Windows XP中的一些软件作为Windows服务,并从login屏幕重新启动,我看到一个臭名昭着的错误消息
“00x …”处的指令以“00x …”为参考。 内存不能被读取。
我向开发人员报告了这个问题,但再次看到这个消息,我注意到地址是一样的。 所以
“00xdf3251”处的指令以“00xdf3251”为参考。 内存不能被读取。
不pipe这是程序中的一个错误,但是内存/访问权限的状态是什么,或者什么都不能阻止指令读取它所在的内存。 这是服务的具体内容吗?
我猜想有人试图在地址0xdf3251上执行一条指令,而且这个位置没有被一个可读和可执行的内存页面(可能是完全未映射的)所支持。
如果是这种情况,那么异常(实际上是页面错误)来自该指令,并且异常处理程序在栈上有地址(要返回的位置,以防异常可以以某种方式解决,并且当处理程序返回)。 这是你看到的第一个地址。
页面错误处理程序读取的CR2
寄存器(也就是您所看到的第二个地址)也具有相同的地址,因为它必须包含无法访问的存储器位置的地址,而不管页面错误是否由以下原因引起:
而不管它是在数据访问期间还是在获取指令的时候(后者就是我们的情况)。
这就是你如何获得指令和内存访问地址相等。
最有可能的代码有一个导致内存损坏的错误,并且一个指针(或堆栈上的返回地址)被一个指向不可访问内存位置的虚假值覆盖。 然后,一个或另一个CPU被指示在那里继续执行(很可能使用这些指令之一: jmp
, call
, ret
)。 在某个地方也有一个竞争条件的机会。
这种崩溃最常见的原因是堆栈损坏。 一个很常见的类型是堆栈缓冲区溢出。 在存储在堆栈中的数组中写入太多的数据,并用数据覆盖函数的返回地址。 当函数返回时,它跳转到伪造的返回地址,程序因为地址上没有代码而失败。 由于没有简单的方法来找出腐败发生的位置,他们将很难修复这个bug。
这是一个臭名昭着的错误,它是恶意软件的主要攻击媒介。 因为它可以指挥一个程序跳转到数据的任意代码。 你应该和这些开发人员静下来,指出这是一个重大的安全风险。 治疗很容易,他们应该更新他们的工具。 缓冲区溢出的对策最近被编入编译器 。