Read/Parse PE



  • I all, i have dll file stored in my webserver, with the QNetworkManager i call a php page that print the dll in hex format.

    In my qt application i read this bytes and stored to QByteArray,convert it form hex format.
    Now i want to parse this bytes for check if is valid image dll,if have valid NT header and other things.
    The problem is that when convert the bytes to data() i get output only the MZ Dos header.

    I want all correct char format of the dll.Someone can help me?
    this is my function:

    QByteArray result=reply->readAll();
    result=QByteArray::fromHex(result);
    
    char *buffer=result.data();
    
    PIMAGE_DOS_HEADER pIDH;
    PIMAGE_NT_HEADERS pINH;
    HANDLE hProcess;
     LPVOID moduleBase,stubBase;
    
            pIDH=(PIMAGE_DOS_HEADER)buffer;
            if(pIDH->e_magic!=IMAGE_DOS_SIGNATURE)
                throw QString("Invalid DOS Header found in image.");
    
            pINH=(PIMAGE_NT_HEADERS)((LPBYTE)buffer+pIDH->e_lfanew);
            if(pINH->Signature!=IMAGE_NT_SIGNATURE)
                throw QString("Invalid NT Header found in image.");
    

    I think the problem is the null terminator string present in the bytes array.
    How i can bypass this problem?Search more solution without success.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Out of curiosity, why download that DLL in hex ?



  • Because the dll its cryped with xor and converted to hex and uploaded to webserver.
    I tried to remove xor and hex and upload original dll to server, the bytes are downloaded correctly , infact if i make a file and write to it this bytes works perfect like:

    File *file;
    fopen("C:/test.dll","w");
    fwrite(result.data(),1,result.size(),file);
    fclose(file);
    

    The dll was created succesdfully.
    But if i make a pointer like:

    char* buffer=result.data();
    

    and parse this char* to validate dll header, the buffer contains only MZ header, and the size of buffer is 8.


  • Qt Champions 2016

    @BadCoder
    No, the null terminator doesn't play. You might be having some problem with structure alignment, or the compiler having trouble static casting the pointer. Have you tried it like this:

    PIMAGE_DOS_HEADER pIDH = reinterpret_cast<PIMAGE_DOS_HEADER>(result.data());
    PIMAGE_NT_HEADERS pINH = reinterpret_cast<PIMAGE_NT_HEADERS>(result.data() + pIDH->e_lfanew);
    

    Additionally I don't see any mention of IMAGE_DOS_HEADER in the MSDN, isn't that obsolete?
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms680198(v=vs.85).aspx



  • casting the buffer is useless, my problem is that if i want to know the lenght of result.data() , this return 3 and if i want know the sizeof result.data() it return 8.

    Than there is a problem with result.data().
    Else if i directly make File and write this bytes , if i open file i see all correct bytes!
    I don't want store to local hd the dll for this motive i want to parse the pointer data for validate PE image file!

    http://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html
    Little example of IMAGE_DOS_HEADER structure!
    If you open all portable executable with CFF Explorer you can see this struct :D


  • Qt Champions 2016

    @BadCoder said:

    if i want to know the lenght of result.data() , this return 3 and if i want know the sizeof result.data() it return 8.

    How do you get those sizes, with strlen() and/or sizeof()?

    PS.
    If you're using either of these two, you're simply doing it wrong. Use QByteArray::size() to get the number of bytes stored in the buffer.



  • Yes i know that but i need te buffer pointer for validate PE image and this buffer contains only MZ chars.

    PIMAGE_DOS_HEADER pIDH;
    PIMAGE_NT_HEADERS pINH;
    HANDLE hProcess;
     LPVOID moduleBase,stubBase;
    
            pIDH=(PIMAGE_DOS_HEADER)buffer;
            if(pIDH->e_magic!=IMAGE_DOS_SIGNATURE)
                throw QString("Invalid DOS Header found in image.");
    

    The buffer don't contains all correct char than i get invalid NT Header.


  • Qt Champions 2016

    @BadCoder
    Above you said that this code:

    File *file;
    fopen("C:/test.dll","w");
    fwrite(result.data(),1,result.size(),file);
    fclose(file);
    

    works as expected, which means that the buffer does contain all the needed data and there is no problem with QByteArray::data(). My guess is you're interpreting the file structure erroneously. I suggest looking up these links:
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms680198(v=vs.85).aspx
    https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files#File_Format
    https://upload.wikimedia.org/wikipedia/commons/7/70/Portable_Executable_32_bit_Structure_in_SVG.svg
    http://code.cheesydesign.com/?p=572

    I'm not an expert, and this is certainly very specific for each version of windows and architecture (x86, x64) you're targeting, so the reading of the loader information table might not be at all a trivial task.



  • Your linked solution is useless because i know the struct of PE (Portable Executable).
    My asnwer is another,why if i write the file dll stored in the hd contains all correct bytes else if i try to show to debug like:

    qDebug()<<result.data();
    

    this show me only the MZ chars and not all content of result array?
    Infact the IMAGE_DOS_HEADER doesn't show an error else IMAGE_NT_HEADERS yes.


  • Moderators

    It's probably because QByteArray::data() returns a char*, if you print it out then the first zero byte is interpreted as string end (like c style string).


  • Moderators

    What happens if you do

    qDebug()<<result;
    


  • qDebug()<<result.data();
    

    print only MZ char.
    This rappresent the bytes of a dll;
    Example of dll bytes

    Yes the problem is data result.data() return char* that contains NULL char,than my problem is how i can allocate new char* with all correct char?

    qDebug()<<result;
    

    nothings happens.Debug is empty!


  • Moderators

    Why do you want to allocate new memory?
    result already contains your data.
    Did you try to do like this as I suggested above:

    qDebug()<<result;
    

    As kshegunov said you should use QByteArray::size() to get the number of bytes and not strlen() or sizeof().



  • Ok the result array contains all correct bytes and the size of it print out the correct len.
    Now i need to check if this bytes contains a valid dll image,for that i need to cast it like:

    PIMAGE_DOS_HEADER pIDH=(PIMAGE_DOS_HEADER)buffer;
    

    i can't cast QByteArray to PIMAGE_DOS_HEADER, for this motive i need char* ,
    but the result.data() contains only the MZ char when cast it.
    Infact i get valid DOS header but invalid NT Header.


  • Moderators

    "but the result.data() contains only the MZ char when cast it" - that is wrong, the char* points to the whole content of the byte array, but this array contains zero bytes which are interpreted as end of string if you treat the char* as string. You need to parse it differently. How, depends on the content, since I do not know the structure of the content a cannot say how you should parse it.



  • Ok i fixed it!The thread can be closed!


  • Lifetime Qt Champion

    You can mark the thread as solved using the "Topic Tool" button :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.