I'm currently reversing some firmware und need to write patches in C. This is a very simple code to illustrate my problem:
#include <iostream>
struct inner {
int32_t a;
int16_t b;
};
struct test {
int32_t one;
int32_t two;
char* data;
};
int main()
{
struct inner inner;
inner.a = 4;
inner.b = 5;
struct test test;
test.data = (char*)(&inner);
char *ptr = (char*)(&test);
int off = offsetof(struct test,data);
std::cout << "Data offset: " << off;
std::cout << "\n" << (&inner);
char* in = (char*)(ptr+off);
std::cout << "\n" << (void*)in;
return 0;
}
This code actually prints two pointer addresses, the second one being exactly 0x10 higher than the first one. This obviously also results into not being able to access the members a and b of the inner struct using this way.
I basically tried to change the pointer types, but didn't manage to find any correct solution by trying. In my understanding, casting to char* should allow me to access members by byte offset. I know that some cast are not needed, I did however get always the same results no matter what I do.
EDIT: This solved my problem:
#include <iostream>
struct inner {
int32_t a;
int16_t b;
};
struct test {
int32_t one;
int32_t two;
char* data;
};
int main()
{
struct inner inner;
inner.a = 4;
inner.b = 5;
struct test test;
test.data = (char*)(&inner);
char *ptr = (char*)(&test);
int off = offsetof(struct test,data);
std::cout << "Data offset: " << off;
std::cout << "\n" << (void*)test.data;
char* in = *((char**)(ptr+off));
std::cout << "\n" << (void*)in;
int32_t a = (int32_t)(*in);
int16_t b = (int16_t)(*(in+0x4));
std::cout << "\nA: " << a << " B: " << b;
return 0;
}
You want to print the value of test.data
, not its address.
char** in = (char**)(ptr+off);
// ^^ ^^
std::cout << "\n" << (void*)*in;
// ^