0

So I am wondering how can I get all sections and their info from a dumped PE file on the disk, using C++.

I have the entire PE loaded on a buffer, the NT headers, and hopefully the DOS headers.

I need this so I can transform a raw offset of the file into an offset that I can add to the base address and get my result.

2
  • Hi and welcome to RE.SE. Your question is actually worded a bit confusingly. Are you talking about a dumped PE file (essentially loaded with SEC_IMAGE and possibly relocated etc) or are you talking about a PE file, which you loaded into a buffer and now you want to make sense of the RVAs?
    – 0xC0000022L
    Dec 20 '21 at 23:41
  • 1
    I want to get the segment sections (.code, .data, etc) and their info (Raw offset, Raw size, Virtual offset, etc) from a PE file that was dumped while was running
    – rafa_br34
    Dec 21 '21 at 2:26
0

Assuming you have a binary dump created by say WinDbg .writemem

0:000> lm m cdb
start             end                 module name
00007ff6`af510000 00007ff6`af53e000   cdb        (deferred)

0:000> .writemem c:\dumped.bin 00007ff6`af510000 l?(00007ff6`af53e000-00007ff6`af510000)
Writing 2e000 bytes............................................................................................
0:000>

C++ does not have the glue to parse PE files. You may need to use the Windows API or roll your own parsing routines.

For example the first few bytes of the dump should be IMAGE_DOS_HEADER for it to be a valid PE file.

I will dump the section of the aforementioned dump using pefile by Ero a versatile PE parsing Python module.

Dumping the first section using the above module from command line

C:\>python -c "import pefile;print(pefile.PE(r\"c:\\dumped.bin\").sections[0]")
[IMAGE_SECTION_HEADER]
0x200      0x0   Name:                          .text
0x208      0x8   Misc:                          0xC1FF
0x208      0x8   Misc_PhysicalAddress:          0xC1FF
0x208      0x8   Misc_VirtualSize:              0xC1FF
0x20C      0xC   VirtualAddress:                0x1000
0x210      0x10  SizeOfRawData:                 0xC200
0x214      0x14  PointerToRawData:              0x400
0x218      0x18  PointerToRelocations:          0x0
0x21C      0x1C  PointerToLinenumbers:          0x0
0x220      0x20  NumberOfRelocations:           0x0
0x222      0x22  NumberOfLinenumbers:           0x0
0x224      0x24  Characteristics:               0x60000020

If you are going to use C basic routines

You may need to fopen(....) and fread();, then cast the bytes as DOS header, read e_lfanew as offset to the PE header, then continue to cast, read and parse until you finish.

A sample DOS header to PE header offset routine may look like:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define BUSIZ 0x50
#define MAXREAD 0x40

int main(void)
{
    FILE *infile = NULL;
    errno_t err = fopen_s(&infile, "c:\\dumped.bin", "rb");
    if (err == 0 && infile != NULL)
    {
        unsigned char buf[BUSIZ] = {0};
        size_t siz = 0;
        siz = fread_s(buf, BUSIZ, 1, MAXREAD, infile);
        if (siz != 0)
        {
            for (int i = 0; i < 16; i++)
            {
                printf("%02x ", buf[i]);
            }
            for (int i = 0; i < 16; i++)
            {
                printf("%c ", buf[i]);
            }
            printf("\n");
        }
        PIMAGE_DOS_HEADER dhead = (PIMAGE_DOS_HEADER)&buf;
        printf("%x\n", dhead->e_magic);
        printf("offset to PE Header from start = %x\n", dhead->e_lfanew);
    }
    else
    {
        printf("file not opened failure \n");
    }
}

compiled and executed

:\>cl /Zi /W4 /analyze /Od /EHsc /nologo parse.cpp /link /release
parse.cpp

:\>parse.exe
4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 M Z É                    
5a4d
offset to PE Header from start = f8

edit

a different demo for IMAGE_FIRST_SECTION

edit src that uses IMAGE_FIRST_SECTION to retrieve all section with 16 initial bytes at each section

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define BUSIZ 0x500
#define MAXREAD 0x400
FILE *infile = NULL;
unsigned char buf[BUSIZ] = {0};
unsigned char tmpbuf[BUFSIZ] = {0};
void hexdump(int bpos, unsigned char *inbuf){
    memset(inbuf, 0, BUSIZ);
    fseek(infile, bpos, SEEK_SET);
    size_t siz = fread_s(inbuf, BUSIZ, 1, MAXREAD, infile);
    if (siz != 0)    {
        for (int i = 0; i < 16; i++) {
            printf("%02x ", inbuf[i]);
        }
        printf("\n");
    }
}
int main(void){
    errno_t err = fopen_s(&infile, "c:\\dumped.bin", "rb");
    if (err == 0 && infile != NULL){
        hexdump(0, buf);
        PIMAGE_DOS_HEADER dhead = (PIMAGE_DOS_HEADER)&buf;
        hexdump(dhead->e_lfanew, buf);
        PIMAGE_NT_HEADERS64 nthead = (PIMAGE_NT_HEADERS64)&buf;
        PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(nthead);
        for (WORD i = 0; i < nthead->FileHeader.NumberOfSections; i++){
            printf("%-8s\t%x\t%x\t%x\n", Section->Name, Section->VirtualAddress,
                   Section->PointerToRawData, Section->SizeOfRawData);
            hexdump(Section->VirtualAddress, tmpbuf);
            Section++;
        }
    }
}

compiled and executed

>cl /Zi /W4 /analyze /Od /EHsc /nologo parse.cpp /link /release
parse.cpp

>parse.exe
4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 
50 45 00 00 64 86 08 00 00 1d 9c 8d 00 00 00 00 
.text           1000    400     c200
cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc 
.rdata          e000    c600    f800
b0 ff 52 af f6 7f 00 00 50 00 53 af f6 7f 00 00
.data           1e000   1be00   2000
60 e0 51 af f6 7f 00 00 90 e0 51 af f6 7f 00 00
.pdata          27000   1de00   800
10 10 00 00 88 10 00 00 4c ba 01 00 90 10 00 00
.didat          28000   1e600   200
92 ce 51 af f6 7f 00 00 00 00 00 00 00 00 00 00
.mrdata         29000   1e800   2e00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
.rsrc           2c000   21600   1000
00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00
.reloc          2d000   22600   a00
00 e0 00 00 28 02 00 00 00 a0 08 a0 10 a0 18 a0

confirmed independently with a hex editor

C:\>for %i in (0x0000,0x1000,0xe000,0x1e000,0x27000,0x28000,0x29000,0x2c000,0x2d000) do xxd -s %i -g 1 -l 16 dumped.bin

C:\>xxd -s 0x0000 -g 1 -l 16 dumped.bin
00000000: 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00  MZ..............

C:\>xxd -s 0x1000 -g 1 -l 16 dumped.bin
00001000: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ................

C:\>xxd -s 0xe000 -g 1 -l 16 dumped.bin
0000e000: b0 ff 52 af f6 7f 00 00 50 00 53 af f6 7f 00 00  ..R.....P.S.....

C:\>xxd -s 0x1e000 -g 1 -l 16 dumped.bin
0001e000: 60 e0 51 af f6 7f 00 00 90 e0 51 af f6 7f 00 00  `.Q.......Q.....

