C Code Parsing PE with Corkami Offset

Today, I want to write about small C code that enable you to listing out dll export and parsing some PE values from the headers. I created the code by following the guide from the Corkami made by Ange Albertini that you can download from

https://raw.githubusercontent.com/corkami/pics/master/binary/pe102/pe102.svg

I write my C code by following the offset specified by the guide so it is very easy to follow

Reading the IMAGE_NT_HEADERS

We can see the code below start by trying to find the offset 0x3C which is the common offset to find the file offset of new exe header or e_lfanew. Then we need to get 4 bytes to extract the value from that offset that guide to pointing us to the IMAGE_NT_HEADERS where in this case is F8. Highlighted below is the 0x3C offset and it points to F8

Below is the code to extract the value of the 0x3C into variable peheaderoffset

    FILE* file = fopen("C:\\Users\\pentest\\Desktop\\Work\\user32.dll", "rb");

    long peheaderoffset;

    // read the offset of the PE header which is located at offset 0x3c
    fseek(file, 0x3c, SEEK_SET);
    fread(&peheaderoffset, 4, 1, file); //read the offset --> e_lfanew

Reading the PE Signature

After we get e_lfanew offset from the 0x3C then we need to go again from the begining of the file by using fseek to F8

char PEHeader[4];  // PE header: contains normally 'P','E','\0','\0'
fseek(file, peheaderoffset, SEEK_SET);
fread(&PEHeader, 4, 1, file);

The code above will read 4 bytes from the the signature PE\0\0

The above code copy the 4 bytes from offset F8 which consist of 50 45 00 00 which equal to PE . .

Reading FILE HEADER

The PE file header consists of a Microsoft MS-DOS stub, the PE signature, the COFF file header, and an optional header. A COFF object file header consists of a COFF file header and an optional header. In both cases, the file headers are followed immediately by section headers

PE File header is a structure type named IMAGE_NT_HEADER which consists of three parts :

  1. Signature
  2. IMAGE_FILE_HEADER
  3. IMAGE _OPTIONAL_HEADER
    short machine_rio;
    fseek(file, peheaderoffset + 4, SEEK_SET);
    fread(&machine_rio, 2, 1, file);
    printf("machine_rio = %x\n", machine_rio);

    short numOfSection;
    fseek(file, peheaderoffset + 4 + 2 , SEEK_SET);
    fread(&numOfSection, 2, 1, file);
    printf("numOfSection = %x\n", numOfSection);

    long timedatastamp;
    fseek(file, peheaderoffset + 4 + 4, SEEK_SET);
    fread(&timedatastamp, 4, 1, file);
    printf("timedatastamp = %x\n", timedatastamp);

    long pointerToSymbolTable;
    fseek(file, peheaderoffset + 4 + 8, SEEK_SET);
    fread(&pointerToSymbolTable, 4, 1, file);
    printf("pointerToSymbolTable = %x\n", pointerToSymbolTable);
    
    long numberOfSymbols;
    fseek(file, peheaderoffset + 4 + 0x0c, SEEK_SET);
    fread(&numberOfSymbols, 4, 1, file);
    printf("numberOfSymbols = %x\n", pointerToSymbolTable);

    //Get sizeofOptionalHeader from File Header
    short sizeofOptionalHeader;
    fseek(file, peheaderoffset + 4 + 16, SEEK_SET);
    fread(&sizeofOptionalHeader, 2, 1, file);
    printf("sizeofOptionalHeader = %x\n", sizeofOptionalHeader);

    //Get Characteristic from File Header
    short characteristic;
    fseek(file, peheaderoffset + 4 + 18, SEEK_SET);
    fread(&characteristic, 2, 1, file);
    printf("characteristic = %x\n", characteristic);

Code output vs PE Bear

The above code follow the Corkami offset as follow

Reading Optional Header

 //Get The magic from optional hdr
    short magic;
    fseek(file, peheaderoffset + 0x18, SEEK_SET);
    fread(&magic, 2, 1, file);
    printf("magic = %x\n", magic);

Reading the IMAGE DATA DIRECTORY

The code below reads data directory structure like this below

typedef struct _IMAGE_DATA_DIRECTORY {
  DWORD VirtualAddress;
  DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

We can see that DWORD size is 4 bytes, So to manually read the bytes sequece of the above data structure then we need to read 4 bytes with times by 2 with additional offset from the Virtual Address reads

//Get the Export Directory RVA
DWORD exportDirectoryRVA;
fseek(file, peheaderoffset + 0x18 + 0x70, SEEK_SET);
fread(&exportDirectoryRVA, 4, 1, file);
printf("exportPointerVA = %x\n", exportDirectoryRVA);

//Get the size and adjust 4 bytes offset from the virtual address reads
DWORD exportDirectorySize;
fseek(file, peheaderoffset + 0x18 + 0x70 + 4, SEEK_SET);
fread(&exportDirectorySize, 4, 1, file);
printf("exportPointerSize = %x\n", exportDirectorySize);

Below is the mapping from the code to the Cokami PE map

The code output vs PE Bear

I will post the full C code in the next post which include listing the export API from the DLL

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s