Search code examples
c++pointers

Getting wrong pointer addresses when accessing struct members by offset


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;
}

Solution

  • You want to print the value of test.data, not its address.

     char** in = (char**)(ptr+off);
     //  ^^           ^^
    
     std::cout << "\n" << (void*)*in;
     //                          ^