#pragma once #include "../../Include/Winheaders.h" #include "../../PE/PEImage.h" #include "../../Include/Types.h" #include "../../Include/NativeStructures.h" #include "../../Include/Macro.h" #include "../../Include/CallResult.h" namespace blackbone { enum LdrRefFlags { Ldr_None = 0x00, // Do not create any reference Ldr_ModList = 0x01, // Add to module list - LdrpModuleIndex( win8 only ), InMemoryOrderModuleList( win7 only ) Ldr_HashTable = 0x02, // Add to LdrpHashTable Ldr_ThdCall = 0x04, // Add to thread callback list (dllmain will be called with THREAD_ATTACH/DETACH reasons) Ldr_All = 0xFF, // Add to everything Ldr_Ignore = 0xDE // Only valid in mod callback, mod callback value will be ignored }; ENUM_OPS( LdrRefFlags ) struct NtLdrEntry : ModuleData { LdrRefFlags flags = Ldr_None; ptr_t entryPoint = 0; ULONG hash = 0; bool safeSEH = false; }; class NtLdr { public: BLACKBONE_API NtLdr( class Process& proc ); BLACKBONE_API ~NtLdr( void ); /// /// Initialize some loader stuff /// /// Target module type /// true on success BLACKBONE_API bool Init( eModType initFor = mt_default ); /// /// Add module to some loader structures /// (LdrpHashTable, LdrpModuleIndex( win8 only ), InMemoryOrderModuleList( win7 only )) /// /// Module data /// true on success BLACKBONE_API bool CreateNTReference( NtLdrEntry& mod ); /// /// Create thread static TLS array /// /// Module data /// TLS directory of target image /// Status code BLACKBONE_API NTSTATUS AddStaticTLSEntry( NtLdrEntry& mod, ptr_t tlsPtr ); /// /// Create module record in LdrpInvertedFunctionTable /// Used to create fake SAFESEH entries /// /// Module data /// true on success BLACKBONE_API bool InsertInvertedFunctionTable( NtLdrEntry& mod ); /// /// Free static TLS /// /// Target module /// Don't create new threads during remote call /// Status code BLACKBONE_API NTSTATUS UnloadTLS( const NtLdrEntry& mod, bool noThread = false ); /// /// Unlink module from Ntdll loader /// /// Module data /// Don't create new threads during unlink /// true on success BLACKBONE_API bool Unlink( const ModuleData& mod, bool noThread = false ); private: /// /// Find LdrpHashTable[] variable /// /// true on success template bool FindLdrpHashTable(); /// /// Find LdrpModuleIndex variable under win8 /// /// true on success template bool FindLdrpModuleIndexBase(); /// /// Find Loader heap base /// /// true on success template bool FindLdrHeap(); /// /// Initialize OS-specific module entry /// /// Module data /// Pointer to created entry template ptr_t InitBaseNode( NtLdrEntry& mod ); /// /// Initialize OS-specific module entry /// /// Module data /// Pointer to created entry template ptr_t InitW8Node( NtLdrEntry& mod ); /// /// Initialize OS-specific module entry /// /// Module data /// Pointer to created entry template ptr_t InitW7Node( NtLdrEntry& mod ); /// /// Insert entry into win8 module graph /// /// Node to insert /// Module data template void InsertTreeNode( ptr_t nodePtr, const NtLdrEntry& mod ); /// /// Insert entry into LdrpHashTable[] /// /// Link of entry to be inserted /// Module hash template void InsertHashNode( ptr_t pNodeLink, ULONG hash ); /// /// Insert entry into InLoadOrderModuleList and InMemoryOrderModuleList /// /// InMemoryOrderModuleList link of entry to be inserted /// InLoadOrderModuleList link of entry to be inserted template void InsertMemModuleNode( ptr_t pNodeMemoryOrderLink, ptr_t pNodeLoadOrderLink, ptr_t pNodeInitOrderLink ); /// /// Insert entry into standard double linked list /// /// List head pointer /// Entry list link to be inserted template void InsertTailList( ptr_t ListHead, ptr_t Entry ); /// /// Hash image name /// /// Iamge name /// Hash ULONG HashString( const std::wstring& str ); /// /// Allocate memory from heap if possible /// /// Module type /// Size to allocate /// Allocated address call_result_t AllocateInHeap( eModType mt, size_t size ); /// /// Get module native node ptr or create new /// /// node pointer (if nullptr - new dummy node is allocated) /// Module base address /// Node address template ptr_t SetNode( ptr_t ptr, Module pModule ); /// /// Unlink module from PEB_LDR_DATA /// /// Module data /// Address of removed record template ptr_t UnlinkFromLdr( const ModuleData& mod ); /// /// Finds LDR entry for module /// /// Target module base /// Found entry /// Found LDR entry address template ptr_t FindLdrEntry( module_t moduleBase, _LDR_DATA_TABLE_ENTRY_BASE_T* found = nullptr ); /// /// Remove record from LIST_ENTRY structure /// /// Entry link template void UnlinkListEntry( ptr_t pListLink ); /// /// Unlink from module graph /// /// Module data /// Module LDR entry /// Don't create new threads during unlink /// Address of removed record template ptr_t UnlinkTreeNode( const ModuleData& mod, ptr_t ldrEntry, bool noThread = false ); NtLdr( const NtLdr& ) = delete; NtLdr& operator =(const NtLdr&) = delete; private: class Process& _process; // Process memory routines ptr_t _LdrpHashTable = 0; // LdrpHashTable address ptr_t _LdrpModuleIndexBase = 0; // LdrpModuleIndex address ptr_t _LdrHeapBase = 0; // Loader heap base address eModType _initializedFor = mt_unknown; // Loader initialization target std::map _nodeMap; // Allocated native structures }; }