0

I'm writing something like Java, and I have problem with pointer (- - ) I have a struct:

struct _lnHeader32
{ unsigned char signature[2]; //LN
  unsigned char architecture;
  unsigned int length; //Without _lnHeader
  unsigned int lnHeaderLength;
  unsigned char permissions;
  unsigned char typeOfExecutable;
  unsigned int flowSegment;
  unsigned int dataSegment;
  unsigned int loaderSegment;
  unsigned int cleanerSegment;
  unsigned int errorSegment;
  unsigned int exportTable;
  unsigned int importTable;
  unsigned int authenticationTable; //Encrypt it with GPG.
  unsigned int loaderTable;
};

I load executable, which is in little-endian, by using std::fstream:

lnFile.open(argv[1], std::fstream::in | std::fstream::binary);
if (false == lnFile.is_open())
 throw (unableToOpen);
lnSize = getFileSize(lnFile);
lnImage = new (std::nothrow) unsigned char [lnSize];
if (0 == lnImage)
 throw (noMem);
lnFile.read(reinterpret_cast<char*>(lnImage), lnSize); //#1 Possible mistake?
if (!lnFile)
 throw (unableToRead);
lnFile.close();

Then I point _lnHeader32* to allocated lnImage:

lnHeader32 = reinterpret_cast<_lnHeader32*>(lnImage);

At final I print whole struct by two methods:

//Method 1
std::cout << reinterpret_cast<unsigned int*>(lnImage) << "\n";
std::cout << reinterpret_cast<unsigned int*>(lnImage+2) << "\n";
std::cout << reinterpret_cast<unsigned int*>(lnImage+3) << "\n";
std::cout << reinterpret_cast<unsigned int*>(lnImage+7) << "\n";
std::cout << reinterpret_cast<unsigned int*>(lnImage+11) << "\n";
std::cout << reinterpret_cast<unsigned int*>(lnImage+12) << "\n\n";

//Method 2    
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->signature) << "\n";
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->architecture) << "\n";
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->length) << "\n";
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->lnHeaderLength) << "\n";
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->permissions) << "\n";
std::cout << reinterpret_cast<unsigned int*>(&lnHeader32->typeOfExecutable) 
                                                                  << "\n\n";

It gives Me output like:

0xe8b260
0xe8b262
0xe8b263 <---
0xe8b267
0xe8b26b
0xe8b26c

0xe8b260
0xe8b262
0xe8b264 <--- Should be 0xe8b263 | Here starts problem
0xe8b268
0xe8b26c
0xe8b26d

It prints well lnHeader32's fields by using first method, but I prefer to use second method. I calculated everything few times. Why it is happening? Executable is generated by compiler done in perl, has it any influence?

4
  • 5
    en.wikipedia.org/wiki/Data_padding Commented Jan 26, 2014 at 10:56
  • Using nothrow new, only to check the result for null and then throw is a real WTF? Commented Jan 26, 2014 at 11:04
  • Now everything is fine. Thank You, Oli Charlesworth. Commented Jan 26, 2014 at 11:04
  • if( false == data.isOpen() ) Arghhh, thats the most horrible boolean condition I have ever seen Commented Jan 26, 2014 at 11:05

2 Answers 2

3

Due to padding (see https://en.wikipedia.org/wiki/Data_padding) your struct actually looks like this:

struct _lnHeader32 {
  unsigned char signature[2]; //LN
  unsigned char architecture;
  unsigned char PADDING[1];//so next member will be aligned by 4
  unsigned int length; //Without _lnHeader
  unsigned int lnHeaderLength;
  unsigned char permissions;
  unsigned char typeOfExecutable;
  unsigned char PADDING[2];//so next member will be aligned by 4
  unsigned int flowSegment;
  unsigned int dataSegment;
  unsigned int loaderSegment;
  unsigned int cleanerSegment;
  unsigned int errorSegment;
  unsigned int exportTable;
  unsigned int importTable;
  unsigned int authenticationTable; //Encrypt it with GPG.
  unsigned int loaderTable;
};
Sign up to request clarification or add additional context in comments.

Comments

1

Fields of C++ types in memory are not necessary continuous, there are certain rules controlling when the compiler introduce padding between the fields.

Fields of different types are usually aligned at a pre-determined boundary. In this case char has the size of 1 byte, and it is 1-aligned, int has the size of 4 bytes and it is 4-aligned. (You can find more details about this here).

So your struct is going to look like this in memory

0: signature[0]
1: signature[1]
2: architecture
3: PADDING!
4: first byte of length
...

And you are getting an incorrect value for the length field because of the padding.

I would advise you against reading raw data into memory and reinterpret_casting it to a certain type. This could be very dangerous, because you can hardly be sure how your compiler aligns your type in memory.

A far more secure solution would be to create a helper function, like

_lnHeader32 readLnHeader32(const char* binary);

and in this function read the fields of the _lnHeader32 struct one by one from the binary stream read from the file.

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.