题
我想创建一个分配提供存储有以下特性:
- 不能呼磁盘。
- 是难以置信难以通过一个调试器的连接
这个想法是,这将包含敏感信息(如驾照信息)这应该是无法给用户。我已经做了通常的在线研究,并要求其他几个人关于这一点,但我无法找到一个好地方开始关于这个问题。
更新
Josh 提到使用 VirtualAlloc
设置保护上的存储空间。我已经创建了一个自定义的分配(如下图所示)我们发现的使用 VirtualLock
功能限制的存储量,我可以分配。这似乎是通过设计虽然。因为我使用它的小象这不是一个问题。
//
template<class _Ty>
class LockedVirtualMemAllocator : public std::allocator<_Ty>
{
public:
template<class _Other>
LockedVirtualMemAllocator<_Ty>& operator=(const LockedVirtualMemAllocator<_Other>&)
{ // assign from a related LockedVirtualMemAllocator (do nothing)
return (*this);
}
template<class Other>
struct rebind {
typedef LockedVirtualMemAllocator<Other> other;
};
pointer allocate( size_type _n )
{
SIZE_T allocLen = (_n * sizeof(_Ty));
DWORD allocType = MEM_COMMIT;
DWORD allocProtect = PAGE_READWRITE;
LPVOID pMem = ::VirtualAlloc( NULL, allocLen, allocType, allocProtect );
if ( pMem != NULL ) {
::VirtualLock( pMem, allocLen );
}
return reinterpret_cast<pointer>( pMem );
}
pointer allocate( size_type _n, const void* )
{
return allocate( _n );
}
void deallocate(void* _pPtr, size_type _n )
{
if ( _pPtr != NULL ) {
SIZE_T allocLen = (_n * sizeof(_Ty));
::SecureZeroMemory( _pPtr, allocLen );
::VirtualUnlock( _pPtr, allocLen );
::VirtualFree( _pPtr, 0, MEM_RELEASE );
}
}
};
和使用
//a memory safe std::string
typedef std::basic_string<char, std::char_traits<char>,
LockedVirtualMemAllocato<char> > modulestring_t;
Ted珀西瓦尔 提到mlock,但我没有执行。
我找到了 实际加密尼尔Furguson和布鲁斯 相当有帮助。
解决方案
你真的不能保护对存储器访问。你也许可以阻止寻呼如果作为一个管理或系统的,但是你不能阻止管理或系统从阅读你的记忆。即使你可以在某种程度上完全阻止其他进程阅读你的存储器(不能),另一个进程可能仍然实际注入新的线进入你的过程和读取存储器的方式。
即使你可以在某种程度上完全锁定您的进程和保证该OS会 从来没有 能让其他人来访问您的过程中,你仍然没有充分的保护。整个OS可能是虚拟机中运行,它可以暂停和检查,在任何时间。
你的 不能 保护记忆的内容所有者的系统。好莱坞和音乐行业已经痛苦这多年。如果这是可能的,他们已经这样做。
其他提示
Unix系统上可以使用 mlock(2) 锁定存的网页入RAM,防止他们被分页。
mlock()和mlockall()分别锁的一部分或全部呼叫 进程的虚拟地址空间成RAM,防止这从存储器 被呼叫交换的区域。
有一个限制要多少内存每个过程可以锁,它可以显示与 ulimit -l
并且是衡量千字节。在我的系统中,默认的限制32昆明植物研究,每一进程。
如果你是在开发用于Windows的,还有方法可以限制进入存储器,但绝对阻止其他人是不可行的。如果你希望保守秘密的秘密,阅读 编写安全代码 -这解决了这一问题在一些长度,但是要知道,你有没有办法知道如果你的代码被上运行的一个真正的机器或一个虚拟机。有一堆Win32API的东西到处理加密处理这种事情,包括安全储存的秘密-这本书的谈判。你可以看看在线 Microsoft CyproAPI 对于细节;OS设计师意识到这非常的问题和需要保持安全的明文(再读 编写安全代码).
Win32API功能 VirtualAlloc
是的操作系统级别的存分配器。它允许设定的接入的保护;你能做什么是组访问 PAGE_GUARD
或 PAGE_NOACCESS
, 和翻转的访问东西更加友好的话,你读取程序,并重置它之后,但这仅仅是的速度难关,如果有人想真的很难看看你的秘密。
在摘要,看着密Api在您的平台,它们将解决这一问题的更好的东西比你砍了自己。
让我们把这一点的时间:
我想创建一个其分配器 提供存储有以下 属性:
这是公平的。
* cannot be paged to disk.
那将会是困难的。就我所知,你不能禁用虚拟呼,因为它是处理由的操作系统。如果有一个办法,然后您将洞穴的深处的操作系统。
* is incredibly hard to access through an attached debugger
你可以通过运行PGP和储存加密存储和解它需要。大规模性的打击。
这个想法是,这将包含 敏感的信息(如驾照 信息)这应该是 无法给用户。我已经做了 通常的在线研究,并要求一个 其他几个人关于这一点,但我 无法找到一个好地方开始在这 问题。
保留所有敏感信息的机。严重。不要储存敏感信息的存储器。写一个自定义中删除程序会自动清除的所有数据的任何拨款的执行。绝不允许一般事访问的机器的敏感材料。如果执行数据库访问,确保所有访问是消毒之前发射。只有人民具体的登录被允许访问。没有一般的小组的访问。
在一个侧面说明,什么其他方法 那里的访问记忆 过程比其他的附加一个 调试器?
把转储存。
安装Libsodium,使用分配机制,由#包括 <sodium.h>
守卫堆分配
慢于malloc()和朋友,他们需要3或4个额外的网页上的虚拟存储器。
void *sodium_malloc(size_t size);
分配存储器中存储敏感数据的使用 sodium_malloc()
和 sodium_allocarray()
.你只需要第一个电话 sodium_init()
之前使用这些堆的警卫。
void *sodium_allocarray(size_t count, size_t size);
的 sodium_allocarray()
功能返回指从其计数的对象,是大字节的存储每个可以访问。它提供了同样的保证 sodium_malloc()
但是,还可以防止算术溢出时 count * size
超过 SIZE_MAX
.
这些职能增加保护页围绕保护的数据,使它不太可能可以在一个导致不样的情况。
此外,保护记忆的区域分配的方式可以改变使用锁定的存储器操作: sodium_mprotect_noaccess()
, sodium_mprotect_readonly()
和 sodium_mprotect_readwrite()
.
后 sodium_malloc
你可以使用 sodium_free()
解锁和释放的记忆。在这一点在实施考虑零的存储器之后使用。
零存在使用之后
void sodium_memzero(void * const pnt, const size_t len);
在使用之后,敏感数据应当复盖,但memset()以及手写的代码可以被默默地剥离出来的一个优化编译器,或通过链接器。
该sodium_memzero()function试图有效地为零len bytes开始在pnt,即使最优化适用的代码。
锁定存分配
int sodium_mlock(void * const addr, const size_t len);
的 sodium_mlock()
功能锁定至少len bytes的存在开始addr。这可以帮助避免交换敏感数据的磁盘。
int sodium_mprotect_noaccess(void *ptr);
该sodium_mprotect_noaccess()function使得一个区域分配使用sodium_malloc()或sodium_allocarray()无法访问。它不能阅读或写,但数据将被保留。这种功能可以使用机密数据无法访问,除非实际上需要一个具体的操作。
int sodium_mprotect_readonly(void *ptr);
该sodium_mprotect_readonly()功能标志着一个区域分配使用sodium_malloc()或sodium_allocarray()为只读。试图修改的数据会造成过程终止。
int sodium_mprotect_readwrite(void *ptr);
的 sodium_mprotect_readwrite()
功能标志着一个区域分配的使用 sodium_malloc()
或 sodium_allocarray()
作为可读写之后,已经使用受保护的 sodium_mprotect_readonly()
或 sodium_mprotect_noaccess()
.
什么你问的是处理在操作系统的水平。一旦数据是在你的节目,它是承担责任是调出。
访问的存储器、动机的个人可以附加的硬件调试器。
@格雷厄姆
你可以通过运行PGP和储存加密存储和解它需要。大规模性的打击。
然后你会需要的关键在存储器。这将使它有点困难的,但肯定不是不可能的。任何人的动机仍将管理获得的数据存储器中。
你最好的选择是实施类似的东西。净的SecureString类,并要非常小心,以零出任何明文数据副本,尽快完成(不要忘了清理,即使在例外情况都扔).一个很好的方式来这样做std::string而这样的使用 定义分配器.
在窗户,如果使用CryptProtectMemory(或RtlEncryptMemory为旧系统)、加密的密码存储在非页(核心?) 存储器。在我的测试,这些职能是相当不错的快速、esp。考虑到保护他们给你。
在其它系统中,我喜欢使用河豚,因为这是一个很好的组合之间的速度和强度。在后一种情况下,你将随机产生自己的密码(16+字节的熵于河豚)在程序启动。不幸的是,没有一个整体很多你能做到保护,没有密码操作系统支持的,虽然你可能使用的一般模糊处理技术来嵌入一个硬编码的盐价值纳入可执行的,你可以相结合的令(每一点帮助).
总体而言,这个战略只是一个部分的更广泛的纵深防御的方法。还记得简单的错误,例如缓冲区溢出和未消毒程序输入仍然是迄今最常见的攻击向量。
@Derek:哦,但是有可信计算,可以使用 其它存储器!:P</devils-advocate>
@。
我真希望这是可能的,我只是还没有找到它。你只是让我意识到这正是我们试图要做的只允许访问的文件的背景下,我们的程序和使保护知识产权。
我猜我必须接受的是,没有真正安全的方式存储个人的文件在另一个计算机,特别是如果在某些时候访问被允许该文件由所有者。
那是肯定的问题。你可以储存的东西的安全的只要你永远不允许访问,但只要您授予访问,你控制了。你可以使这一点更加困难,但这就是全部。
@克里斯
哦,但是有可信计算,可以使用存储器其它!:P
但你必须实际上将愿意支付用于计算机的其他人拥有。:p
@德里克公园
他只是说困难的,不是不可能的。PGP将使它更难,不是不可能的。