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? Commented Dec 20, 2021 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 Commented Dec 21, 2021 at 2:26

1 Answer 1

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 Commented Dec 21, 2021 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. Commented Dec 21, 2021 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 Commented Dec 21, 2021 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 Commented Dec 22, 2021 at 18:44

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.