缓冲区溢出到不同的 exe 内存中?或者从远程桌面程序到 csrss.exe?
Buffer Overflow into a different exe's memory? Or onto csrss.exe from a remote desktop prog?
简短,问题形式:
我进行了一些谷歌搜索,但无法得出这个问题的答案:是否可以将溢出内存缓冲到另一个 exe 的内存中? And/or,是否可以从远程桌面会话中的 exe 运行 溢出 csrss.exe 的内存?
长话短说 - 这是我们的情况:
我们有一台服务器,其始终具有 运行 远程桌面会话,该会话具有 24/7 程序 运行 - C++ .exe。更糟糕的是,C++ exe 是使用各种不安全的内存操作(原始 strcpy、sprintf 等)编写的。你不需要告诉我这在结构上有多糟糕——我完全同意。
最近,我们的服务器出现蓝屏死机,转储文件显示 csrss.exe 正在被我们的 C++ exe 终止(这将导致蓝屏,csrss.exe 也负责用于管理远程桌面会话。
所以我想知道是否有人知道一个应用程序是否可能发生内存缓冲区溢出并溢出到另一个应用程序的内存中 space,或者是否有可能远程桌面会话这样做到 csrss.exe?
如有任何帮助,我们将不胜感激!
简答不,不是。
原因的简单解释。每个程序 运行 都在它自己的虚拟地址 space 中。这个虚拟地址 space 由页面 table 控制,它本质上是一个查找 table 将虚拟地址(executable 指针中的地址)映射到物理内存地址。当 OS 切换到任务时,它会将正确的 table 交给 cpu/core 运行 任务。此 table 中未提及的任何物理地址都无法从程序访问。属于另一个应用程序的物理地址不应出现在此 table 中,因此无法访问属于另一个应用程序的内存。当程序行为不当并访问无效的内存位置时,它将尝试使用 table 中未提及的虚拟地址。这将触发 cpu 上的 exception/fault,通常在 windows 中报告为 "Access violation"。
当然 OS 和 CPU 可能包含错误,因此无法保证它不会发生。但是,如果您的 C++ 程序行为不当,那么在大多数情况下,这仍然会被 CPU 捕获并报告为访问冲突,而不会导致 BSOD。如果您没有看到您的 C++ 程序生成访问冲突,我认为问题更有可能是由错误的内存或错误的驱动程序引起的(驱动程序 运行 具有更高的权限并且可以执行普通程序可以执行的操作't).
我会说首先使用像 memtest86 这样的程序进行广泛的内存测试。顺便说一句,如果服务器是具有 ECC 内存的 "real" 服务器,则内存故障不应该是问题,因为这应该由系统报告。
更新
内存访问如何发生下溢、溢出、未初始化的指针都无关紧要。使用的虚拟地址要么映射到为程序保留的物理内存位置,要么根本不映射。顺便说一句,检查是由 CPU 完成的 OS 只维护用于查找的 tables。
然而,这并不意味着程序的每个错误都会被检测到,因为只要它正在访问为其分配内存的地址,就 CPU 而言,访问就可以了。您程序中的堆管理器可能不这么认为,但无法检测到这一点。因此,即使地址末尾的缓冲区溢出 space 也不会总是导致访问冲突,因为内存以至少 4kB 的页面分配给程序,并且堆管理器将这些页面细分为程序要求的更小的块为了。因此,您的 10 字节小缓冲区可以位于此类页面的开头,就 cpu 而言,向其中写入一千个字节就可以了。因为所有这些内存都是为程序使用而设置的。但是,当您的 10 字节缓冲区位于页面末尾并且下一个条目未分配给物理地址位置时,将发生访问冲突。
简短,问题形式:
我进行了一些谷歌搜索,但无法得出这个问题的答案:是否可以将溢出内存缓冲到另一个 exe 的内存中? And/or,是否可以从远程桌面会话中的 exe 运行 溢出 csrss.exe 的内存?
长话短说 - 这是我们的情况:
我们有一台服务器,其始终具有 运行 远程桌面会话,该会话具有 24/7 程序 运行 - C++ .exe。更糟糕的是,C++ exe 是使用各种不安全的内存操作(原始 strcpy、sprintf 等)编写的。你不需要告诉我这在结构上有多糟糕——我完全同意。
最近,我们的服务器出现蓝屏死机,转储文件显示 csrss.exe 正在被我们的 C++ exe 终止(这将导致蓝屏,csrss.exe 也负责用于管理远程桌面会话。
所以我想知道是否有人知道一个应用程序是否可能发生内存缓冲区溢出并溢出到另一个应用程序的内存中 space,或者是否有可能远程桌面会话这样做到 csrss.exe?
如有任何帮助,我们将不胜感激!
简答不,不是。
原因的简单解释。每个程序 运行 都在它自己的虚拟地址 space 中。这个虚拟地址 space 由页面 table 控制,它本质上是一个查找 table 将虚拟地址(executable 指针中的地址)映射到物理内存地址。当 OS 切换到任务时,它会将正确的 table 交给 cpu/core 运行 任务。此 table 中未提及的任何物理地址都无法从程序访问。属于另一个应用程序的物理地址不应出现在此 table 中,因此无法访问属于另一个应用程序的内存。当程序行为不当并访问无效的内存位置时,它将尝试使用 table 中未提及的虚拟地址。这将触发 cpu 上的 exception/fault,通常在 windows 中报告为 "Access violation"。
当然 OS 和 CPU 可能包含错误,因此无法保证它不会发生。但是,如果您的 C++ 程序行为不当,那么在大多数情况下,这仍然会被 CPU 捕获并报告为访问冲突,而不会导致 BSOD。如果您没有看到您的 C++ 程序生成访问冲突,我认为问题更有可能是由错误的内存或错误的驱动程序引起的(驱动程序 运行 具有更高的权限并且可以执行普通程序可以执行的操作't).
我会说首先使用像 memtest86 这样的程序进行广泛的内存测试。顺便说一句,如果服务器是具有 ECC 内存的 "real" 服务器,则内存故障不应该是问题,因为这应该由系统报告。
更新 内存访问如何发生下溢、溢出、未初始化的指针都无关紧要。使用的虚拟地址要么映射到为程序保留的物理内存位置,要么根本不映射。顺便说一句,检查是由 CPU 完成的 OS 只维护用于查找的 tables。
然而,这并不意味着程序的每个错误都会被检测到,因为只要它正在访问为其分配内存的地址,就 CPU 而言,访问就可以了。您程序中的堆管理器可能不这么认为,但无法检测到这一点。因此,即使地址末尾的缓冲区溢出 space 也不会总是导致访问冲突,因为内存以至少 4kB 的页面分配给程序,并且堆管理器将这些页面细分为程序要求的更小的块为了。因此,您的 10 字节小缓冲区可以位于此类页面的开头,就 cpu 而言,向其中写入一千个字节就可以了。因为所有这些内存都是为程序使用而设置的。但是,当您的 10 字节缓冲区位于页面末尾并且下一个条目未分配给物理地址位置时,将发生访问冲突。