3

在 Windows XP 中使用一些作为 Windows 服务工作的软件并从登录屏幕重新启动我看到一条臭名昭著的错误消息

“00x...”处的指令引用了“00x...”处的内存。无法读取内存。

我向开发人员报告了问题,但再次查看消息,我发现地址是相同的。所以

“00xdf3251”处的指令引用了“00xdf3251”处的内存。无法读取内存。

这是否是程序中的错误,但内存/访问权限的状态是什么,或者阻止指令读取它所放置的内存的其他东西是什么。它是特定于服务的吗?

4

2 回答 2

2

我猜想有人试图在地址 0xdf3251 处执行指令,并且该位置没有由可读和可执行的内存页(也许完全未映射)备份。

如果是这种情况,则异常(实际上是页面错误)源自该指令,并且异常处理程序在堆栈上具有其地址(要返回的位置,以防异常可以以某种方式解决并且错误指令在执行时重新启动)处理程序返回)。这是您看到的第一个地址。

页面错误处理程序读取的CR2寄存器,即您看到的第二个地址,也具有相同的地址,因为它必须包含不可访问的内存位置的地址,而不管页面错误是否由以下原因引起:

  • 完全没有映射(根本没有映射页面)
  • 缺少写权限(页面是只读的)
  • 缺少执行权限(页面设置了不执行位)或
  • 缺乏内核权限(页面被标记为只能在内核中访问)

并且无论是在数据访问期间还是在获取指令时(后者是我们的情况)。

这就是如何使指令和内存访问地址相等。

代码很可能存在导致内存损坏的错误,并且某些指针(或堆栈上的返回地址)被指向不可访问的内存位置的虚假值覆盖。然后以一种或另一种方式指示 CPU 继续在那里执行(很可能使用以下指令之一:jmp, call, ret)。也有可能在某处出现比赛条件。

于 2012-05-03T08:59:43.557 回答
1

这种崩溃最常见的原因是堆栈损坏。一种非常常见的类型是堆栈缓冲区溢出。在存储在堆栈上的数组中写入太多数据,它会用数据覆盖函数的返回地址。然后,当函数返回时,它会跳转到虚假的返回地址,并且由于该地址处没有代码,程序会失败。他们将很难修复错误,因为没有简单的方法可以找出损坏发生的位置。

这是一种相当臭名昭著的错误,它是恶意软件的主要攻击媒介。因为它可以控制程序跳转到带有数据的任意代码。您应该与这些开发人员坐下来并指出这一点,这是一个重大的安全风险。治愈很容易,他们应该更新他们的工具。如今,针对缓冲区溢出的对策已内置于编译器中。

于 2012-05-03T10:03:02.013 回答