C:\>xxd -s 0x27000 -g 1 -l 16 dumped.bin
00027000: 10 10 00 00 88 10 00 00 4c ba 01 00 90 10 00 00  ........L.......

C:\>xxd -s 0x28000 -g 1 -l 16 dumped.bin
00028000: 92 ce 51 af f6 7f 00 00 00 00 00 00 00 00 00 00  ..Q.............

C:\>xxd -s 0x29000 -g 1 -l 16 dumped.bin
00029000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

C:\>xxd -s 0x2c000 -g 1 -l 16 dumped.bin
0002c000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00  ................

C:\>xxd -s 0x2d000 -g 1 -l 16 dumped.bin
0002d000: 00 e0 00 00 28 02 00 00 00 a0 08 a0 10 a0 18 a0  ....(...........
4
  • yes, I have the DOS and NT header already what I want are the sections info, like when you use alt+1 in PE editor and go-to sections
    – rafa_br34
    Dec 21 '21 at 6:00
  • 1
    Which PE editor you make it sounds as if there is a single one? As for PE-parsing you could have a look at pe-parse with which I worked a bit due to work with another project by the same group: uthenticode. Either way, a PE parser can be written easily and portably in C++. The parsing is no different in memory and on disk. Just the calculation of offsets differs due to file vs. section alignment.
    – 0xC0000022L
    Dec 21 '21 at 8:52
  • I'm using the PETools editor, I would like to get the segments the program has, and their information, I just need to find the right offset for the array. edit: sorry for the late response, thought StackOverflow would notify me, I don't think the IMAGE_FIRST_SECTION works for files on the disk
    – rafa_br34
    Dec 21 '21 at 12:39
  • maybe you can explain why you think so ??? it is a simple macro that retrieves the position of First Section in the PE header. anyway i edited in a modified source which dumps at start of each section
    – blabb
    Dec 22 '21 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.