Inspecting memory values - c++

I have source code for a project that inspects a game's memory values. The thing I don't understand is this: How did the author so precisely determined the type and location of these values? For example, here's a struct he defined:
typedef struct {
UInt16 times_used; // 0x0
UInt16 token; // 0x2
SInt16 previous_id; // 0x4
SInt16 next_id; // 0x6
SInt32 model; // 0x8
char unknown00[0x1B]; // 0xC
UInt8 player_owner; // 0x27
char unknown01[0x18]; // 0x28
UInt32 position_x; // 0x40
UInt32 position_y; // 0x44
char unknown02[0x1F]; // 0x48
UInt32 death_type; // 0x69
char unknown03[0x7]; // 0x6D
UInt32 destination_x; // 0x74
UInt32 destination_y; // 0x78
char unknown04[0x84]; // 0x7C
UInt32 health_damage; // 0x100
UInt32 shield_damage; // 0x104
UInt32 energy_damage; // 0x108
char unknown05[0x74]; // 0x10C
} Unit;
He looks for it at this address 0x3BC2060 and it's size is 0x8B8. I ran the program and watch the memory at this location, and sure, I could identify some things like the name property, but how did he find this out so precisely?
Thanks.

I hope I get this straight:
You look at 0x3bc2060 and the next 0x8b8 bytes/octets.
To reverse engineer a struct like this it is crucial to observe the program using this struct by filling it with values for the different fields in it.
Then you can deduce from many dumps starting at 0x3bc2060 and the following 0x8b8 bytes
what is happening.
But it is not so precise as you might expect, because some fields are apparently not assignable. These are the char unknown[].
Doing a struct reverse is a very tedious task and you need much patience with your debugger ;)
Hope this helps to understand how it works in principle

Related

Convert unsigned long to char*, disregard high 0 bytes

I have an unsigned long long variable which I want to write to a binary file. However, I need to neglect all leading bytes which are zero.
This means
unsigned long long toWrite = 4;
should write 0x04 and not 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04 to the stream.
#include <fstream>
int main(){
std::ofstream out("test.txt", std::ios::binary);
unsigned long long toWrite = 4;
out << cutoffZeroBytes(toWrite);
out.close();
return 1;
}
I was thinking about making cutoffZeroBytes a function which returns a char*. But if there are zero bytes in the middle (e.g. 0x03 0x00 0xf1), then I think I couldn't write it to the stream, since 0x00 determines the end of an char array.
I'm a little clueless here and need some help.
One way is using write for this aim.
So, just change:
out << cutoffZeroBytes(toWrite);
to:
out.write((char*)&toWrite, sizeof(toWrite));
And if you want to cut this number:
char* start = (char*)&toWrite;
int pi = sizeof(toWrite);
for (; pi > 0; pi--, start++)
if (*start)
break;
out.write(start, pi);

Append quint16/unsigned short to QByteArray quickly

In my project I'm working with QByteArrays appending data to them as the program goes. Most of the time, a simple quint8 gets appended just fine using QByteArray::append(). But when a quint16 gets appended, only 1 byte gets appended instead of 2.
QByteArray ba = QByteArray::fromHex("010203");
quint number(300);//300 in hex is 012c
ba.append(number);//What should be appended instead of just number?
//the current incorrect result is
ba.toHex() == "0102032c"
//the desired result is
ba.toHex() == "010203012c"
I've already tried this, but it just inserts the value as a string (4 bytes):
ba.append(QByteArray::number(number, 16));
What should I append to the QByteArray so both bytes of "number" get appended instead of just one byte? Also, the fastest method possible is preferred since this program needs to have great performance times. So absolutely no converting to QStrings.
Thanks for your time.
On its own, QByteArray only supports appending bytes; to append a big-endian representation of fixed-size integer types you can build your own operator<< (or what you prefer) overloads using the appropriate bit shifts:
QByteArray &operator<<(QByteArray &l, quint8 r)
{
l.append(r);
return l;
}
QByteArray &operator<<(QByteArray &l, quint16 r)
{
return l<<quint8(r>>8)<<quint8(r);
}
QByteArray &operator<<(QByteArray &l, quint32 r)
{
return l<<quint16(r>>16)<<quint16(r);
}
This allows you to write code like:
QByteArray b;
b<<quint16(300); // appends 0x01 0x2c
b<<quint8(4); // appends 0x04
b<<quint16(4); // appends 0x00 0x04
b<<quint32(123456); // appends 0x00 0x01 0xe2 0x40
b<<quint8(1)<<quin16(2)<<quint32(3); // appends 0x01 0x00 0x02 0x00 0x00 0x00 0x03
You should probably avoid writing
QByteArray b;
b<<1;
because in theory the output depends on the size of the current platform integer (although AFAIK on all platforms supported by Qt int is 32 bit).

