ReadProcessMemory reads Memory backwards? - c++

When using ReadProcessMemory to read memory of an executable file, the first two bytes that I get are reversed. The code is:
SIZE_T dataRead;
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) malloc(1);
ReadProcessMemory(process, (LPVOID)addr, dosHeader, 2, &dataRead);
printf("%x\n", dosHeader->e_magic);
The above outputs 5A4D instead of 4D5A. Why would that be? Could it endianess?
Thanks in advance.

Yes, this is due to endianness. The first byte in the file is 0x4d, the second byte is 0x5a. When you print these using %x, they are interpreted as being a little endian number, so the bytes are swapped when they are printed. Consider, as a self-contained example, the following program:
#include <cassert>
#include <cstdio>
int main()
{
assert(sizeof(unsigned) == 4);
char bytes[4] = { 0x12, 0x34, 0x56, 0x78 };
std::printf("%x\n", *reinterpret_cast<unsigned const*>(bytes));
}
On a system with a little-endian byte ordering, the output will be 78563412. (This example program ignores potential alignment issues; since you are using Visual C++, there will be no problems.)
Note also that you are overrunning your one byte allocation (you malloc(1) but read two bytes).

Related

C++ printing float as nan

This is a simplified C++ program converting 4 bytes into their IEE754 float representation.
#include <iostream>
#include <math.h>
#include <memory.h>
uint8_t bytes[4] = {0x40, 0xd5, 0xc6, 0x7f}; // 0x40d5c67f
float f;
int main()
{
memcpy(&f, &bytes[0], 4);
printf("%.*lf", 5, f);
}
it's output is nan! isnan also returns true for it. How has this happened? 0x40d5c67f is 6.6804...
Happens both on my arduino-like microcontroller and http://cpp.sh/
If you are running this code on a machine that uses little-endian,
higher digits of multi-byte numbers are stored in higher address of the memory.
Therefore, on little endian machines, the 4-byte number on memory
0x40, 0xd5, 0xc6, 0x7f is treated as 0x7fc6d540, not 0x40d5c67f.
Interpreting as IEEE754, the exponent part of this number is 255 and
the fraction part of this number is not 0, so this is NaN.

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

endianness when using part of int array

I'm trying to pullout values from a uint8_t array.
But I'm having troubles understanding how these are represented in the memory.
#include <cstdio>
#include <cstring>
#include <stdint.h>
int main(){
uint8_t tmp1[2];
uint16_t tmp2 = 511;//0x01 + 0xFF = 0x01FF
tmp1[0] = 255;//0xFF
tmp1[1] = 1;//0x01
fprintf(stderr,"memcmp = %d\n",memcmp(tmp1,&tmp2,2));
fprintf(stderr,"first elem in uint8 array = %u\n",(uint8_t) *(tmp1+0));
fprintf(stderr,"first elem in uint8 array = %u\n",(uint8_t) *(tmp1+1));
fprintf(stderr,"2xuint8_t as uint16_t = %u\n",(uint16_t) *tmp1);
return 0;
}
So i have an 2 element long array of datatype uint8_t. And I have a single variable uint16_t.
So when I take the value 511 on my little endian machine, I would assume this is layed out in memory as
0000 0001 1111 1111
But when I use memcompare it looks like it is actually being represented as
1111 1111 0000 0001
So little endianness is only used "within" each byte?
And since the single bit that is set in the tmp1[1] counts as 256, even though it is further "right" in my stream. The values for each byte (not bit), is therefore bigendian? I'm abit confused about this.
Also if I want to coerce an fprint, to printout, my 2xuint8_t as a single uint16_t, how do I do this. The code below doesn't work, it only printouts the first byte.
fprintf(stderr,"2x uint8_t as uint16_t = %u\n",(uint16_t) *tmp1);
Thanks in advance
Your assumption of what you expect is backwards. Your observation is consistent with little-endian representation. To answer your last question, it would look like this:
fprintf(stderr,"2x uint8_t as uint16_t = %u\n",*(uint16_t*)tmp1);
Don't think of endianness as "within bytes". Think of it as "byte ordering". (That is, the actual bit ordering never matters because humans typically read values in big-endian.) If it helps to imagine that the bits are reversed on a little-endian machine, you can imagine it that way. (in that case, your example would have looked like 1111 1111 1000 0000, but as I said, humans don't typically read numbers such that the most significant values are to the right...but you might want to imagine that's how the computer sees things, if it helps you understand little-endian.)
On a little endian machine, 0xAABBCCDD would be seen as 0xDD 0xCC 0xBB 0xAA in memory, just as you are seeing. On a big-endian machine (such as a PPC box) you'd see the same ordering in-memory as you see when you write out the 32-bit word.
First, if you want be 100% sure that your variables are stored in right order in memory, you should put them in a struct.
Then note that memcmp() treats input you give it as a sequence of bytes, since it has no assumptions regarding the nature of the data you give it. Think, for example, of the following code:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char** argv) {
int32_t a, b;
a = 1;
b = -1;
printf( "%i\n", memcmp( &a, &b, sizeof( int32_t ) ) );
}
It outputs -254 on my little-endian machine regardless of fact that a > b. This is because it has no ideas about what the memory actually is, so it compares them like an array of uint8_t.
If you actually want to visualize how the data is represented on your machine, you may first use fwrite to write a struct into the file and then open it with your favorite hex editor (in my experience, wxHexEditor is great in telling you how the data looks if it is X-bit Y-endian ingeter). Here's the source:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t tmp1[2];
uint16_t tmp2;
} mytmp;
int main(int argc, char** argv) {
mytmp tmp;
tmp.tmp1[0] = 255;
tmp.tmp1[1] = 1;
tmp.tmp2 = 511;
FILE* file = fopen( "struct-dump", "w" );
fwrite( &tmp, sizeof( mytmp ), 1, file );
fclose( file );
}
As for treating an array of uint8_t as uint16_t, you would probably want to declare a union or use pointer coercion.

