1

I have written a program in C which will read the bytes at a specific memory address from its own address space.

it works like this:

  1. first it reads a DWORD from a File.
  2. then it uses this DWORD as a memory address and reads a byte from this memory address in the current process' address space.

Here is a summary of the code:

FILE *fp;
char buffer[4];

fp=fopen("input.txt","rb");

// buffer will store the DWORD read from the file

fread(buffer, 1, 4, fp);

printf("the memory address is: %x", *buffer);

// I have to do all these type castings so that it prints only the byte example:
// 0x8b instead of 0xffffff8b

printf("the byte at this memory address is: %x\n", (unsigned)(unsigned char)(*(*buffer)));

// And I perform comparisons this way

if((unsigned)(unsigned char)(*(*buffer)) == 0x8b)
{
    // do something
}

While this program works, I wanted to know if there is another way to read the byte from a specific memory address and perform comparisons? Because each time, I need to write all the type castings.

Also, now when I try to write the byte to a file using the following syntax:

// fp2 is the file pointer for the output file
fwrite(fp2, 1, 1, (unsigned)(unsigned char)(*(*buffer)));

I get the warnings:

test.c(64) : warning C4047: 'function' : 'FILE *' differs in levels of indirectio
n from 'unsigned int'
test.c(64) : warning C4024: 'fwrite' : different types for formal and actual para
meter 4

thanks.

3 Answers 3

1

You can use the C language union construct to represent an alias for your type as shown

typedef union {
      char char[4];
      char *pointer;
   } alias;

alias buffer;

This assumes a 32-bit architecture (you could adjust the 4 at compile time, but would then also need to change the fread() byte count).

Then, you can simply use *(buffer.pointer) to reference the contents of the memory location.

From your question, the application is not clear, and the technique seems error prone. How do you take into account the movement of addresses in memory as things change? There may be some point in using the linker maps to extract symbolic information for locations to avoid the absolute addresses.

Sign up to request clarification or add additional context in comments.

1 Comment

I am actually checking the memory address space of a loaded module by reading the addresses from a file. I am loading this module using LoadLibrary() in my program. Thanks, I will try your suggestion.
1

Take note of the definition of fwrite,

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

which means that the warnings at the last part of your question are because you should be writing from a character pointer rather than writing the actual value of the character.

You can remove the extra type castings by assigning the pointer you read from the file to another variable of the correct type.

Examples to think about:

#include <stdio.h>
int main() {
  union {
    char buffer[8];
    char *character;
    long long number;
  } indirect;
  /* indirect is a single 8-byte variable that can be accessed
   * as either a character array, a character pointer, or as
   * an 8-byte integer! */
  char *x = "hi";
  long long y;
  char *z;
  printf("stored in the memory beginning at x: '%s'\n", x); /* 'hi' */
  printf("bytes used to represent the pointer x: %ld\n", sizeof(x)); /* 8 */
  printf("exact value (memory location) of (pointed to by) the pointer x: %p\n", x); /* 4006c8 */
  y = (long long) x;
  printf("%llx\n", y); /* 4006c8 */
  z = (char *) y;
  printf("%s\n", z); /* 'hi' */
  /* the cool part--we can access the exact same 8 bytes of data
   * in three different ways, as a 64-bit character pointer,
   * as an 8-byte character buffer, or as
   * an 8-byte integer */
  indirect.character = z;
  printf("%s\n", indirect.character); /* 'hi' */
  printf("%s\n", indirect.buffer); /* binary garbage which is the raw pointer  */
  printf("%lld\n", indirect.number); /* 4196040 */
  return 0;
}

By the way, reading arbitrary locations from memory seems concerning. (You say that you are reading from a specific memory address within the program's own address space, but how do you make sure of that?)

3 Comments

Thanks. I think it should be: fwrite((*buffer), 1, 1, fp2). Since fp2 is the file pointer for the output FILE stream. I am able to get it working this way. Please elaborate on how to remove the extra type castings, I tried doing this by using another variable but did not work.
Could you update your original question with the changes and the new warnings/errors you are getting?
If your pointer read from the file into buffer is binary equivalent in both length and value to a valid char * pointer in your program's address space, and the defined size of the buffer is also correct, then you can simply do char * x = (char *) buffer. This gives no error even with -Wall. But I am still scratching my head how you know that the value you read from a file is a valid memory address in the transient memory space of your program.
0
    fp=fopen("input.txt","rb");

The file has an extension of .txt and you are trying to read it as a binary file. Please name files accordingly. If on Windows, name binary files with .bin extention. On Linux file extension do not matter.

    // buffer will store the DWORD read from the file

    fread(buffer, 1, 4, fp);

If you want to read 4 bytes, declare an unsinged int variable and read 4 bytes into it as shown below

    fread(&uint, 1, 4, fp);

Why do you want to use a character array ? That is incorrect.

    printf("the memory address is: %x", *buffer);

What are you trying to do here ? buffer is a pointer to a const char and the above statement prints the hex value of the first character in the array. The above statement is equal to

   printf("the memory address is: %x", buffer[0]);

   (*(*buffer)

How is this working ? Aren't there any compiler warnings and errors ? Is it Windows or Linux ? (*buffer) is a char and again de-referencing it should throw and error unless properly cast which I see you are not doing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.