17

I'm trying to create a C/C++ program that dumps as much uninitialized memory as possible. The program has to be run by a local user, i.e in user mode.

It does not work to use malloc: Why does malloc initialize the values to 0 in gcc?

The goal is not to use this data as a seed for randomness.

Does the OS always make sure that you can't see "leftovers" from other processes?

If possible, I would like references to implementations or further explanation.

user144437
  • 1,063
  • 10
  • 9

4 Answers4

11

The most common multi-user operating systems (modern Windows, Linux, other Unix variants, VMS--probably all OSes with a concept of virtual memory) try to isolate processes from one another for security. If process A could read process B's leftover memory, it might get access to user data it shouldn't have, so these operating systems will clear pages of memory before they become available to a new process. You would probably have to have elevated privileges to get at uninitialized RAM, and the solution would likely depend on which operating system it was.

Embedded OSes, DOS, and ancient versions of Windows generally don't have the facilities for protecting memory. But they also don't have a concept of virtual memory or of strong process isolation. On these, just allocating memory through the usual methods (e.g., malloc) would give you uninitialized memory without you having to do anything special.

For more information on Windows, you can search for Windows zero page thread to learn about the OS thread whose only job is to write zeros in unused pages so that they can be doled out again. Also, Windows has a feature called superfetch which fills up unused RAM with files that Windows predicts you'll want to open soon. If you allocated memory and Windows decided to give you a superfetch page, there would be a risk that you'd see the contents of a file you don't have access to read. This is another reason why pages must be cleared before they can be allocated to a process.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
6

You got uninitialized memory. It contains indeterminate values. In your case those values are all 0. Nothing unexpected. If you want pseudo-random numbers use a PRNG. If you want real random numbers/entropy, use a legitimate random source like your operating system's random number device (e.g. /dev/urandom) or API.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • The goal is not to use the data for randomness. (I updated the question). Just to figure out if I can get "leftovers" from other processes. – user144437 May 07 '16 at 19:29
  • 7
    You can't. That's a fundamental part of the privilege model of any non-toy OS. – R.. GitHub STOP HELPING ICE May 08 '16 at 01:28
  • 3
    @user144437 I speculate that possibly the reason you're trying to do this has some relationship to why OSes do not allow you to do this. –  May 12 '16 at 22:26
3

No operating system in its right mind is going to provide uninitialized memory to a process.

The closest thing you are going to find is the stack. That memory will have been initialized when mapped to the process but much of it will have been overwritten.

user3344003
  • 20,574
  • 3
  • 26
  • 62
  • 3
    "No operating system in its right mind is going to provide uninitialized memory to a process." - Source? – user144437 May 07 '16 at 19:27
  • 1
    You are wrong. If you allocate memory with malloc, the memory comes with system gargabe. It's not initialized. Also, an operating system doesn't have a mind. – Luis Paulo May 14 '16 at 14:35
  • It's initialized before it goes into the the "heap" when the page is mapped to the logical address space. – user3344003 May 14 '16 at 14:38
2

It's common sense. We don't need to document that 1+1=2 either.

An operating system that leaks secrets between processes would be useless for many applications. So if a general purpose operating system that wants to be general purpose it will isolate processes. Keeping track of which pages might contain secrets and which are safe would be too much work and too error-prone, so we assume that every page that has ever been used is dirty and contains secrets. Initializing new pages with garbage is slower than initializing them with just one value, so random garbage isn't used. The most useful value is zero (for calloc or bss for example), so new pages are zeroed to clear them.

There's really no other way to do it.

There might be special purpose operating systems that don't do it and do leak secrets between processes (it might be necessary for real-time requirements for example). Some older operating systems didn't have decent memory management and privilege isolation. Also, malloc will reuse previously freed memory within the same process. Therefore malloc will be documented to contain uninitialized garbage. But that doesn't mean you'll ever be able to obtain uninitialized memory from another process on a general purpose operating system.

I guess a simple rule of thumb is: if your operating system ever asks you for a password it will not give uninitialized pages to a process and since zeroing is the only reasonable way to initialize pages, they will be zeroed.

Art
  • 19,807
  • 1
  • 34
  • 60