Getting RAX Register in C/C++ or coders that should be killed ;)

Just a weird story, suppose I need to get the value of RAX register in x64 inside some function I wrote.
I was using Visual Studio and as you might know in x64 you are not allowed to use the declspec(naked) or the inline __asm keyword anymore, what a shame. So obviously, I could write some .asm file and link it in. But I prefered to come up with more elegant idea. Anyway, I just wanna show you the solution.

if I set up a function such as:
uint64_t getRax() { }
An empty function which doesn’t do anything. The compiler will shout at me that it cannot compile such a function because there’s no any return statement. What a shame. But suppose we could compile that function, we could then just call it and it would immediately return to the caller without doing anything, then we could read the return value, which wasn’t changed cause the function is empty, thus we could get RAX. Following so far?

A single cast should do the trick. So first, we will have to change the function into:
void getRax() { }
Now the compiler will actually compile it. And now we will add a new pointer to a function that returns an actual uint64_t.

Defining a pointer to a function as follows:
uint64_t (*_getRax)()) = getRax;
But that wouldn’t compile as well, because the compiler is smart enough to know that we are messing up with types here. We will either end up with a warning or an error, too bad. As we know everything can be casted to void* and that’s why we need to cast through void* for success, such as:
uint64_t (*_getRax)() = (void*) getRax;

This way we got rid off the warnings when using W3/4 or treat warning as errors, the way I usually work. Though I could also disable the warning for the region of that fugly code. However, this is one of the reasons C/C++ is probably one of the strongest programming languages, this flexibility…
Surprisingly, I just found that GCC is more permissive in this case than VS.

And then we can simply use it:
uint64_t rax = _getRax();

I wish this could also work:
unsigned char getRax[] = { 0xc3 };
uint64_t (*_getRax)() = (void*) getRax;
But obviously since DEP is enabled nowadays, it will fail with an awful death :(

It really bothers me that I have to CALL to a RET in order to get RAX accessible in C, LOL. Anyone aware of any intrinsic to do similar things with registers? For some reason I remember something like __EAX in VS, but I couldn’t find it.

7 Responses to “Getting RAX Register in C/C++ or coders that should be killed ;)”

  1. Vasili says:

    Switch to Mingw. It has no trouble gettng any registers any time.

  2. Michael says:

    Probably already aware of this… but:

    It doesn’t do basic registers, sadly, but here’s a list of VS2010 compiler intrinsics.

    Useful for device driver development or, perhaps, OS dev!

  3. sylvainulg says:

    Sorry if that sounds dull and stupid (only used GCC as a C/C++ compiler over the last 10 years :/), but … can’t you just define the getRAX() function in assembly in a separate unit ?

  4. airmax says:

    It’s also possible to retrieve any register by using GetThreadContext.
    Probably you know this :)

  5. arkon says:

    Vasili – Sometimes I can’t choose the compiler.
    Michael – As I said, I didn’t find anything like that.
    Sylvainulg – I mentioned such an option in the beginning of the post, but I didn’t want to do it.
    Airmax – Yes, but I was whining about a CALL instruction, now you’re saying I should go all the way to kernel. And by the time you reach to the actual code that gets the context, EAX will be different.

  6. Lee says:

    I remember back in cc you could just do something like int eax = (int(*)()”\xc3″)();

  7. Lee says:

    Actually, having finished reading the last part of your post, I found it a little disturbing that DEP didn’t catch the last bit

Leave a Reply