Managing buffers of binary data in C++

I'm trying to create a simple binary format to transmit over a BlueToothLE module on Arduino. I'm trying to describe properties of a list of objects. And for starters I'm trying to transmit just a single property.
The format I'm attempting to encode and pass around is as follows.
namePropertyID, nameLength, nameString...
So given a name of "Bob"
0x01 0x03 0x42 0x6F 0x62
nameID 3 chars "B" "o" "b"
But when I pass the buffer around, it seems to mutate.
before I pass it, it reads:
0x01 0x03 0x42 0x6F 0x62
But after I pass it, it reads:
0x00 0x3C 0x18 0x04 0x00
Program.h
typedef enum {
InfoTypeName = 0x01
} InfoType;
class Program {
public:
char *name;
uint8_t * data();
uint8_t dataLen();
};
Program.cpp
#include "Program.h"
uint8_t* Program::data() {
uint8_t nameLength = strlen(name);
uint8_t buff[dataLen()];
buff[0] = InfoTypeName;
buff[1] = nameLength;
for (uint8_t i = 0; i < nameLength; i++) {
buff[i+2] = (uint8_t)name[i];
}
// First check of data, things look ok.
for (uint8_t i = 0; i < nameLength+2; i++) {
Serial.print(F(" 0x")); Serial.print(buff[i], HEX);
}
Serial.println();
return buff;
}
uint8_t Program::dataLen() {
return strlen(name) + 2;
}
Elsewhere I pass this to the Bluetooth library:
BTLEserial.write(program.data(), program.dataLen());
Which is implemented like so, and is printing out seemingly incorrect data:
size_t Adafruit_BLE_UART::write(uint8_t * buffer, uint8_t len)
{
Serial.print(F("\tWriting out to BTLE:"));
for (uint8_t i=0; i<len; i++) {
Serial.print(F(" 0x")); Serial.print(buffer[i], HEX);
}
Serial.println();
// actually sends the data over bluetooth here...
}
So a few questions:
Why the data mutating?
Is this a good approach for generating buffers?
Is having two separate methods, one for length and one for data a good pattern?
The problem is that in Program::data(), buff is a local variable. You are returning a pointer to its first element, which is a dangling pointer at the call side. You need to ensure the buffer you export is something that stays alive for long enough. There are different ways of doing this, but I am not entirely familiar with the limitations arduino places on what parts of the C and C++ standard libraries you can use.
The simplest approach could be to reserve a buffer in main, and pass that around to the code that populates it and consumes it. Alternatively, you could give your Program class a buffer data member. The main problem is going to be ensuring that the buffer is large enough for different messages.
I would first try something like this:
void create_msg_(const char* name, uint8_t buff, size_t size)
{
// populate buff with the message
}
void send_msg(const char* name)
{
size_t size = strlen(name) + 2;
uint8_t buff[size]; // VLA extension, not std C++
create_msg_(name, buff, size);
BTLEserial.write(buff, size);
}

Memset an address into four bytes of allocated memory

EDIT: Thanks to Ipmcc, he has given me a solution in the comments.
I would like to use memset to allocate a four-byte address into the first four bytes of memory that I have dynamically allocated. An example with comments of what I'd like to do is shown below. All of my attempts to find out how to do this or figure it out myself has ended up without success.
Any help would be most appreciated, thank you.
int main(void)
{
// Define and assign eight bytes of memory
unsigned char *data1 = new unsigned char [8];
unsigned char *data2 = new unsigned char [8];
// Set all eight bytes in both data1 and data2 to 0x00
memset(data1, 0x00, 8);
memset(data2, 0x00, 8);
// Lets say that the address of *data1 is: 00508d30
// Lets say that the address of *data2 is: 0050b180
// I want to set the first four bytes in data1 to the
// address of data2, so it would look something like this...
memset(data1, 0x00, 1); ++data1;
memset(data1, 0x50, 1); ++data1;
memset(data1, 0xB1, 1); ++data1;
memset(data1, 0x80, 1);
data1 -= 3; // Reset pointer
// But of course this is in no way practical or viable
// since the addresses change each time (also it's not a good
// practice to hard-code things in anyway). So I'm wondering
// if there's a proper/feasible way to do this.
return 0;
}

QtDataStream::writeRawData reorders my bytes

I am trying to save a raw byte array into a file:
mDataStream.writeRawData( ( (const char *)&testPacket), 188);
The test packet is just an array of unsigned char, the packet is copied in the right size, but the bytes are reordered. ie: 0x47 0x00 0x10 0x20 ... becomes 0x00 0x47 ox20 0x10.
This looks like an endianness problem, but i've tried setting the byte order to little endian with unsuccessful results.