Clearing memory securely and reallocations(安全清除内存并重新分配)
问题描述
如果您想参加安全课程,请在此处进行讨论要将敏感信息(例如密码)存储在内存中,您必须:
Following the discussion here, if you want to have a secure class for storing sensitive information (e.g passwords) on memory, you have to:
- memset/clear the memory before free it
- 重新分配也必须遵循相同的规则 - 不要使用 realloc,而是使用 malloc 创建一个新的内存区域,将旧内存复制到新内存,然后 memset/clear 旧内存,然后最终释放它
所以这听起来不错,我创建了一个测试类来看看它是否有效.所以我做了一个简单的测试用例,我不断添加单词LOL"和WUT",然后在这个安全缓冲区类中添加一个数字大约一千次,销毁该对象,然后最终执行导致核心转储的操作.
So this sounds good, and I created a test class to see if this works. So I made a simple test case where I keep adding the words "LOL" and "WUT", followed by a number to this secure buffer class around a thousand times, destroying that object, before finally doing something that causes a core dump.
由于该类应该在销毁之前安全地清除内存,因此我不应该能够在 coredump 上找到LOLWUT".但是,我还是设法找到了它们,并想知道我的实现是否只是错误.但是,我使用 CryptoPP 库的 SecByteBlock 尝试了同样的事情:
Since the class is supposed to securely clear the memory before the destruction, I'm not supposed to be able to find a "LOLWUT" on the coredump. However, I managed to find them still, and wondered if my implementation is just buggy. However, I tried the same thing using CryptoPP library's 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
然后,启用核心转储并运行它
But then, enabling core dump and running it
./a.out ; grep LOLWUT core ; echo hello
给出以下输出
Segmentation fault (core dumped)
Binary file core matches
hello
这是什么原因造成的?由于 SecByteBlock 的 append 引起的重新分配,应用程序的整个内存区域是否重新分配?
What is causing this? Did the whole memory region for the application realloc itself, because of the reallocation caused by SecByteBlock's append?
另外,这是 SecByteBlock 的文档
edit:使用 vim 检查核心转储后,我得到了这个:http://imgur.com/owkaw
edit: After checking the core dump using vim, I got this: http://imgur.com/owkaw
edit2:更新了代码,使其更易于编译,以及编译说明
edit2: updated code so it's more readily compilable, and compilation instructions
final edit3:看起来 memcpy 是罪魁祸首.请参阅 Rasmus 在下面的答案中的 mymemcpy
实现.
final edit3: It looks like memcpy is the culprit. See Rasmus' mymemcpy
implementation on his answer below.
推荐答案
这是另一个更直接地重现问题的程序:
Here is another program that reproduces the problem more directly:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
inline void SecureWipeBuffer(char* buf, size_t n){
volatile char* p = buf;
asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory");
}
void mymemcpy(char* b, const char* a, size_t n){
char* s1 = b;
const char* s2= a;
for(; 0<n; --n) *s1++ = *s2++;
}
int main(){
const size_t size1 = 200;
const size_t size2 = 400;
char* b = new char[size1];
for(int j=0;j<size1-10;j+=10){
memcpy(b+j, "LOL", 3);
memcpy(b+j+3, "WUT", 3);
sprintf((char*) (b+j+6), "%d", j);
}
char* nb = new char[size2];
memcpy(nb, b, size1);
//mymemcpy(nb, b, size1);
SecureWipeBuffer(b,size1);
SecureWipeBuffer(nb,size2);
*((int*)NULL) = 1;
return 0;
}
如果您将 memcpy
替换为 mymemcpy
或使用较小的尺寸,问题就会消失,所以我最好的猜测是内置 memcpy 会留下部分复制数据在内存中.
If you replace memcpy
with mymemcpy
or use smaller sizes the problem goes away, so my best guess is that the builtin memcpy does something that leaves part of the copied data in memory.
我想这只是表明从内存中清除敏感数据实际上是不可能的,除非它是从头开始设计到整个系统中的.
I guess this just shows that clearing sensitive data from memory is practically impossible unless it is designed into the entire system from scratch.
这篇关于安全清除内存并重新分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:安全清除内存并重新分配
基础教程推荐
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- C++,'if' 表达式中的变量声明 2021-01-01
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 设计字符串本地化的最佳方法 2022-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17