Need help understanding ida pseudocode - c++

I am new to reversing. I have stumbled upon a line of code which I am unable to understand.
return (*(_int64(**)(void))(**(_QWORD **)(v1 + 0x3C8) + 0x68LL ))();
The code is for arm64 lib. So , what I understood is that it's returning a pointer out as unsigned int64 data type. But , when I try to use it as ,
return (unsigned long) ((unsigned long)(v1 + 0x3C8) + 0x68) ;
, the result is so out of the unsigned long range , for example one result is 19985131375820901. Also , _int64 and _QWORD both have the size of 8 bytes and so does unsigned long. So I am a little confused here how is this happening. Can anybody help with the correct interpretation of this pls ?

v1 + 0x3C8
Yes. This adds 0x3C8 to v1. But you seemed to have overlooked something else that happens before 0x68 gets added to it.
(_QWORD **)
The result of this addition gets casted to a pointer to a pointer to a _QWORD. That's what this means in C++.
**
And dereferenced. Twice. That produces a _QWORD, from somewhere. Wherever those pointers lead to.
+0x68LL
And only then does 0x68 gets added to whatever you have now.
But you're not done yet. There's still more C++ code left that you need to unravel.
(_int64(**)(void))
This gets now casted to a pointer to a pointer to a function that takes no parameters and returns an _int64.
*
And the pointer dereferenced.
()
And the function call is finally made, which returns an _int64 value.

Related

Using Address as scalar value

I am trying to understand some legacy code using AfxBeginThread.
To my understanding LPVOID is defined as a pointer to a void object. I have this function:
Start(LPVOID pParam){
...
int iTemp = (int)pParam;
...
}
And then the call:
int ch1 = 1;
AfxBeginThread(Start(), (LPVOID)ch1);
I am getting the following compiler warning when compiling for 64bit:
warning C4312: 'type cast': conversion from 'int' to 'LPVOID' of greater size
I am
not 100% sure this is a proper use of a pointer
to avoid the warning, I could use a helper function like (LPVOID) PtrToInt(ch1), but that doesn't look right to me as well
Could anyone help me understand the mechanics behind this? I've been trying to find an example online which uses AfxBeginThread in a similar fashion but failed so far.
MS states:
The parameter is a single value. The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. The controlling function can interpret this value in any manner it chooses. It can be treated as a scalar value or a pointer to a structure containing multiple parameters, or it can be ignored.
This warning occurs because you are compiling on a 64 bit machine where sizeof(void*) is 8 bytes but sizeof(int) is 4.
A proper way to handle this would be to use an integer type for ch1 which is the same size as a void pointer. This is the exact use case for intptr_t.
And so, it should be safe if you use ìntptr_t to hold the ch1 variable. See also this question: C++: Is it safe to cast pointer to int and later back to pointer again?
not 100% sure this is a proper use of a pointer
You have the right hunch. No, it is not proper use of a pointer.
You can pass a pointer to the function.
int ch1 = 1;
int* ptr = &ch1;
AfxBeginThread(Start(), ptr);

C++ pointer syntax problems

I am a professional software developer but I'm largely unfamiliar with C++ syntax. I am trying to compare the value at the end of a pointer with a double in an inherited C++ project.
The following bit of code successfully grabs the valueAddress from a text file and prints, for example
|"Primary key value"|123.456|
where the 123.456 is the value of the double at the address in the text file.
...
char DebugString[64];
int valueAddress;
fscanf(inputFile, "%s %d", key, &valueAddress);//inputFile declared elsewhere
printf("|");
printf(database->primaryKey);// Defined elsewhere and not the focus of this question
printf("|");
sprintf_s(DebugString,64,"%g",* ((double *)valueAddress));
printf(DebugString);
printf("|");
...
Why then, can't I access the value using:
if ((double *)valueAddress < -0.5)
{...}
as I get the error "error C2440: '>' : cannot convert from 'double' to 'double *'"
I also can't do:
if ((double) *valueAddress < -0.5)
{...}
as I get the error "error C2100: illegal indirection". Creating a variable and trying to assign that doesn't work either.
valueAddress is an integer in a text file, which is the memory address of a double value. So I need to use the int valueAddress as a double pointer. It clearly works when putting the value in the DebugString, so why won't it work in an if statement? How can I get around this?
I'm clearly misunderstanding the syntax here. What have I got wrong?
Using an int to represent the address of a double stored somewhere and attempting to cast an int to a double* is undefined behaviour in C++.
An int might not even be large enough to hold a pointer address. On a 64 bit system, a 32 bit int is not sufficient.
You might get away with using intptr_t to represent the address, and cast using *(double*)valueAddress. But it's still not well-defined.
I'm willing to be corrected on this point but I think the only realistic choice is an inline assembly solution specific to your platform to effect this conversion. That said, you're only reading data from a text file, and you can do that using perfectly normal C++.
First off, int is not the correct data type to store a memory address. You really should use intptr_t from <stdint.h>, which is guaranteed to be the correct size.
To reinterpret this value as a double* and dereference for comparison, you would do:
if ( *(double*)valueAddress < -0.5 )
But I am a little concerned about this. Unless that pointer references memory that already belongs to your program, you are not allowed to access it. Doing so will fall in the realm of undefined behaviour.
You need to dereference your pointer
if ( * ( (double * ) valueAddress ) < -0.5)
This first converts to a pointer, then finds the value pointed to.

