按照这里的讨论,如果你想有一个安全的类来在内存上存储敏感信息(例如密码),你必须:
- memset/在释放内存之前清除内存
- 重新分配也必须遵循相同的规则——不要使用 realloc,而是使用 malloc 创建一个新的内存区域,将旧内存复制到新内存,然后在最终释放之前 memset/clear 旧内存
所以这听起来不错,我创建了一个测试类来看看这是否有效。所以我做了一个简单的测试用例,我不断添加单词“LOL”和“WUT”,然后在这个安全缓冲区类中添加一个数字大约一千次,销毁该对象,然后最终执行导致核心转储的操作。
由于该类应该在销毁之前安全地清除内存,因此我不应该能够在 coredump 上找到“LOLWUT”。但是,我还是设法找到了它们,并想知道我的实现是否只是错误。但是,我使用 CryptoPP 库的 SecByteBlock 尝试了同样的事情:
#include <cryptopp/osrng.h>
#include <cryptopp/dh.h>
#include <cryptopp/sha.h>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/filters.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using namespace std;
int main(){
{
CryptoPP::SecByteBlock moo;
int i;
for(i = 0; i < 234; i++){
moo += (CryptoPP::SecByteBlock((byte*)"LOL", 3));
moo += (CryptoPP::SecByteBlock((byte*)"WUT", 3));
char buffer[33];
sprintf(buffer, "%d", i);
string thenumber (buffer);
moo += (CryptoPP::SecByteBlock((byte*)thenumber.c_str(), thenumber.size()));
}
moo.CleanNew(0);
}
sleep(1);
*((int*)NULL) = 1;
return 0;
}
然后编译使用:
g++ clearer.cpp -lcryptopp -O0
然后启用核心转储
ulimit -c 99999999
但是,启用核心转储并运行它
./a.out ; grep LOLWUT core ; echo hello
给出以下输出
Segmentation fault (core dumped)
Binary file core matches
hello
这是什么原因造成的?由于 SecByteBlock 的追加引起的重新分配,应用程序的整个内存区域是否重新分配了?
编辑:使用 vim 检查核心转储后,我得到了这个:http: //imgur.com/owkaw
edit2:更新了代码,使其更容易编译,以及编译说明
最终编辑3:看起来 memcpy 是罪魁祸首。请参阅 Rasmusmymemcpy
在下面的回答中的实施。