views:

888

answers:

12

I want to create an allocator which provides memory with the following attributes:

  • cannot be paged to disk.
  • is incredibly hard to access through an attached debugger

The idea is that this will contain sensitive information (like licence information) which should be inaccessible to the user. I have done the usual research online and asked a few other people about this, but I cannot find a good place start on this problem.

Updates

Josh mentions using VirtualAlloc to set protection on the memory space. I have created a custom allocator ( shown below ) I have found the using the VirtualLock function it limits the amount of memory I can allocate. This seems to be by design though. Since I am using it for small objects this is not a problem.

//
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 );
  }
 }
};

and is used

 //a memory safe std::string
 typedef std::basic_string<char, std::char_traits<char>, 
                           LockedVirtualMemAllocato<char> > modulestring_t;

Ted Percival mentions mlock, but I have no implementation of that yet.

I found Practical Cryptography by Neil Furguson and Bruce Schneier quite helpful as well.

+2  A: 

What you are asking for is handled at the OS level. Once the data is in your program, it is liable to be paged out.

For accessing the memory, a motivated individual can attach a hardware debugger.

Mark Harrison
+4  A: 

Let's take this a bit at a time:

I want to create an allocator which provides memory with the following attributes:

That's fair enough.

* cannot be paged to disk.

That's going to be hard. As far as I am aware, you cannot disable Virtual Paging as it is handled by the OS. If there is a way, then you'll be seplunking in the bowels of the OS.

* is incredibly hard to access through an attached debugger

You could run it through PGP and store it encrypted in memory and unencrypt it as needed. Massive performance hit.

The idea is that this will contain sensitive information (like licence information) which should be inaccessible to the user. I have done the usual research online and asked a few other people about this, but I cannot find a good place start on this problem.

Keep all sensitive information off the machine. Seriously. Don't store sensitive information in memory. Write a custom delete routine that will automatically remove all data from any allocations you perform. Never allow general access to a machine with sensitive material on it. If you perform db access, make sure all access is sanitized before firing. Only people with specific log-ins are allowed to access. No general group access.

On a side note, what other methods are there of accessing the memory of a process other than attaching a debugger?

Taking a dump of the memory.

graham.reeds
+11  A: 

You can't really protect against memory access. You can probably prevent paging if you are running as an admin or as the system, but you cannot prevent the admin or system from reading your memory. Even if you could somehow completely block other processes from reading your memory (which you can't), another process could still actually inject a new thread into your process and read the memory that way.

Even if you could somehow completely lock down your process and guarantee that the OS would never allow anyone else to access your process, you still don't have full protection. The entire OS could be running in a virtual machine, which could be paused and inspected at any time.

You cannot protect memory contents from the owner of the system. Hollywood and the music industry have been aching for this for years. If it were possible, they'd already be doing it.

Derek Park
A: 

@graham

You could run it through PGP and store it encrypted in memory and unencrypt it as needed. Massive performance hit.

Then you'd have to hold the key in memory. That would make it a little harder, but definitely not impossible. Anyone motivated will still manage to get the data from memory.

Derek Park
A: 

@derek

You cannot protect memory contents from the owner of the system. Hollywood and the music industry have been aching for this for years. If it were possible, they'd already be doing it.

I was really hoping that is was possible, and that I just hadn't found it yet. Your example just made me realise that that is exactly what we are trying to do - only allow access to files in the context of our program and so preserve the IP.

I guess I have to accept that there is no truly secure way to store someone’s files on another computer, especially if at some point access is allowed to that file by the owner.

roo
A: 

@Derek: Oh, but with trusted computing, you can use memory curtaining! :-P</devils-advocate>

Chris Jester-Young
A: 

@roo

I was really hoping that is was possible, and that I just hadn't found it yet. Your example just made me realise that that is exactly what we are trying to do - only allow access to files in the context of our program and so preserve the IP.

I guess I have to accept that there is no truly secure way to store someone’s files on another computer, especially if at some point access is allowed to that file by the owner.

That's definitely the problem. You can store something securely so long as you never grant access, but as soon as you grant access, your control is gone. You can make it a little bit more difficult, but that's all.

Derek Park
A: 

@Chris

Oh, but with trusted computing, you can use memory curtaining! :-P

But then you have to actually be willing to pay for a computer someone else owns. :p

Derek Park
A: 

@Derek Park

He only said harder, not impossible. PGP would make it harder, not impossible.

graham.reeds
+4  A: 

If you're developing for Windows, there are ways you can restrict access to memory, but absolutely blocking out others is not doable. If you're hoping to keep a secret secret, read Writing Secure Code - which addresses this problem at some length, but be aware that you have no way of knowing if your code is running on a real machine or a virtual machine. There's a bunch of Win32 API stuff to deal with crypto that handles this kind of thing, including safe storage of secrets - the book talks about that. You can look at the online Microsoft CyproAPI for details; the OS designers recognise this very problem and the need to keep the cleartext secure (again, read Writing Secure Code).

The Win32 API function VirtualAlloc is the OS level memory allocator. It allows you to set access protection; what you could do is set access to PAGE_GUARD or PAGE_NOACCESS, and flip the access to something friendlier while your program reads, and reset it afterward, but that's merely a speed hump if someone is trying really hard to peek at your secret.

In summary, look at the crypto APIs on your platform, they'll address the problem better than something you hack up yourself.

Josh
CryptProtectMemory, is another API call that may help. I'm not sure exactly what it does, but the advertised behavior to stop other processes from reading the page.
caspin
+3  A: 

On Unix systems you can use mlock(2) to lock memory pages into RAM, preventing them being paged.

mlock() and mlockall() respectively lock part or all of the calling process’s virtual address space into RAM, preventing that memory from being paged to the swap area.

There is a limit to how much memory each process can lock, it can be shown with ulimit -l and is measured in kilobytes. On my system, the default limit is 32 kiB per process.

Ted Percival
A: 

You cannot protect memory contents from the owner of the system. Hollywood and the music industry have been aching for this for years. If it were possible, they'd already be doing it.

Have you had a look at Vista (and above) Protected Processes (http://www.microsoft.com/whdc/system/vista/process_vista.mspx). I believe the Operating System enforced protection is courtesy of the entertainment industry.

Jeffrey Walton