What does *(int*) mean in C++?

I encountered the following line in a OpenGL tutorial and I wanna know what does the *(int*) mean and what is its value
if ( *(int*)&(header[0x1E])!=0 )
Let's take this a step at a time:
header[0x1E]
header must be an array of some kind, and here we are getting a reference to the 0x1Eth element in the array.
&(header[0x1E])
We take the address of that element.
(int*)&(header[0x1E])
We cast that address to a pointer-to-int.
*(int*)&(header[0x1E])
We dereference that pointer-to-int, yielding an int by interpreting the first sizeof(int) bytes of header, starting at offset 0x1E, as an int and gets the value it finds there.
if ( *(int*)&(header[0x1E])!=0 )
It compares that resulting value to 0 and if it isn't 0, executes whatever is in the body of the if statement.
Note that this is potentially very dangerous. Consider what would happen if header were declared as:
double header [0xFF];
...or as:
int header [5];
It's truly a terrible piece of code, but what it's doing is:
&(header[0x1E])
takes the address of the (0x1E + 1)th element of array header, let's call it addr:
(int *)addr
C-style cast this address into a pointer to an int, let's call this pointer p:
*p
dereferences this memory location as an int.
Assuming header is an array of bytes, and the original code has been tested only on intel, it's equivalent with:
header[0x1E] + header[0x1F] << 8 + header[0x20] << 16 + header[0x21] << 24;
However, besides the potential alignment issues the other posters mentioned, it has at least two more portability problems:
on a platform with 64 bit ints, it will make an int out of bytes 0x1E to 0x25 instead of the above; it will be also wrong on a platform with 16 bit ints, but I suppose those are too old to matter
on a big endian platform the number will be wrong, because the bytes will get reversed and it will end up as:
header[0x1E] << 24 + header[0x1F] << 16 + header[0x20] << 8 + header[0x21];
Also, if it's a bmp file header as rici assumed, the field is probably unsigned and the cast is done to a signed int. In this case it doesn't matter as it's being compared to zero, but in some other case it may.

Dereferencing pointer in Code Composer Studio

I have a value I receive in an unsigned byte array that I would like to dereference as a float. Take ptr as a uint8_t* pointing at a byte array of four values 0,0,0xCD,0x42 (this is a little endian system).
float val = *(float*)ptr;
is return -1.34e8
When I type:
*(float*)ptr;
In the expressions window after hitting a break point in that section of code, it gives me 102.5 as expected. Further, when I type:
*(float*)(ptr - 1);
I get the incorrect -1.34e8, as if the compiler used ptr - 1 instead of what I typed.
I'm confused - am I missing something here?
Basically the deref is correct.
If you printf("%p", ptr); do you get an address that is maybe not 4-byte aligned (or at least 2-byte aligned)? This may be necessary on some platforms.
For test, just pass the value of a real float in the uint8_t*, e.g.
float f= 102.5;
yourfunct((uint8_t*)&f);
and see if that works.
*(float*)(ptr - 1);
is the same as this
ptr--; //move the pointer to point to charackter in front of the previous one
*(float*)ptr;
Is this your intention ?
Or do you just want to subtract 1 from the value that is being pointed to be ptr.

Where is pointer metadata stored?

Could be that I am overlooking something obvious, but where is pointer metadata stored? For instance if I have a 32-bit int pointer ptr and I execute ptr++ it knows to advance 4 bytes in memory. However, if I have a 64-bit int pointer it knows to advance 8 bytes. So who keeps track of what type of pointer ptr is and where is it stored? For simplicity you can limit this to C++.
It isn't stored anywhere, per-se. The compiler looks at the type of the ptr and turns the ++ operation into an increment of the correct number of bytes.
In the symbol table while the compiler runs. Nowhere while your program runs, or rather it is implicit in the lower level code produced by the compiler.
It's not stored anywhere, it's determined at compile time. In fact, take this code as an example:
int *abc = NULL;
cout << abc + 1; /* Prints sizeof(int) */
cout << (void *)((char *)abc + 1); /* Prints 1. Casting it back to void * is necessary,
otherwise it will try to dereference it and print as a string. */