【问题标题】:windows - protected shared memorywindows - 受保护的共享内存
【发布时间】:2014-02-07 10:17:11
【问题描述】:

我正在寻找一种在 Windows 平台上创建共享内存块的可能性,该共享内存块对除创建共享内存块的进程之外的所有进程都具有写保护。

详细我需要以下内容:

进程 (1) 必须创建一个共享内存块并且应该能够修改缓冲区。 进程(2)应该能够打开和读取创建的共享内存块,但不能有修改内容的权限。由于安全/安全原因,这很重要。

目前我有一个解决方案,使用 CreateFileMapping() 和 MapViewOfFile() 创建共享内存块,然后在进程 (1) 和 (2) 中具有读写权限,例如:

HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, highSize, lowSize, L"uniquename");
void* sharedMemory = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
// now we can modify sharedMemory...

这两行代码可以在两个进程中应用,因为第一个进程创建共享内存块,第二个进程只是打开共享内存。 但是,由于在创建内存块期间提供的访问值(PAGE_READWRITE 和 FILE_MAP_ALL_ACCESS),显然第二个进程将具有写权限。

我需要使用访问值 PAGE_READONLY 和 FILE_MAP_READ 在进程 (1) 中创建共享内存块,但显然我不允许在进程 (1) 中初始化/设置/修改内存块,这比无用的内存缓冲区。

据我所知,安全属性的定义不能解决问题,因为我的问题不依赖于用户或组。

我什至会对这样的解决方案感到满意)。

【问题讨论】:

    标签: c++ windows shared-memory readonly protected


    【解决方案1】:

    CreateFileMapping 函数允许您为文件映射对象设置 ACL。如果您创建的 ACL 只允许只读访问,其他进程应该无法打开具有读写访问权限的文件映射对象。

    通常,在创建对象时,您分配的权限不适用于您在创建期间获得的句柄。但是,我还没有特别用CreateFileMapping 对此进行过测试。

    这只提供了较弱的保护。恶意进程可能会更改文件映射对象的权限,或将代码注入到创建对象的进程中。

    【讨论】:

      【解决方案2】:

      您没有解释为什么不能在每种情况下提供不同的参数,所以我假设您在打开文件之前不知道哪个进程是创建者。在这种情况下,您可能想尝试:

      HANDLE h = OpenFileMapping(FILE_MAP_READ, /*args*/);
      if (h) {
          v = MapViewOfFile(h, FILE_MAP_READ, 0, 0, 0);
      } else {
          h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, highSize, lowSize, L"uniquename");
          if (!h)
              FirePhotonTorpedoes();
          v = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
      }
      

      【讨论】:

      • 我可以提供不同的参数,因为我知道我是进程#1 还是进程#2。但我想确保没有其他坏人可以使用进程#3 破解我的实现,该进程只需使用PAGE_READWRITE 打开我创建的共享内存块并修改共享内存块的内容。
      • @user3208346:作为计算机的所有者,我想确保没有进程可以拒绝我写入自己的内存的能力。我付了钱,搞定了!解决方案取决于用户凭据。不要让进程 #3 以您拥有的相同权限运行。
      • @Ben 感谢您的回复。你是绝对正确的 - 但我认为 Windows API 自带的独特解决方案(因为我认为我的问题应该是一个非常常见的问题)会更好;) - 如果使用我的应用程序的人不能找到利用我的代码的可能性......(这些人以相同的权限运行我的应用程序和他们的应用程序)
      • 没有办法阻止恶意活动。您希望做的最好的事情就是让它更复杂(并且对您的过程来说更昂贵),但您无法阻止它:(
      【解决方案3】:

      您是否相信进程#2 使用FILE_MAP_READ?这将防止意外覆盖,例如破坏共享内存的野指针。

      如果您尝试防止恶意覆盖,则需要使用操作系统提供的安全主体,并在具有较少凭据的不同会话中运行进程 #2。如果进程#2 在与进程#1 相同的安全凭证下运行,那么它可以执行进程#1 可以执行的任何操作(例如,通过将代码注入进程#1)。

      (在 Windows 上,用户是安全主体,而进程不是。用户不是唯一的限制级别,例如,Vista 和更高版本中的用户访问控制会创建与具有和不具有管理员组成员身份的管理用户相对应的令牌)

      既然您说进程#1 不需要继续写入访问,那么只需一次,您可以创建映射,将其映射为写入,然后使用SetSecurityInfo 调整 ACL,以便以后的访问无法写入。

      另一种可能性是映射一个磁盘文件,并使用第一个进程的FILE_SHARE_READ(但不是FILE_SHARE_WRITE)访问权限打开它。

      但是这些都不能阻止进程#2 强制进程#1 代表它进行更改。只有使用单独的令牌才能防止强制。

      【讨论】:

      • 上述基于 SetSecurityInfo() 的解决方案并不能完全解决问题 - 此调用与部分/映射创建之间存在竞争条件
      • @Bukes:SetSecurityInfo() 解决方案根本没有解决问题,因为进程#2 可以使用WriteProcessMemory(PROCESS1_HANDLE, ...) 访问共享部分。这些方法只能防止事故发生。为了强制安全,必须使用操作系统支持的主体(用户和组成员)。
      • @Ben 我也考虑过使用磁盘文件的可能性,但我想找到一个避免访问磁盘的解决方案......
      • @user3208346:我已经给你了。 TL;DR 版本:如果您信任进程 #2,请让它使用 FILE_MAP_READ 以防止意外覆盖。如果您不信任进程 #2,请以更受限制的用户身份运行它。
      • @BenVoigt:我也有类似的问题。不幸的是,您的回答表明,在我的情况下,可能无法让我的程序在 Windows 上安全。你能看看吗?我有与上述过程相对应的程序 1 和程序 2。然后我想让两个用户,让我们妈妈和爸爸同时运行程序1和2。在这种情况下,我相信程序1需要创建一个前缀为Local的文件映射,以防止妈妈和爸爸的程序1实例写入进入同一个共享区域。所以程序 1 不能由第三个额外的用户运行,这将为它提供一个特殊的安全级别
      猜你喜欢
      • 2012-02-09
      • 2012-06-14
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 2013-05-20
      • 2011-01-29
      相关资源
      最近更新 更多