NO

Author Topic: How to parse PE Export table?  (Read 6599 times)

Offline bitcoin

  • Member
  • *
  • Posts: 179
How to parse PE Export table?
« on: October 30, 2020, 01:18:09 PM »
Hello.
I try to parse PE export table, but it crashes every time. Where I can get good sample in C to parse Pe file? EXEDUMP from Matt Pietrek also fails..
Crashes in AddressOfNames Array.

Code: [Select]
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define MakePtr(Type, Base, Offset) ((Type)(DWORD(Base) + (DWORD)(Offset)))
#define offsetof(st, m) ((size_t)&(((st *)0)->m))

void Err(char *err)
{
    printf("%s\n",err);
}

void inf(char *inf)
{
    printf("%s\n",inf);
}



LPBYTE OpenPEFileA(LPCSTR lpszFileName)
{
  HANDLE hMapping,hFile;
  LPBYTE pBase = NULL;
  hFile = CreateFileA(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if (hFile == INVALID_HANDLE_VALUE)
  {
    Err("Cannot open file (CreateFile)");
    return NULL;
  }

  hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  CloseHandle(hFile);

  if (hMapping != NULL)
    {
    pBase = (LPBYTE)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
    CloseHandle(hMapping);
    }
  return pBase;
}

void ClosePEFile(LPBYTE pBase)
{
  if (pBase != NULL)
    UnmapViewOfFile(pBase);
}


char * mem_alloc()
{
char *lpMem = NULL;

lpMem = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,256);
if (lpMem == NULL)
        Err("HeapAlloc err");
return lpMem;
}


DWORD Rva2Raw(LPVOID pe, DWORD_PTR dwRVA)
{
DWORD dwRawRvaAddr = 0;
PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS nt;
dos = (PIMAGE_DOS_HEADER)pe;
nt = (PIMAGE_NT_HEADERS)(((DWORD_PTR)pe) + dos->e_lfanew);
PIMAGE_SECTION_HEADER pSections = IMAGE_FIRST_SECTION(nt);

if (!pSections)
{
return dwRawRvaAddr;
}

while (pSections->VirtualAddress != 0)
{
if (dwRVA >= pSections->VirtualAddress && dwRVA < pSections->VirtualAddress + pSections->SizeOfRawData)
{
dwRawRvaAddr = (dwRVA - pSections->VirtualAddress) + pSections->PointerToRawData;
break;
}
pSections++;
}

return dwRawRvaAddr;
}

int main(int argc,char *argv[])
{
LPBYTE PE = NULL;
IMAGE_DOS_HEADER* pDosHeader;
IMAGE_NT_HEADERS* pNtHeader;
int tmp = 0;
char file_name[64] = {0};

char *pe_magic,*pe_cblp,*pe_lfanew;
char *pSignature,*pMachine,*pMagic,*pTimeDateStamp;

goto X;

if (argc < 2)
{
 printf("Error usage: %s xyz.pe\n",argv[0]);
 return 1;
}

X:
//PE = OpenPEFileA(argv[1]);
PE = OpenPEFileA("1.dll");
pDosHeader = (IMAGE_DOS_HEADER*)PE;

if (pDosHeader->e_lfarlc >= 0x40)
{
    inf("This is PE file");
}

pNtHeader = (IMAGE_NT_HEADERS*)(PE +  pDosHeader->e_lfanew);


DWORD dwRva = Rva2Raw(PE,pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

PIMAGE_EXPORT_DIRECTORY pIED = (PIMAGE_EXPORT_DIRECTORY)(PE + dwRva);

PDWORD functions,names;
PWORD ordinals;
unsigned char *name;

DWORD base = (DWORD)pDosHeader;
//DebugBreak();
PSTR filename = (PSTR)(pIED->Name + base);

printf("rva is %x FN is %d %d!!!\n",dwRva,pIED->NumberOfFunctions,base);

DWORD nSize = pIED->Name;

functions = (PDWORD)(PE + Rva2Raw(PE,pIED->AddressOfFunctions));
ordinals = (PWORD)(PE + Rva2Raw(PE,pIED->AddressOfNameOrdinals));
names = (PDWORD)(PE + Rva2Raw(PE,pIED->AddressOfNames));
name = (PCHAR)(PE + Rva2Raw(PE,pIED->AddressOfNames));
//HERE fails! in name array
for (int i=0; i < pIED->NumberOfNames; i++ )
{
printf("  %08X  %4u  %s \n", *functions, *ordinals + pIED->Base,*name);
names++; // Bump each pointer to the next array element
ordinals++;
functions++;
}
ClosePEFile(PE);
    return 0;
}

Offline algernon_77

  • Member
  • *
  • Posts: 33
Re: How to parse PE Export table?
« Reply #1 on: October 30, 2020, 02:41:25 PM »
Hi!

Some years ago, I've built a DLL based on Matt Pietrek work on Microsoft PE. I've revised it recently and uploaded to Github, you can find it here:

https://github.com/yo3gfh/pehlp32

As I remember, both 32 and 64 bit should work. My initial code also crashed on enum exports/imports, mainly because pointer arithmetic :)
Should be ok now, but I don't guarantee it :)

I also have an example project for testing the library:
https://github.com/yo3gfh/procview

Hope you find something useful, but all the bugs are mine :)

I forgot to add, Matt Pietrek updated the initial PEDUmp code, here you can find the article:

http://bytepointer.com/resources/pietrek_in_depth_look_into_pe_format_pt1.htm/

In PEHlp32 github page, you can also find the latest version of Matt's utility (PEDump.zip).
Good luck!
 
« Last Edit: October 30, 2020, 02:46:02 PM by algernon_77 »

Offline Vortex

  • Member
  • *
  • Posts: 864
    • http://www.vortex.masmcode.com
Re: How to parse PE Export table?
« Reply #2 on: May 13, 2021, 11:52:40 AM »
Hi bitcon,

Here is a quick example, the code below displays the function names exported by kernel32.dll

Code: [Select]
#include <windows.h>
#include <stdio.h>

int main(void)
{
HMODULE hMod;
PIMAGE_NT_HEADERS pNThdr;
PIMAGE_EXPORT_DIRECTORY pDesc;
DWORD NumbOfNames,i;
DWORD* AddrOfNames;

hMod=LoadLibrary("kernel32.dll");

pNThdr=(PIMAGE_NT_HEADERS)((LPBYTE)hMod + ((PIMAGE_DOS_HEADER)hMod)->e_lfanew);

pDesc=(PIMAGE_EXPORT_DIRECTORY)((LPBYTE)hMod + pNThdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

NumbOfNames =  pDesc -> NumberOfNames;

AddrOfNames = (DWORD *)((LPBYTE)hMod + pDesc -> AddressOfNames);

for(i=0;i<NumbOfNames;i++)
{
printf("%s\n",(*AddrOfNames+(LPBYTE)hMod));

AddrOfNames=AddrOfNames+1;
}

FreeLibrary(hMod);
return 0;
}
« Last Edit: May 13, 2021, 12:12:40 PM by Vortex »
Code it... That's all...

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: How to parse PE Export table?
« Reply #3 on: May 16, 2021, 12:54:58 PM »
Thank you friends.