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 :
- Signature
- IMAGE_FILE_HEADER
- 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