简体   繁体   中英

Reading Bytes from a File using C

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.

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?)

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.

    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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM