Search code examples
cwinapiportable-executable

howto neatly modify a PE's datssection


I'm writing a dll in 'C/C++ - Win32API' environment. I have some constant variables (all are DWORD values and LPWSTR/LPSTR strings) that I have to enable the user modify. what I'm looking for is (hopefully) a tool that enable a SAFE binary modification as described, in a way that updates all the necessary tables of the PE.


Solution

  • You can create a struct in a separate PE section thus:

    // Create the section
    #pragma section("myconst", read)
    
    // Declare a struct to hold the constant data
    typedef struct
    {
        DWORD a;
        DWORD b;
        char stringa[256];
        char stringb[256];
    } ConstData;
    
    // Create an initialized instance of the struct in the new section
    __declspec(allocate("myconst"))
    const ConstData theData = {0xdeadbeef, 0xfeedface, "Hello", "dolly"};
    

    Compile the code. Open a Visual Studio Command Prompt, run

    dumpbin /all myexe.exe > dump.txt
    notepad dump.txt
    

    Search for the myconst section. You should see something like:

    SECTION HEADER #4
     myconst name
         208 virtual size
        4000 virtual address (00404000 to 00404207)
         400 size of raw data
        2000 file pointer to raw data (00002000 to 000023FF)
           0 file pointer to relocation table
           0 file pointer to line numbers
           0 number of relocations
           0 number of line numbers
    40000040 flags
             Initialized Data
             Read Only
    
    RAW DATA #4
      00404000: EF BE AD DE CE FA ED FE 48 65 6C 6C 6F 00 00 00  ï¾­ÞÎúíþHello...
      00404010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
      00404020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    

    You can see the two hex values that were initialised in the code and the first string value. You can also see that the offset of this data in the PE file - "file pointer to raw data" - is 0x2000.

    Armed with that information it is very easy to construct a new data block, open the PE file and overwrite the data at 0x2000.

    To determine the offset from code you need to parse the PE file header and section headers. This is fairly straightforward. Or you could grab the offset from the dumpbin output as part of your build process, and feed it into the build of the editing tool.

    Note that to test this in release mode you need to actually make use of theData or the linker will throw it away. Also note that the section only has the read attribute so it is truly read-only. Attempting to write it will give an access violation.

    And finally... This is all quite scruffy. I wouldn't bother unless you really have no alternative.