• R/O
  • SSH
  • HTTPS

peframework: Commit


Commit MetaInfo

Revision16 (tree)
Time2017-08-14 07:56:35
Authorquiret

Log Message

- added verification + allocation of PE delay-load DLL handle memory locations
- added helper code to take over memory allocations more efficiently
- shared code a little more

Change Summary

Incremental Difference

--- include/peloader.h (revision 15)
+++ include/peloader.h (revision 16)
@@ -659,6 +659,26 @@
659659 return ( theSection != NULL );
660660 }
661661
662+ inline PESectionAllocation CloneOnlyFinal( void ) const
663+ {
664+ PESection *allocSect = this->theSection;
665+
666+ if ( allocSect == NULL )
667+ {
668+ return PESectionAllocation();
669+ }
670+
671+ if ( allocSect->IsFinal() == false )
672+ {
673+ return PESectionAllocation();
674+ }
675+
676+ PEFile::PESectionAllocation newAlloc;
677+ allocSect->SetPlacedMemoryInline( newAlloc, this->sectOffset, this->dataSize );
678+
679+ return newAlloc;
680+ }
681+
662682 // We can spawn a data reference from any allocation.
663683 inline operator PESectionDataReference ( void )
664684 {
@@ -732,6 +752,7 @@
732752 // Allocation methods.
733753 std::uint32_t Allocate( PESectionAllocation& blockMeta, std::uint32_t allocSize, std::uint32_t alignment = sizeof(std::uint32_t) );
734754 void SetPlacedMemory( PESectionAllocation& blockMeta, std::uint32_t allocOff, std::uint32_t allocSize = 0u );
755+ void SetPlacedMemoryInline( PESectionAllocation& blockMeta, std::uint32_t allocOff, std::uint32_t allocSize = 0u );
735756
736757 std::uint32_t ResolveRVA( std::uint32_t sectOffset ) const;
737758
@@ -995,12 +1016,12 @@
9951016
9961017 // Function to get the section and the offset into it for a RVA.
9971018 template <typename sectLocationProviderType>
998- inline bool GetPEDataLocationGeneric( const sectLocationProviderType& sectLocProv, std::uint32_t rvirtAddr, std::uint32_t *allocOffOut, PESection **allocSectOut = NULL, std::uint32_t *sectIndexOut = NULL ) const
1019+ inline bool GetPEDataLocationGeneric( const sectLocationProviderType& sectLocProv, std::uint32_t rvirtAddr, std::uint32_t rvirtSize, std::uint32_t *allocOffOut, PESection **allocSectOut = NULL, std::uint32_t *sectIndexOut = NULL ) const
9991020 {
10001021 typedef sliceOfData <std::uint32_t> memSlice_t;
10011022
10021023 // Create a memory slice of the request.
1003- memSlice_t requestRegion( rvirtAddr, 1 );
1024+ memSlice_t requestRegion( rvirtAddr, rvirtSize );
10041025
10051026 std::uint32_t sectIndex = 0;
10061027
@@ -1065,9 +1086,16 @@
10651086 {
10661087 mainSectLocProv locProv;
10671088
1068- return GetPEDataLocationGeneric( locProv, rvirtAddr, allocOffOut, allocSectOut, sectIndexOut );
1089+ return GetPEDataLocationGeneric( locProv, rvirtAddr, 1, allocOffOut, allocSectOut, sectIndexOut );
10691090 }
10701091
1092+ inline bool GetPEDataLocationEx( std::uint32_t rvirtAddr, std::uint32_t rvirtSize, std::uint32_t *allocOffOut, PESection **allocSectOut = NULL, std::uint32_t *sectIndexOut = NULL ) const
1093+ {
1094+ mainSectLocProv locProv;
1095+
1096+ return GetPEDataLocationGeneric( locProv, rvirtAddr, rvirtSize, allocOffOut, allocSectOut, sectIndexOut );
1097+ }
1098+
10711099 // Function to get a data pointer of data directories.
10721100 template <typename sectLocationProviderType>
10731101 inline bool GetPEDataStreamGeneric(
@@ -1080,7 +1108,7 @@
10801108 std::uint32_t offsetIntoSect;
10811109 PESection *allocSect;
10821110
1083- bool gotLocation = GetPEDataLocationGeneric( sectLocProv, rvirtAddr, &offsetIntoSect, &allocSect );
1111+ bool gotLocation = GetPEDataLocationGeneric( sectLocProv, rvirtAddr, 1, &offsetIntoSect, &allocSect );
10841112
10851113 if ( !gotLocation )
10861114 return false;
@@ -1917,7 +1945,7 @@
19171945 std::uint32_t attrib;
19181946 std::string DLLName;
19191947 PESectionAllocation DLLName_allocEntry;
1920- PESectionDataReference DLLHandleRef;
1948+ PESectionAllocation DLLHandleAlloc; // just storage (for the NT loader) in the size of a pointer
19211949 PESectionDataReference IATRef;
19221950 PEImportDesc::functions_t importNames;
19231951 PESectionAllocation importNamesAllocEntry;
--- src/peloader.write.cpp (revision 15)
+++ src/peloader.write.cpp (revision 16)
@@ -293,17 +293,8 @@
293293 PEFile::PESectionAllocation PEFile::PEImportDesc::WritePEImportFunctions( PESection& writeSect, const functions_t& functionList, bool isExtendedFormat )
294294 {
295295 // The size of an entry depends on PE32 or PE32+.
296- std::uint32_t entrySize;
296+ std::uint32_t entrySize = GetPEPointerSize( isExtendedFormat );
297297
298- if ( isExtendedFormat )
299- {
300- entrySize = sizeof(std::uint64_t);
301- }
302- else
303- {
304- entrySize = sizeof(std::uint32_t);
305- }
306-
307298 std::uint32_t numFuncs = (std::uint32_t)functionList.size();
308299
309300 // We need to end of the array with a zero-entry to describe the end.
@@ -1382,6 +1373,14 @@
13821373 delayDesc.DLLName_allocEntry = WriteZeroTermString( rdonlySect, delayDesc.DLLName );
13831374 }
13841375
1376+ // Check if allocation for the DLL handle is required.
1377+ if ( delayDesc.DLLHandleAlloc.IsAllocated() == false )
1378+ {
1379+ std::uint32_t entrySize = GetPEPointerSize( isExtendedFormat );
1380+
1381+ dataSect.Allocate( delayDesc.DLLHandleAlloc, entrySize, entrySize );
1382+ }
1383+
13851384 // Write the import names.
13861385 auto& funcs = delayDesc.importNames;
13871386
@@ -1422,7 +1421,8 @@
14221421 nativeDesc.Attributes.AllAttributes = delayDesc.attrib;
14231422 nativeDesc.DllNameRVA = 0;
14241423 delayLoadsAlloc.RegisterTargetRVA( descWriteOff + offsetof(PEStructures::IMAGE_DELAYLOAD_DESCRIPTOR, DllNameRVA), delayDesc.DLLName_allocEntry );
1425- nativeDesc.ModuleHandleRVA = delayDesc.DLLHandleRef.GetRVA();
1424+ nativeDesc.ModuleHandleRVA = 0;
1425+ delayLoadsAlloc.RegisterTargetRVA( descWriteOff + offsetof(PEStructures::IMAGE_DELAYLOAD_DESCRIPTOR, ModuleHandleRVA), delayDesc.DLLHandleAlloc );
14261426 nativeDesc.ImportAddressTableRVA = delayDesc.IATRef.GetRVA();
14271427 nativeDesc.ImportNameTableRVA = 0;
14281428 delayLoadsAlloc.RegisterTargetRVA( descWriteOff + offsetof(PEStructures::IMAGE_DELAYLOAD_DESCRIPTOR, ImportNameTableRVA), delayDesc.importNamesAllocEntry );
--- src/peloader.read.cpp (revision 15)
+++ src/peloader.read.cpp (revision 16)
@@ -812,16 +812,8 @@
812812 std::vector <PEExportDir::func> funcs;
813813 funcs.reserve( expEntry.NumberOfFunctions );
814814
815- std::uint64_t tabSize;
816-
817- if ( isExtendedFormat )
818- {
819- tabSize = ( sizeof(std::uint64_t) * expEntry.NumberOfFunctions );
820- }
821- else
822- {
823- tabSize = ( sizeof(std::uint32_t) * expEntry.NumberOfFunctions );
824- }
815+ std::uint32_t archPointerSize = GetPEPointerSize( isExtendedFormat );
816+ std::uint64_t tabSize = ( archPointerSize * expEntry.NumberOfFunctions );
825817
826818 PESection *addrPtrSect;
827819 PEDataStream addrPtrStream;
@@ -1041,7 +1033,7 @@
10411033
10421034 std::uint32_t n = 0;
10431035
1044- while ( n++ < potentialNumDescriptors )
1036+ while ( n < potentialNumDescriptors )
10451037 {
10461038 PEStructures::IMAGE_IMPORT_DESCRIPTOR importInfo;
10471039 importDescsStream.Read( &importInfo, sizeof(importInfo) );
@@ -1094,6 +1086,9 @@
10941086 // Store this import desc.
10951087 impDescs.push_back( std::move( impDesc ) );
10961088
1089+ // Next iteration.
1090+ n++;
1091+
10971092 // Done with this import desc!
10981093 }
10991094
@@ -1972,7 +1967,27 @@
19721967 dllNamePtrSect->SetPlacedMemory( desc.DLLName_allocEntry, DllNameRVA );
19731968 }
19741969
1975- desc.DLLHandleRef = sections.ResolveRVAToRef( delayLoad.ModuleHandleRVA );
1970+ // Take over the memory location of the DLL handle.
1971+ {
1972+ std::uint32_t archPointerSize = GetPEPointerSize( isExtendedFormat );
1973+
1974+ std::uint32_t sectOff;
1975+ PESection *handleSect;
1976+ {
1977+ bool gotLocation = sections.GetPEDataLocationEx( delayLoad.ModuleHandleRVA, archPointerSize, &sectOff, &handleSect );
1978+
1979+ if ( !gotLocation )
1980+ {
1981+ throw peframework_exception(
1982+ ePEExceptCode::CORRUPT_PE_STRUCTURE,
1983+ "failed to read valid PE delay-load module handle allocation"
1984+ );
1985+ }
1986+ }
1987+
1988+ handleSect->SetPlacedMemoryInline( desc.DLLHandleAlloc, sectOff, archPointerSize );
1989+ }
1990+
19761991 desc.IATRef = sections.ResolveRVAToRef( delayLoad.ImportAddressTableRVA );
19771992
19781993 if ( std::uint32_t importNamesRVA = delayLoad.ImportNameTableRVA )
--- src/peloader.imports.cpp (revision 15)
+++ src/peloader.imports.cpp (revision 16)
@@ -91,6 +91,7 @@
9191 PEFile::PEImportDesc::importFunc carbonCopy;
9292 carbonCopy.isOrdinalImport = impFunc.isOrdinalImport;
9393 carbonCopy.name = impFunc.name;
94+ carbonCopy.nameAllocEntry = impFunc.nameAllocEntry.CloneOnlyFinal();
9495 carbonCopy.ordinal_hint = impFunc.ordinal_hint;
9596
9697 newFuncs.push_back( std::move( carbonCopy ) );
--- src/peloader.cpp (revision 15)
+++ src/peloader.cpp (revision 16)
@@ -343,6 +343,17 @@
343343
344344 void PEFile::PESection::SetPlacedMemory( PESectionAllocation& blockMeta, std::uint32_t allocOff, std::uint32_t allocSize )
345345 {
346+ assert( allocOff >= this->virtualAddr );
347+
348+ this->SetPlacedMemoryInline(
349+ blockMeta,
350+ ( allocOff - this->virtualAddr ),
351+ allocSize
352+ );
353+}
354+
355+void PEFile::PESection::SetPlacedMemoryInline( PESectionAllocation& blockMeta, std::uint32_t allocOff, std::uint32_t allocSize )
356+{
346357 assert( this->isFinal == true );
347358 assert( this->ownerImage != NULL );
348359
@@ -353,7 +364,7 @@
353364 {
354365 typedef sliceOfData <std::uint32_t> streamSlice_t;
355366
356- streamSlice_t sectionSlice( this->virtualAddr, this->virtualSize );
367+ streamSlice_t sectionSlice( 0, this->virtualSize );
357368
358369 streamSlice_t reqSlice( allocOff, std::max( allocSize, 1u ) );
359370
@@ -362,7 +373,7 @@
362373 assert( intResult == streamSlice_t::INTERSECT_INSIDE || intResult == streamSlice_t::INTERSECT_EQUAL );
363374 }
364375
365- blockMeta.sectOffset = ( allocOff - this->virtualAddr );
376+ blockMeta.sectOffset = allocOff;
366377 blockMeta.dataSize = allocSize;
367378 blockMeta.theSection = this;
368379
--- src/peloader.internal.hxx (revision 15)
+++ src/peloader.internal.hxx (revision 16)
@@ -4,4 +4,15 @@
44 // Forward to the global header, because it is sometimes necessary.
55 #include "peloader.serialize.h"
66
7+// Helper function for pointer size.
8+inline std::uint32_t GetPEPointerSize( bool isExtendedFormat )
9+{
10+ if ( isExtendedFormat )
11+ {
12+ return sizeof(std::uint64_t);
13+ }
14+
15+ return sizeof(std::uint32_t);
16+}
17+
718 #endif //_PELOADER_INTERNAL_
\ No newline at end of file
Show on old repository browser