#pragma once #include "../Config.h" #include "../Include/Winheaders.h" #include "../Include/Types.h" #include "../Include/HandleGuard.h" #include "../Misc/Utils.h" #ifdef COMPILER_MSVC #include "ImageNET.h" #endif // COMPILER_MSVC #include #include #include #include #include #include #include namespace blackbone { namespace pe { enum AddressType { RVA, // Relative virtual VA, // Absolute virtual RPA, // Relative physical }; // Relocation block information struct RelocData { ULONG PageRVA; ULONG BlockSize; struct { WORD Offset : 12; WORD Type : 4; }Item[1]; }; /// /// Import information /// struct ImportData { std::string importName; // Function name uintptr_t ptrRVA; // Function pointer RVA in WORD importOrdinal; // Function ordinal bool importByOrd; // Function is imported by ordinal }; /// /// Export function info /// struct ExportData { std::string name; uint32_t RVA = 0; ExportData( const std::string& name_, uint32_t rva_ ) : name( name_ ) , RVA( rva_ ) { } bool operator == (const ExportData& other) { return name == other.name; } bool operator < (const ExportData& other) { return name < other.name; } }; // Imports and sections related using mapImports = std::unordered_map>; using vecSections = std::vector; using vecExports = std::vector; /// /// Primitive PE parsing class /// class PEImage { using PCHDR32 = const IMAGE_NT_HEADERS32*; using PCHDR64 = const IMAGE_NT_HEADERS64*; public: BLACKBONE_API PEImage( void ); BLACKBONE_API ~PEImage( void ); /// /// Load image from file /// /// File path /// If true - do not initialize activation context /// Status code BLACKBONE_API NTSTATUS Load( const std::wstring& path, bool skipActx = false ); /// /// Load image from memory location /// /// Image data /// Data size. /// If false - data has image layout /// Status code BLACKBONE_API NTSTATUS Load( void* pData, size_t size, bool plainData = true ); /// /// Reload closed image /// /// Status code BLACKBONE_API NTSTATUS Reload(); /// /// Release mapping, if any /// /// Preserve file paths for file reopening BLACKBONE_API void Release( bool temporary = false ); /// /// Parses PE image /// /// Status code BLACKBONE_API NTSTATUS Parse( void* pImageBase = nullptr ); /// /// Processes image imports /// /// Process delayed import instead /// Import data BLACKBONE_API mapImports& GetImports( bool useDelayed = false ); /// /// Retrieve all exported functions with names /// /// Found exports BLACKBONE_API void GetExports( vecExports& exports ); /// /// Retrieve image TLS callbacks /// Callbacks are rebased for target image /// /// Target image base /// Found callbacks /// Number of TLS callbacks in image BLACKBONE_API int GetTLSCallbacks( module_t targetBase, std::vector& result ) const; /// /// Retrieve data directory address /// /// Directory index /// Keep address relative to image base /// Directory address BLACKBONE_API uintptr_t DirectoryAddress( int index, AddressType type = VA ) const; /// /// Get data directory size /// /// Data directory index /// Data directory size BLACKBONE_API size_t DirectorySize( int index ) const; /// /// Resolve virtual memory address to physical file offset /// /// Memory address /// Address type to return /// Resolved address BLACKBONE_API uintptr_t ResolveRVAToVA( uintptr_t Rva, AddressType type = VA ) const; /// /// Get image path /// /// Image path BLACKBONE_API inline const std::wstring& path() const { return _imagePath; } /// /// Get image name /// /// Image name BLACKBONE_API inline std::wstring name() const { return Utils::StripPath( _imagePath ); } /// /// Get image load address /// /// Image base BLACKBONE_API inline void* base() const { return _pFileBase; } /// /// Get image base address /// /// Image base BLACKBONE_API inline module_t imageBase() const { return _imgBase; } /// /// Get image size in bytes /// /// Image size BLACKBONE_API inline uint32_t imageSize() const { return _imgSize; } /// /// Get size of image headers /// /// Size of image headers BLACKBONE_API inline size_t headersSize() const { return _hdrSize; } /// /// Get image entry point rebased to another image base /// /// New image base /// New entry point address BLACKBONE_API inline ptr_t entryPoint( module_t base ) const { return ((_epRVA != 0) ? (_epRVA + base) : 0); }; /// /// Get image sections /// /// Image sections BLACKBONE_API inline const vecSections& sections() const { return _sections; } /// /// Check if image is an executable file and not a dll /// /// true if image is an *.exe BLACKBONE_API inline bool isExe() const { return _isExe; } /// /// Check if image is pure IL image /// /// true on success BLACKBONE_API inline bool pureIL() const { return _isPureIL; } BLACKBONE_API inline int32_t ilFlagOffset() const { return _ILFlagOffset; } /// /// Get image type. 32/64 bit /// /// Image type BLACKBONE_API inline eModType mType() const { return _is64 ? mt_mod64 : mt_mod32; } /// /// Get activation context handle /// /// Actx handle BLACKBONE_API inline HANDLE actx() const { return _hctx; } /// /// true if image is mapped as plain data file /// /// true if mapped as plain data file, false if mapped as image BLACKBONE_API inline bool isPlainData() const { return _isPlainData; } /// /// Get manifest resource ID /// /// Manifest resource ID BLACKBONE_API inline int manifestID() const { return _manifestIdx; } /// /// Get image subsystem /// /// Image subsystem BLACKBONE_API inline uint32_t subsystem() const { return _subsystem; } /// /// Get manifest resource file /// /// Manifest resource file BLACKBONE_API inline const std::wstring& manifestFile() const { return _manifestPath; } /// /// If true - no actual PE file available on disk /// /// Flag BLACKBONE_API inline bool noPhysFile() const { return _noFile; } /// /// DllCharacteristics field of header /// /// DllCharacteristics BLACKBONE_API inline uint32_t DllCharacteristics() const { return _DllCharacteristics; } #ifdef COMPILER_MSVC /// /// .NET image parser /// /// .NET image parser BLACKBONE_API ImageNET& net() { return _netImage; } #endif private: /// /// Prepare activation context /// /// Path to PE file. If nullptr - manifest is extracted from memory to disk /// Status code NTSTATUS PrepareACTX( const wchar_t* filepath = nullptr ); /// /// Get manifest from image data /// /// Manifest size /// Mmanifest ID /// Manifest data void* GetManifest( uint32_t& size, int32_t& manifestID ); private: FileHandle _hFile; // Target file HANDLE Handle _hMapping; // Memory mapping object void* _pFileBase = nullptr; // Mapping base bool _isPlainData = false; // File mapped as plain data file bool _is64 = false; // Image is 64 bit bool _isExe = false; // Image is an .exe file bool _isPureIL = false; // Pure IL image bool _noFile = false; // Parsed from memory, no underlying PE file available PCHDR32 _pImageHdr32 = nullptr; // PE header info PCHDR64 _pImageHdr64 = nullptr; // PE header info ptr_t _imgBase = 0; // Image base uint32_t _imgSize = 0; // Image size uint32_t _epRVA = 0; // Entry point RVA uint32_t _hdrSize = 0; // Size of headers ACtxHandle _hctx; // Activation context int32_t _manifestIdx = 0; // Manifest resource ID uint32_t _subsystem = 0; // Image subsystem int32_t _ILFlagOffset = 0; // Offset of pure IL flag uint32_t _DllCharacteristics = 0; // DllCharacteristics flags vecSections _sections; // Section info mapImports _imports; // Import functions mapImports _delayImports; // Import functions std::wstring _imagePath; // Image path std::wstring _manifestPath; // Image manifest container #ifdef COMPILER_MSVC ImageNET _netImage; // .net image info #endif }; } }