views:

1049

answers:

6

For my bachelor thesis i want to visualize the data remanence of memory and how it persists after rebooting a system.

I had the simple idea to mmap a picture to memory, shut down my computer, wait x seconds, boot the computer and see if the picture is still there.

int mmap_lena(void)
{
    FILE *fd = NULL;
    size_t lena_size;
    void *addr = NULL;

    fd = fopen("lena.png", "r");

    fseek(fd, 0, SEEK_END);
    lena_size = ftell(fd);

    addr = mmap((void *) 0x12345678, (size_t) lena_size, (int) PROT_READ, (int) MAP_SHARED, (int) fileno(fd), (off_t) 0);
    fprintf(stdout, "Addr = %p\n", addr);
    munmap((void *) addr, (size_t) lena_size);
    fclose(fd);
    fclose(fd_log);
    return EXIT_SUCCESS;
}

I ommitted checking return values for clarities sake.

So after the mmap i tried to somehow get the address, but i usually end up with a segmentation fault as to my understanding the memory is protected by my operating system.

int fetch_lena(void)
{
    FILE *fd = NULL;
    FILE *fd_out = NULL;
    size_t lenna_size;
    FILE *addr = (FILE *) 0x12346000;

    fd = fopen("lena.png", "r");
    fd_out = fopen("lena_out.png", "rw");

    fseek(fd, 0, SEEK_END);
    lenna_size = ftell(fd);

    // Segfault 
    fwrite((FILE *) addr, (size_t) 1, (size_t) lenna_size, (FILE *) fd_out);

    fclose(fd);
    fclose(fd_out);

    return 0;

}

Please also note that i hard coded the adresses in this example, so whenever you run mmap_lena the value i use in fetch_lena could be wrong as the operating system takes the first parameter to mmap only as a hint (on my system it always defaults to 0x12346000 somehow).

If there is any trivial coding error i am sorry as my C skills have not fully developed.

I would like to now if there is any way to get to the data i want without implementing any malloc hooks or memory allocator hacks.

Thanks in advance, David

+13  A: 

One issue you have is that you are getting back a virtual address, not the physical address where the memory resides. Next time you boot, the mapping probably won't be the same.

This can definitly be done within a kernel module in Linux, but I don't think there is any sort of API in userspace you can use.

If you have permission ( and I assume you could be root on this machine if you are rebooting it ), then you can peek at /dev/mem to see the actual phyiscal layout. Maybe you should try sampling values, reboot, and see how many of those values persisted.

Chris Arguin
Thank you, i had not in mind that the virtual memory mapping was a problem too.I am somehow unsure how use /dev/mem to get the information i want, so i guess i will have to write a kernel module.
tr9sh
Maybe try to mmap /dev/mem and then seek to the position you want to look at?
Johannes Schaub - litb
I'll agree with Chris: you're going to need to use some kind of OS (or no OS at all) that gives you direct, unrestricted access to RAM. If you boot back into Linux or any other OS with protected virtual memory, you can't get any guarantee that you'll have access to the same pages of memory. If you want something easy to use, how about rebooting into an old version of DOS?
Barry Brown
+5  A: 

There is a similar project where a cold boot attack is demonstrated. The source code is available, maybe you can get some inspiration there.

However, AFAIR they read out the memory without loading an OS first and therefore do not have to mess with the OSs memory protection. Maybe you should try this too to avoid memory being overwritten or cleared by the OS after boot.

(Also check the video on the site, it's pretty impressive ;)

rodion
In fact i know their work pretty well as my thesis is partly about their work :) They describe very innovative ways to obtain a memory image, but I don't think that they describe how to extract specific memory ranges from a system. (I haven't looked in the bootloader code though)Thank you for the hint!
tr9sh
+1  A: 

I'm not familiar with Linux, but you'll likely need to write a device driver. Device drivers must have some way to convert virtual memory addresses to physical memory addresses for DMA purposes (DMA controllers only deal with physical memory addresses). You should be able to use those interfaces to deal directly with physical memory.

Michael Burr
+2  A: 

Your test code looks odd

FILE *addr = (FILE *) 0x12346000;
fwrite((FILE *) fd_out, (size_t) 1, (size_t) lenna_size, (FILE *) addr);

You can't just cast an integer to a FILE pointer and expect to get something sane. Did you also switch the first and last argument to fwrite ? The last argument is supposed to be the FILE* to write to.

nos
I have fixed the fwrite error, probably happend during copy-pasting the code. As for the cast you are right, i guess i have to find a workaround for that too!Thanks for the fix!
tr9sh
+2  A: 

In this question we worked out most of the fundamentals needed to accomplish this. Note, mmap() is not the answer to this for exactly the reasons that were stated by others .. you need a real address, not virtual, which you can only get inside the kernel (or by writing a driver to relay one to userspace).

The simplest method would be to write a character device driver that can be read or written to, with an ioctl to give you a valid start or ending address. Again, if you want pointers on the memory management functions to use in the kernel, see the question that I've linked to .. most of it was worked out in the comments in the first (and accepted) answer.

Tim Post
+1  A: 

You probably want as little OS as possible for this purpose; the more software you load, the more chances of overwriting something you want to examine.

DOS might be a good bet; it uses < 640k of memory. If you don't load HIMEM and instead write your own (assembly required) routine to jump into pmode, copy a block of high memory into low memory, then jump back into real mode, you could write a mostly-real-mode program which can dump out the physical ram (minus however much the BIOS, DOS and your app use). It could dump it to a flash disc or something.

Of course the real problem may be that the BIOS clears the memory during POST.

MarkR