Při práci s PE (Portable Executable) soubory dřív nebo později každý zjistí, že neustálé kopírování stejného kódu/funkcí (v lepším případě) nebo jeho stálé znovuvytváření (v horším případě), je vyloženě ztráta času. Proto jsem před časem vytvořil DLL knihovnu, která aktuálně obsahuje 17 funkcí pro práci s raw soubory (nespuštěné soubory uložené na disku).

V budoucnu (pokud najdu dost chuti a času) by tato knihovna měla být postupně rozšiřována o další funkce. Při návrhu byl brán ohled hlavně na jednoduchost použití (většinou stačí použít jeden jediný argument). Snažil jsem se vyhnout masivní blbuvzdornosti, protože předpokládám, že s knihovnou budou pracovat lidé, kteří již o PE souborech něco vědí a ví, jak ji používat.

DLL_PE_image_0_1.rar

Jednoduchá ukázka použití:

#include <windows.h>
#include <stdio.h>
 
int main(){
    char *szFile = "C:\\WINDOWS\\system32\\calc.exe";
    char *szDllName = "PE_image.dll";
 
    HANDLE hFile, hMapFile;
    LPVOID lpMappedFile;
    HMODULE hMyDll;
    DWORD dwLoSize;
 
    PIMAGE_DOS_HEADER pImageDos;
    PIMAGE_NT_HEADERS pImageNt;
    PIMAGE_FILE_HEADER pImageFile;
    PIMAGE_OPTIONAL_HEADER pImageOptional;
 
    // nahraje knihovnu do pameti
    ////////
    hMyDll = LoadLibrary(szDllName);
 
    if(hMyDll == NULL){
        printf("Nepovedlo se nacist DLL knihovnu.\n");
        return 4;
    }
 
    // vytvori/otevre specifikovany soubor pro cteni
    ////////
    hFile = CreateFile(szFile,
                       GENERIC_WRITE | GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
 
    if(!hFile){
        printf("Nepovedlo se otevrit soubor.\n");
        FreeLibrary(hMyDll);
        return 1;
    }
 
    dwLoSize = GetFileSize(hFile, 0);
 
    // vytvori/otevre namapovani daneho souboru
    ////////
    hMapFile = CreateFileMapping(hFile,
                                 0,
                                 PAGE_READWRITE,
                                 0,
                                 dwLoSize,
                                 0);
 
    if(!hMapFile){
        printf("Nepovedlo se vytvorit namapovany objekt.\n");
        FreeLibrary(hMyDll);
        CloseHandle(hFile);
        return 2;
    }
 
    // namapuje objekt do adresniho prostoru volaneho procesu
    ////////
    lpMappedFile = MapViewOfFile(hMapFile,
                                 FILE_MAP_ALL_ACCESS,
                                 0,
                                 0,
                                 dwLoSize);
 
    if(!lpMappedFile){
        printf("Nepovedlo se namapovat objekt.\n");
        FreeLibrary(hMyDll);
        CloseHandle(hMapFile);
        CloseHandle(hFile);
        return 3;
    }
 
    // ziskani adres funkci z DLL_image.dll
    ////////
    FARPROC GetDosHeader = GetProcAddress(hMyDll, "GetDosHeader@4");
    FARPROC GetNTHeaders = GetProcAddress(hMyDll, "GetNTHeaders@4");
    FARPROC GetFileHeader = GetProcAddress(hMyDll, "GetFileHeader@4");
    FARPROC GetOptionalHeader = GetProcAddress(hMyDll, "GetOptionalHeader@4");
 
    // pouziti ziskanych funkci z DLL_image.dll
    ////////
    pImageDos = (PIMAGE_DOS_HEADER)GetDosHeader(lpMappedFile);
    pImageNt = (PIMAGE_NT_HEADERS)GetNTHeaders(lpMappedFile);
    pImageFile = (PIMAGE_FILE_HEADER)GetFileHeader(lpMappedFile);
    pImageOptional = (PIMAGE_OPTIONAL_HEADER)GetOptionalHeader(lpMappedFile);
 
    // par ukazkovych dat z calc.exe
    ////////
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf("*-*-*-*- IMAGE_DOS_HEADER *-*-*-*-*\n");
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf(" e_magic:    %x\n", pImageDos->e_magic);
    printf(" e_lfanew: 0x%p\n\n", pImageDos->e_lfanew);
 
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf("*-*-*-*- IMAGE_NT_HEADERS *-*-*-*-*\n");
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf(" Signature:                   %x\n", pImageNt->Signature);
    printf(" IMAGE_FILE_HEADER RVA:     0x%p\n", pImageNt->FileHeader);
    printf(" IMAGE_OPTIONAL_HEADER RVA: 0x%p\n\n", pImageNt->OptionalHeader);
 
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf("*-*-*-*- IMAGE_FILE_HEADER -*-*-*-*\n");
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf(" NumberOfSections:     %d\n", pImageFile->NumberOfSections);
    printf(" SizeOfOptionalHeader: %d B\n\n", pImageFile->SizeOfOptionalHeader);
 
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf("*-*-*- IMAGE_OPTIONAL_HEADER -*-*-*\n");
    printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf(" ImageBase:           0x%p\n", pImageOptional->ImageBase);
    printf(" AddressOfEntryPoint: 0x%p\n", pImageOptional->AddressOfEntryPoint);
    printf(" BaseOfCode:          0x%p\n", pImageOptional->BaseOfCode);
    printf(" BaseOfData:          0x%p\n\n", pImageOptional->BaseOfData);
 
    FreeLibrary(hMyDll);
    UnmapViewOfFile(lpMappedFile);
    CloseHandle(hMapFile);
    CloseHandle(hFile);
 
    return 0;
}