Garmekain
Garmekain

Reputation: 319

Know if the value of a memory address can be retrieved

I'm trying to get the values stored in my computer's memory addresses. For that, I've written a little C++ program, but it throws a Read access violation error when trying to get the value stored in the address 0x1.

The goal here is to get the values that can be retrieved, not the ones that can't.

Anyways, here's the code:

#include <iostream>
#include <conio.h>

using namespace std;

int main() {
    unsigned long long *ptr1;
    for (unsigned long long i = 0; i < 0xFFFFFFFF; i++)
    {
        try {
            ptr1 = reinterpret_cast<unsigned long long*>(i);
        }
        catch (...) {
            cout << "Some erros happened" << endl;
        }

        if (ptr1 != nullptr) {
            try {
                cout << "Value in address 0x" << i << ": " << *ptr1 /*Error here*/ << endl;
            }
            catch(...) {
                cout << "Some erros happened" << endl;
            }
        }
        else {
            cout << "Value in address 0x" << i << ": null pointer" << endl;
        }

    }
    _getch();
    return 0;
}

Note that in the first iteration of the for loop the program detects that ptr1 is a null pointer but in the second one, the program crashes when it gets to *ptr1.

If I'm not mistaken, I think the error comes from *ptr1 not being able to read what's stored in that address, but I don't know how to know that without actually referencing ptr1.

Apparently, the try catch blocks cannot be used in this situation.

By the way, this is the output of the program:

Value in address 0x0: null pointer Value in address 0x1:

Then it throws the error.

Upvotes: 1

Views: 511

Answers (3)

PcAF
PcAF

Reputation: 2007

I played around with signals and catching SIGSEGV. Note that this example is very (I'm saying again, very) bad example, it isn't even legal (in terms of C(++) standard), but it just Works™. I tested it with 2 (local) variables and it seems to work.

Also, don't forget that this won't print values in your (physical) memory. Usually, your program gets a virtual address space where virtual address doesn't have to match with physical address. So, you won't see contents of memory addresses of other processes, you'll see only yours.

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <conio.h>


jmp_buf jumpBuffer;

void sig(int ignore)
{
    signal(SIGSEGV,sig); //to prevent reseting signal action back to SIG_DFL (default)
    longjmp(jumpBuffer,1); //jump back to setjmp() and correct our mistakes
}

int main()
{
    signal(SIGSEGV,sig);

    unsigned int a = 0x123456;
    unsigned int b = 0x876543;

    printf("a (%x) resides at %p \n",a,&a);
    printf("b (%x) resides at %p \n",b,&b);
    getch();

    static const long max = 0xFFFFFFFF;
    int *i = 0; //This is tricky, null pointer constant doesn't need to be represented as zero
    for (;(long)i < max;i++) //these pointer-to-integer casts are also implementation-specific
    {

        //if jmp was made to setjmp, returned value is specified as second parameter in longjmp
        //if this is regular call, not jump, returned value is zero
        if (setjmp(jumpBuffer) == 0) 
            printf("Address %p contains %x \n",i,*i); //if this fails, SIGSEGV is raised and sent to our handler
        else
            printf("Address %p is invalid \n",i);

    }
}

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726639

There is no technique to do it in a way that is legal from the C++ standard's point of view. According to the standard, the only way to know that a memory location can be accessed is to make sure that it has been allocated to your program. In other words, your pointer needs to point to an address of one of your global / static / local variables, or a block that has been allocated using malloc functions.

All other addresses are off-limits to your program. If you access them, your system is allowed to do anything it wants, from returning invalid values to terminating the program.

Upvotes: 3

sameerkn
sameerkn

Reputation: 2259

for (unsigned long long i = 0; i < 0xFFFFFFFF; i++) from this for loop it seems that you are trying to access complete virtual address space of process.

So you can try by first finding the page size used in process. Then you can try Locking that page. Some APIs are available in Windows. Depending upon the result you will come to know which range of addresses are restricted.

VirtualLock function

Upvotes: 0

Related Questions