Problem converting endianness

I'm following this tutorial for using OpenAL in C++: http://enigma-dev.org/forums/index.php?topic=730.0
As you can see in the tutorial, they leave a few methods unimplemented, and I am having trouble implementing file_read_int32_le(char*, FILE*) and file_read_int16_le(char*, FILE*). Apparently what it should do is load 4 bytes from the file (or 2 in the case of int16 I guess..), convert it from little-endian to big endian and then return it as an unsigned integer. Here's the code:
static unsigned int file_read_int32_le(char* buffer, FILE* file) {
size_t bytesRead = fread(buffer, 1, 4, file);
printf("%x\n",(unsigned int)*buffer);
unsigned int* newBuffer = (unsigned int*)malloc(4);
*newBuffer = ((*buffer << 24) & 0xFF000000U) | ((*buffer << 8) & 0x00FF0000U) | ((*buffer >> 8) & 0x0000FF00U) | ((*buffer >> 24) & 0x000000FFU);
printf("%x\n", *newBuffer);
return (unsigned int)*newBuffer;
}
When debugging (in XCode) it says that the hexadecimal value of *buffer is 0x72, which is only one byte. When I create newBuffer using malloc(4), I get a 4-byte buffer (*newBuffer is something like 0xC0000003) which then, after the operations, becomes 0x72000000. I assume the result I'm looking for is 0x00000027 (edit: actually 0x00000072), but how would I achieve this? Is it something to do with converting between the char* buffer and the unsigned int* newBuffer?
Yes, *buffer will read in Xcode's debugger as 0x72, because buffer is a pointer to a char.
If the first four bytes in the memory block pointed to by buffer are (hex) 72 00 00 00, then the return value should be 0x00000072, not 0x00000027. The bytes should get swapped, but not the two "nybbles" that make up each byte.
This code leaks the memory you malloc'd, and you don't need to malloc here anyway.
Your byte-swapping is correct on a PowerPC or 68K Mac, but not on an Intel Mac or ARM-based iOS. On those platforms, you don't have to do any byte-swapping because they're natively little-endian.
Core Foundation provides a way to do this all much more easily:
static uint32_t file_read_int32_le(char* buffer, FILE* file) {
fread(buffer, 1, 4, file); // Get four bytes from the file
uint32_t val = *(uint32_t*)buffer; // Turn them into a 32-bit integer
// Swap on a big-endian Mac, do nothing on a little-endian Mac or iOS
return CFSwapInt32LittleToHost(val);
}
there's a whole range of functions called "htons/htonl/hton" whose sole purpose in life is to convert from "host" to "network" byte order.
http://beej.us/guide/bgnet/output/html/multipage/htonsman.html
Each function has a reciprocal that does the opposite.
Now, these functions won't help you necessarily because they intrinsically convert from your hosts specific byte order, so please just use this answer as a starting point to find what you need. Generally code should never make assumptions about what architecture it's on.
Intel == "Little Endian".
Network == "Big Endian".
Hope this starts you out on the right track.
I've used the following for integral types. On some platforms, it's not safe for non-integral types.
template <typename T> T byte_reverse(T in) {
T out;
char* in_c = reinterpret_cast<char *>(&in);
char* out_c = reinterpret_cast<char *>(&out);
std::reverse_copy(in_c, in_c+sizeof(T), out_c);
return out;
};
So, to put that in your file reader (why are you passing the buffer in, since it appears that it could be a temporary)
static unsigned int file_read_int32_le(FILE* file) {
unsigned int int_buffer;
size_t bytesRead = fread(&int_buffer, 1, sizeof(int_buffer), file);
/* Error or less than 4 bytes should be checked */
return byte_reverse(int_buffer);
}

memcpy - int variable to BYTE

I am trying to create a data packet, using memcpy. I expect to see the output in pOutBuffer, whose first four bytes will have 999, followed by 111 followed by 12; But currently i am getting some garbage.
The problem is that instead of copying the value, it copies the address, I think. How can i copy these values in to a contiguous memory so that i can write it to disk and can retrieve the data at the receiving end with my defined format?
Thanks.
#include "stdafx.h"
#include "windows.h"
typedef struct
{
int Begin;
int End;
int Size;
}PACKET;
void AddBuffer(PACKET* pPacket, BYTE* pOutBuffer)
{
memcpy(pOutBuffer, &pPacket->Begin, sizeof(int));
memcpy(pOutBuffer+sizeof(int), &pPacket->End, sizeof(int));
memcpy(pOutBuffer+sizeof(int)+sizeof(int), &pPacket->Size, sizeof(int));
}
int _tmain(int argc, _TCHAR* argv[])
{
PACKET* pPacket = new PACKET;
pPacket->Begin = 999;
pPacket->End = 111;
pPacket->Size = 12;
BYTE* pOutBuffer = new BYTE [pPacket->Size];
AddBuffer(pPacket, pOutBuffer);
//Write pOutBuffer on to the disk
//WriteFile(vhFileToWrite,(BYTE*)pOutBuffer,pPacket.Size,&vRetFileSize,NULL);
//Delete pOutBuffer
return 0;
}
Source sample has been updated. It now builds ok
Your code works correctly. On a little-endian machine with sizeof(int)==4, the number 999 will be stored as the four bytes 0xe7, 0x03, 0x00, 0x00.
You said you saw the character 'ç': That is because you are trying to view the array as a string, and ç has the character code 0xe7, which is indeed the first byte written. If you view it as an array (either using Visual Studio's memory view, or by typing pOutBuffer,12 in the watch window), you will see the correct byte values.