Skip to content

coderforlife/pe-file

Repository files navigation

pe-file

Basic utility code for reading and modifying PE files (EXE, DLL, ...)

This is simply code and not a program. It could easily be compiled into a DLL and expose the PEFile class.

When compiling commenting out EXPOSE_DIRECT_RESOURCES causes direct resource access to be completely blocked and not expose the underlying resource classes. However resources are still accessible though other functions.

The interface is as follows:

class PE::File {
public:
    File(LPVOID data, size_t size, bool readonly = false); // data is freed when the PEFile is deleted
    File(LPCWSTR filename, bool readonly = false);
    ~File();
    bool isLoaded() const;
    bool isReadOnly() const;

    bool save(); // flushes

    bool is32bit() const;
    bool is64bit() const;
    ULONGLONG getImageBase() const;

    IMAGE_FILE_HEADER *getFileHeader();				// pointer can modify the file
    IMAGE_NT_HEADERS32 *getNtHeaders32();			// pointer can modify the file
    IMAGE_NT_HEADERS64 *getNtHeaders64();			// pointer can modify the file
    const IMAGE_FILE_HEADER *getFileHeader() const;
    const IMAGE_NT_HEADERS32 *getNtHeaders32() const;
    const IMAGE_NT_HEADERS64 *getNtHeaders64() const;

    DWORD getDataDirectoryCount() const;
    IMAGE_DATA_DIRECTORY *getDataDirectory(int i);	// pointer can modify the file
    const IMAGE_DATA_DIRECTORY *getDataDirectory(int i) const;

    IMAGE_SECTION_HEADER *getSectionHeader(int i);							// pointer can modify the file
    IMAGE_SECTION_HEADER *getSectionHeader(const char *str, int *i = NULL);	// pointer can modify the file
    IMAGE_SECTION_HEADER *getSectionHeaderByRVA(DWORD rva, int *i);			// pointer can modify the file
    IMAGE_SECTION_HEADER *getSectionHeaderByVA(ULONGLONG va, int *i);		// pointer can modify the file
    const IMAGE_SECTION_HEADER *getSectionHeader(int i) const;
    const IMAGE_SECTION_HEADER *getSectionHeader(const char *str, int *i = NULL) const;
    const IMAGE_SECTION_HEADER *getSectionHeaderByRVA(DWORD rva, int *i) const;
    const IMAGE_SECTION_HEADER *getSectionHeaderByVA(ULONGLONG va, int *i) const;
    int getSectionHeaderCount() const;

    IMAGE_SECTION_HEADER *getExpandedSectionHdr(int i, DWORD room);		// pointer can modify the file, invalidates all pointers returned by functions, flushes
    IMAGE_SECTION_HEADER *getExpandedSectionHdr(char *str, DWORD room);	// as above

#define CHARS_CODE_SECTION			IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
#define CHARS_INIT_DATA_SECTION_R	IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
#define CHARS_INIT_DATA_SECTION_RW	IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

    IMAGE_SECTION_HEADER *createSection(int i, const char *name, DWORD room, DWORD chars);				// pointer can modify the file, invalidates all pointers returned by functions, flushes
    IMAGE_SECTION_HEADER *createSection(const char *str, const char *name, DWORD room, DWORD chars);	// as above, adds before the section named str
    IMAGE_SECTION_HEADER *createSection(const char *name, DWORD room, DWORD chars);						// as above, adds before ".reloc" if exists or at the very end

    size_t getSize() const;
    bool setSize(size_t dwSize, bool grow_only = true);				// invalidates all pointers returned by functions, flushes

    LPBYTE get(DWORD dwOffset = 0, DWORD *dwSize = NULL);			// pointer can modify the file
    const LPBYTE get(DWORD dwOffset = 0, DWORD *dwSize = NULL) const;
    bool set(const LPVOID lpBuffer, DWORD dwSize, DWORD dwOffset);	// shorthand for memcpy(f->get(dwOffset), lpBuffer, dwSize) with bounds checking
    bool zero(DWORD dwSize, DWORD dwOffset);						// shorthand for memset(f->get(dwOffset), 0, dwSize) with bounds checking
    bool move(DWORD dwOffset, DWORD dwSize, int dwDistanceToMove);	// shorthand for x = f->get(dwOffset); memmove(x+dwDistanceToMove, x, dwSize) with bounds checking
    bool shift(DWORD dwOffset, int dwDistanceToMove);				// shorthand for f->move(dwOffset, f->getSize() - dwOffset - dwDistanceToMove, dwDistanceToMove)
    bool flush();

    bool updatePEChkSum();				// flushes
    bool hasExtraData() const;
    LPVOID getExtraData(DWORD *size);	// pointer can modify the file, when first enabling it will flush
    bool clearCertificateTable();		// may invalidate all pointers returned by functions, flushes
    ULONGLONG getFileVersion() const;
    bool isAlreadyModified() const;
    bool setModifiedFlag();				// flushes
    bool removeRelocs(DWORD start, DWORD end, bool reverse = false);

#ifdef EXPOSE_DIRECT_RESOURCES
    Rsrc *getResources();
    const Rsrc *getResources() const;
#endif
    bool resourceExists(LPCWSTR type, LPCWSTR name, WORD lang) const;
    bool resourceExists(LPCWSTR type, LPCWSTR name, WORD* lang) const;
    LPVOID getResource (LPCWSTR type, LPCWSTR name, WORD lang, size_t* size) const;	// must be freed
    LPVOID getResource (LPCWSTR type, LPCWSTR name, WORD* lang, size_t* size) const;	// must be freed
    bool removeResource(LPCWSTR type, LPCWSTR name, WORD lang);
    bool addResource   (LPCWSTR type, LPCWSTR name, WORD lang, const LPVOID data, size_t size, DWORD overwrite = OVERWRITE_ALWAYS);

    static const LPVOID GetResourceDirect(const LPVOID data, LPCWSTR type, LPCWSTR name); // must be freed, massively performance enhanced for a single retrieval and no editing // lang? size?
    static bool UpdatePEChkSum(LPBYTE data, size_t dwSize, size_t peOffset, DWORD dwOldCheck);
    static bool GetVersionInfo(const LPVOID ver, LPCWSTR query, LPVOID *buffer, PUINT len);
    static VS_FIXEDFILEINFO *GetVersionInfo(const LPVOID ver);
    static void UnmapAllViewsOfFile(LPCWSTR file);
};

About

Basic utility code for reading and modifying PE files (EXE, DLL, ...)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published