0

I've been working on this for months and am absolutely livid that me nor my team can figure this out :/

Here is the situation - I am managing the memory of another program, specifically reading structures. When reading something simple, like an integer, it works fine. When reading a structure, I need to shift my reading location back 4 bytes, else I end up reading at the wrong location and the values stored are incorrect.

Here is an example:

ReadProcessMemory( hProcess, lpBaseAddress, &xBuffer, sizeof( xBuffer ), nullptr );

So long that xBuffer is not a Class or a Struct, this works fine. Say that xBuffer is declared as an object of vector_t - this is the only way my read will work:

class vector_t
{
public:
    float x, y, z;
};
vector_t xBuffer;
ReadProcessMemory( hProcess, lpBaseAddress - 0x4, &xBuffer, sizeof( xBuffer ), nullptr );

I know this code isn't MCRE/reproducible, because I've tried copying over snippets of my code and it works fine, but this is all that is happening and I have no idea what else could cause this.

Getting the size of a class, it returns size of all members +0x4, when it should be +0x1, right? Maybe that helps?

EDIT: After further debugging, I found the issue is with atomic. Why?

#include <Windows>
#include <atomic>

class vector_t
{
public:
    float x, y, z;
};

/* ... */

    std::atomic< DWORD > dwBaseAddress { };
    /* ... */
    std::atomic< vector_t > vecBuffer { };
    // unless we subtract 4 bytes from lpBaseAddress._My_val, we will not read properly
    ReadProcessMemory( hProcess, LPVOID( lpBaseAddress._My_val ), &vecBuffer, sizeof( vector_t ), nullptr );

When I make a copy of vecBuffer (that isn't atomic), it works fine. What can I do to ensure this situation doesn't happen?

Jonathan Potter
  • 36,172
  • 4
  • 64
  • 79
J. Doe
  • 208
  • 1
  • 4
  • 13
  • What does `alignof` say? You may be missing out on the alignment factor. – tadman Jan 14 '18 at 03:23
  • Can you give me more information on exactly how you want me to use the alignof operator? – J. Doe Jan 14 '18 at 03:24
  • When it comes to raw memory size, `sizeof` tells you how physically large something is. When it comes to positioning in memory, [`alignof`](http://en.cppreference.com/w/cpp/language/alignof) will tell you where it has to be located. It's possible your `lpBaseAddress` is based on mistaken assumptions as to where this ilves in memory. Where does that value come from? – tadman Jan 14 '18 at 03:25
  • `vector_t` returns `4` (and my other classes do as well). lpBaseAddress is the correct address, as it works fine on empty projects. The value comes from a simple offset from a dereferenced pointer – J. Doe Jan 14 '18 at 03:27
  • Comes from as in how? Where's the code that generates that value? Also how does a struct return `4`? That's a composite of three floats, which should be 12 bytes. – tadman Jan 14 '18 at 03:32
  • Comes from, as in I created the other program. There is a pointer to a specific address. Once that pointer is dereferenced, it returns that address I'm looking for. It's all hard coded: `[ base.dll + 0x140 ] + 0x10` returns what I'm looking for. Also, sorry, I should've been more clear. `alignof( vector_t )` returns `4`, and so do my other classes. – J. Doe Jan 14 '18 at 03:34
  • @J.Doe -- *Getting the size of a class, it returns size of all members +0x4, when it should be +0x1, right? Maybe that helps?* -- So your question boils down to [this issue](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member)? – PaulMcKenzie Jan 14 '18 at 03:42
  • I wouldn't know, @PaulMcKenzie - that's just an observation I've made. I'm currently testing @ MinorThreat's solution. – J. Doe Jan 14 '18 at 03:50
  • @MinorThreat's solution did not work :( – J. Doe Jan 14 '18 at 03:59
  • #updated the question – J. Doe Jan 14 '18 at 04:30
  • Why are you reading `sizeof( vector_t )` bytes, and not `sizeof(std::atomic< vector_t >)`, when the latter reflects the actual type of `vecBuffer`? – Igor Tandetnik Jan 14 '18 at 04:33
  • because atomic is just for my CURRENT program, not the original program that I'm reading. I use atomic to communicate that variable info across my threads. Also, afaik, you cannot copy anything to an atomic variable - that constructor is deleted. – J. Doe Jan 14 '18 at 04:35
  • There is no requirement that `std::atomic` be the same size as a `T`. In fact, if `T` is not the size of a type that the processor can operate on atomically, there will necessarily be some type of lock required in order to synthesize the atomic operation. (See [`is_lock_free`](http://en.cppreference.com/w/cpp/atomic/atomic_is_lock_free).) Your vector_t is 12 bytes. I'm not aware of a processor with native support for atomic 12-byte operations. – Raymond Chen Jan 14 '18 at 15:17

1 Answers1

0

Making a copy of the atomic variable, then copying it over works.

I'd love to know the reasoning behind it, though, so I'm leaving the question open in case anyone knows. I suppose only the developer of the WinAPI function ReadProcessMemory can know since we cannot actually see the code.

Whatever :/

J. Doe
  • 208
  • 1
  • 4
  • 13
  • 1
    The reasoning has nothing to do with `ReadProcessMemory`. It has to do with how your implementation implemented `std::atomic`. If you look at `vecBuffer` in the debugger, you'll see that the first thing in it is a lock, not `x`. – Raymond Chen Jan 23 '18 at 14:42