Convert char array to integer value

0

I'm having a bit of a trouble figuring out the correct calculation of WORD, DWORD etc. I'm having kind of a knot in my brain, probably sitting on this problem for too long.

I'm reading a PE-section header. So far everything is ok. Here is a sample output from a random .exe file:

File is 286 Kbytes large
PE-Signature [@ 0x108]
0x00000100: ........ ........ 504500

Collect Information (PE file header):
[WORD]  Mashinae Type          :014C
[WORD]  Number of Sections     :0006
[DWORD] TimeStamp              :5C6ECB00
[DWORD] Pointer to symbol table:00000000
[DWORD] Number of Symbols      :00000000
[WORD]  Size of optional header:00E0

Now, as you see the size of the "optional" header is 0x00E0, so I was trying to buffer that for later. (Bc. it would make things faster to just read the complete header).

Where I'm having problems is the point where I am to convert the little-endian values to an actual integer. I need to read the value from behind (so the second WORD [ 00 ] is actually the first value to be read). The second value, however, needs to be shifted in some way (bc. significance of bytes), and this is where I am struggeling. I guess the solution is not that hard, I just ran out of wisdom lol.

Here is my draft for a function that should return an integer value with the value:

 //get a specific value and safe it for later usage
 int getValue(char* memory, int start, int end)
 {
   if (end <= start)
       return 0;

   unsigned int retVal = 0;

   //now just add up array fields 
   for (int i = end; i >= start; i--)
   {
       fprintf(stdout, "\n%02hhx", memory[i]);
       retVal &= (memory[i] << 8 * (i- start));
   }
   fprintf(stdout, "\n\n\n%d",retVal);

   return retVal;
}

In other words, I need to parse an array of hex values (or chars) to an actual integer, but in respect of the significance of the bytes.

Also: [Pointer to symbol table] and [Number of Symbols] seem to always be 0. I'm guessing this is due to the fact the binary is stripped of symbols, but I'm not sure since I am more an expert on Linux Binary Analysis. Is my asumption correct?

c++
binary
hex
portable-executable
asked on Stack Overflow Dec 6, 2019 by clockw0rk • edited Dec 6, 2019 by Filburt

2 Answers

1

I really hope that this helps you. From what I understood so far this will grab the bytes that are within the start to end range and will place them in an integer:

// here I am converting the chars from hex to int
int getBitPattern(char ch)
{
    if (ch >= 48 && ch <= 57)
    {
        return ch - '0';
    }
    else if (ch >= 65 && ch <= 70)
    {
        return ch - 55;
    }
    else
    {
        // this is in case of invalid input
        return -1;
    }
}


int getValue(const char* memory, int start, int end)
{
    if (end <= start)
        return 0;

    unsigned int retVal = 0;

    //now just add up array fields 
    for (int i = end, j = 0; i >= start; i--, ++j)
    {
        fprintf(stdout, "\n%02hhx", memory[i]);
        // bitshift in order to insert the next set of 4 bits into their correct spot
        retVal |= (getBitPattern(memory[i]) << (4*j));
    }
    fprintf(stdout, "\n\n\n%d", retVal);
    return retVal;
}

answered on Stack Overflow Dec 6, 2019 by bhristov
0

boyanhristov96 helped a lot by pointing out the usage of the OR operator instead of AND and it was his / her effort that lead to this solution

A cast to (unsigned char) also had to be made before shifting.

If not, the variable will simply be shifted over it's maximum positive range,
resulting in the value

0xFFFFE000 (4294959104)

instead of the desired 0x0000E000 (57344)

We have to left-shift by 8, because we want to shift 2 16bit values at once, like in

0x00FF00 << 8 ; // after operation is 0xFF0000

The final function also uses an OR, here is it:

//now with or operation and cast
int getValue(const char* memory, int start, int end)
{
if (end <= start)
    return 0;

unsigned int retVal = 0;

//now just add up array fields 
for (int i = end, j = end-start; i >= start; i--, --j)
{
    fprintf(stdout, "\n%02hhx", memory[i]);
    retVal |= ((unsigned char)(memory[i]) << (8 * j));
}
fprintf(stdout, "\n\n\n%u", retVal);
return retVal;

}

Many thanks for helping

EDIT 16.12.2019:

Returning back here for updated version of function; It was necassary to rewrite it for 2 reasons: 1) The offset to PE-Header depends on the target binary, so we have to get this value first (at location 0x3c). Then, use a pointer to move from value to value from there. 2) The calculations where shambled, I corrected them, now it should work as intended. The second parameter is the byte-length, f.e. DWORD - 4 byte

Here you go:

//because file shambles
int getValuePNTR(const char* memory, int &start, int size)
{
    DWORD retVal = 0;

    //now just add up array fields 
    for (int i = start + size-1,j = size-1; j >= 0; --j ,i--)
    {

        fprintf(stdout, "\ncycle: %d, memory: [%x]", j, memory[i]);

        if ((unsigned char)memory[i] == 00 && j > 0)
            retVal <<= 8;
        else
            retVal |= ((unsigned char)(memory[i]) << (8 * j));
        //else
            //retVal |= ((unsigned char)(memory[i]));


    }
    //get the next field after this one
    start += size;
    return retVal;
}
answered on Stack Overflow Dec 7, 2019 by clockw0rk • edited Dec 17, 2019 by clockw0rk

User contributions licensed under CC BY-SA 3.0