I am trying to read memory addresses from an executable running in memory, and then use those memory addresses to walk the PE structure.
I am having trouble because I'm unsure how to convert a 4 byte char array to it's int equivalent.
Here is my code so far:
char buffer[4];
int e_lfanew = 60;
if(!ReadProcessMemory(pHandle, (me32.modBaseAddr + e_lfanew), buffer, 4, NULL))
{
printf("ReadProcessMemory # %x Failed (%d)\n", me32.modBaseAddr, GetLastError());
}
The address i'm reading in, in this case 0xE0000000, is the offset of the PE Header. I want to take the memory address I just read and use it as an offset to read from process memory again, but I cannot figure out how to convert it to an int properly.
Any help would be greatly appreciated.
buffer[0] |
(buffer[1] << 8) |
(buffer[2] << 16) |
(buffer[3] << 24)
or the other way around, depending on whether your high-order byte is buffer[0] or buffer[3]
int MemoryBufferToInt(char* buffer, int buffer_size) {
int result;
assert(buffer_size == sizeof(result));
memcpy(&result, &buffer[0], sizeof(result));
return result;
}
The code above assumes that this buffer was obtained from the process, so that the byte order of the memory buffer is the same as the byte order of a regular int on your platform. Otherwise, you can easily contruct the integer for a specific byte order if you know what the byte order of the buffer is.
NOTE that you could just use static_cast<char*>(&result) in place of your buffer as the parameter to the function that retrieves the buffer contents.
Related
I'm working on simple debugger for Windows x86 platform, just for tests. I have implemented almost all functionality I need, except code disassembling. I decide that I use udis86 library but it is not important in my case.
In 0x86 - 0x64 architecture any instruction can has at most 15 bytes lenght, so
how I can get excatly 10 instructions started from e.g 0x4000bcda?
I have following code.
void disassembly(HANDLE hProcess, DWORD address)
{
BYTE buffer[15];
SIZE_T bytes_read;
GetProcessMemory(hProcess, (LPBYTE) address, buffer, sizeof(buffer), &bytes_read);
}
When the GetProcessMemory function doesn't failed, buffer should be filled with data.
But I can't assume that buffer contains fixed amount of instructuions. It may be one, two or whatever.
Maybe you have any ideas how it should be implemented?
Here is my current solution:
SIZE_T bytes_read;
BYTE buffer[4096];
if (!ReadProcessMemory(hProcess, (LPBYTE)address, buffer, sizeof(buffer), &bytes_read)) {
std::cout << "Cannot read process memory -> dissasembly." << std::endl;
return;
}
printf("Address : %#010x\n", address);
std::cout << "Disassembled code: " << std::endl;
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_input_buffer(&ud_obj, buffer, sizeof(buffer));
ud_set_mode(&ud_obj, 64);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
int counter = 0;
int instructionAmount = 10;
while (ud_disassemble(&ud_obj)) {
printf("\t%s\n", ud_insn_asm(&ud_obj));
counter++;
if (counter == instructionAmount) {
break;
}
}
It basically works but in m opinion it does not good solution and it may cause errors
You said the max bytes per instruction is 15 and you want to read 10 instructions, so 15 x 10 = 150. That is how much memory you should read in your call to ReadProcessMemory.
But the instructions won't consume that much memory, once you read that memory into your local buffer, you will have to read each instruction starting at buffer[0], decode it, get it's length, index into the next instruction, decode the instruction and continue until the number of instructions decoded is reached 10. The combined length of all the instructions you decoded represents the last byte in the buffer of your 10 instructions.
You will have to increase the instruction counter and a seperate number of bytes counter one each iteration.
I'm writing a program that creates MIDI files, and I'm trying to write the midi messages on a file.
I tested first all the way to create file from zero using the function fputc() and inputting byte per byte all the file, and it went well.
The problem came when I tried to write more than one byte at the same time (e.g. writing a short int or an int into the file), because the function fwrite() put the bytes backwards.
For example:
FILE* midiFile;
midiFile = fopen("test.mid", "wb");
short msg = 0x0006;
fwrite(msg, sizeof(msg), 1, midiFile);
fclose(midifile);
The output written int the file its 0x06 the 0x00, and not the expected: 0x00,0x06.
I read about that, and find that it's caused by the endianness; my Intel processor uses little endian so it writes variables bigger than 1 byte backwards (compared to a big endian machine).
I still need to correct that and write the bytes the way I want to develop my program.
My compiler doesn't identify functions like htonl() or similar (I don't know why) but I'm asking a way to do it, or how to write short's and int's on char arrays (especially short's).
Either write the bytes you want in order, one at a time...
or swap the bytes before you write them.
uint8_t msbyte = msg >> 8;
uint8_t lsbyte = msg & 0xFF;
uint8_t buffer[2];
// Big Endian
buffer[0] = msbyte;
buffer[1] = lsbyte;
/* Little endian
buffer[0] = lsbyte;
buffer[1] = msbyte;
*/
fwrite(&buffer[0], 1, sizeof(buffer), midiFile);
Swapping bytes:
uint16_t swap_bytes(const uint16_t value)
{
uint16_t result;
result = value >> 8;
result += (value & 0xFF) << 8;
return result;
}
I have a code below, but i can't put int to my buffer.
unsigned char buffer[1024];
buffer[0] = 0x44;
u_long fd = htonl(VERSION);
memcpy(buffer+1, &fd, 4);
Can you help me?
In ntohl(buffer[1]); value of buffer[1] will be taken (a char) and will be casted into long.This will cause on a little endian machine to take value at &buffer[1] which is obviously 0 for value less than 224(unsigned) as you have called ntohl earlier which reverses byte order.
And if you are really interested to look into the buffer then try
int *f =(int*) (&buffer[1]);
printf("\n %u \n", ntohl(*f));//Also *f but then you have to paste it in calculator to see allignment
You are putting the value into the buffer correctly, but you are not checking it correctly afterwards. ntohl(buffer[1]) is retrieving the 1-byte unsigned char value that is inside the second slot of the buffer by itself, and then extending it to a 4-byte value when passing it to ntohl(). What you need to do instead is retrieve the 4-byte unsigned long value that occupies the second, third, fourth, and fifth slots of the buffer and use it as-is:
ntohl(*reinterpret_cast<u_long*>(buffer+1));
Or:
u_long version;
memcpy(&version, buffer+1, 4);
ntohl(version);
I'm attempting to use ReadProcessMemory to read a dynamic amount of bytes into an array and then return it. I simply can't get it to work properly. My current code is...
byte *Application::readMemory(DWORD address, int length) {
byte *buffer = new byte[length];
SIZE_T bytesRead;
ReadProcessMemory(piProcessInfo.hProcess, (void *)address, &buffer, length, &bytesRead);
return buffer;
}
Any help would be appreciated.
Shouldn't it be
ReadProcessMemory(piProcessInfo.hProcess, (void *)address, buffer, length, &bytesRead);
? If you give buffer-pointer address as input parameter, then ReadProcessMemory copies it where buffer pointer lies (not to the buffer but into buffer pointer vatiable and beyond) - and sice it is on the stack, stack gets corrupted.
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);
}