• R/O
  • SSH
  • HTTPS

peframework: Commit


Commit MetaInfo

Revision6 (tree)
Time2017-04-16 20:25:52
Authorquiret

Log Message

- added automatic sorting to PE image exports

Change Summary

Incremental Difference

--- include/peloader.h (revision 5)
+++ include/peloader.h (revision 6)
@@ -1402,16 +1402,31 @@
14021402 PESectionDataReference expRef; // only valid if not a forwarder.
14031403 std::string forwarder;
14041404 bool isForwarder;
1405-
1406- // Optional fields.
1407- std::string name; // is valid if not empty
1408- bool isNamed;
1409- PESectionAllocation nameAllocEntry;
1405+
14101406 // definition of ordinal: index into function array.
14111407 // thus it is given implicitly.
14121408 };
14131409 std::vector <func> functions;
14141410
1411+ // Name map.
1412+ struct mappedName
1413+ {
1414+ std::string name;
1415+ mutable PESectionAllocation nameAllocEntry;
1416+
1417+ inline bool operator < ( const mappedName& right ) const
1418+ {
1419+ return ( this->name < right.name );
1420+ }
1421+ };
1422+ std::map <mappedName, size_t> funcNameMap;
1423+
1424+ // Helper API.
1425+ // (all ordinals have to be local to this image ordinal base)
1426+ std::uint32_t AddExport( func&& entryToTakeOver );
1427+ void MapName( std::uint32_t ordinal, const char *name );
1428+ void RemoveExport( std::uint32_t ordinal );
1429+
14151430 PESectionAllocation funcAddressAllocEntry;
14161431 PESectionAllocation funcNamesAllocEntry;
14171432 PESectionAllocation funcOrdinalsAllocEntry;
--- src/peloader.write.cpp (revision 5)
+++ src/peloader.write.cpp (revision 6)
@@ -376,37 +376,32 @@
376376 if ( expDir.chars != 0 || expDir.name.empty() == false || expDir.functions.empty() == false )
377377 {
378378 // Commit all export directory name entries.
379- const std::uint32_t numExportEntries = (std::uint32_t)expDir.functions.size();
380379
381380 // Determine if we need to allocate a function name mapping.
382- std::uint32_t numNamedEntries = 0;
381+ std::uint32_t numNamedEntries = (std::uint32_t)expDir.funcNameMap.size();
383382
384- for ( size_t n = 0; n < numExportEntries; n++ )
383+ for ( auto& nameMapIter : expDir.funcNameMap )
385384 {
386- PEExportDir::func& funcEntry = expDir.functions[ n ];
385+ const PEExportDir::mappedName& nameMap = nameMapIter.first;
387386
388- // Are we a named entry? If yes we will need a mapping.
389- if ( funcEntry.isNamed )
387+ // Make sure we wrote the name into PE virtual memory.
388+ if ( !nameMap.nameAllocEntry.IsAllocated() )
390389 {
391- if ( !funcEntry.nameAllocEntry.IsAllocated() )
392- {
393- // Allocate an entry for the name.
394- const std::uint32_t strSize = (std::uint32_t)( funcEntry.name.size() + 1 );
390+ // Allocate an entry for the name.
391+ const std::uint32_t strSize = (std::uint32_t)( nameMap.name.size() + 1 );
395392
396- PESectionAllocation nameAllocEntry;
397- rdonlySect.Allocate( nameAllocEntry, strSize, 1 );
393+ PESectionAllocation nameAllocEntry;
394+ rdonlySect.Allocate( nameAllocEntry, strSize, 1 );
398395
399- nameAllocEntry.WriteToSection( funcEntry.name.c_str(), strSize );
396+ nameAllocEntry.WriteToSection( nameMap.name.c_str(), strSize );
400397
401- // Remember the completed data.
402- funcEntry.nameAllocEntry = std::move( nameAllocEntry );
403- }
404-
405- // We definately need a name-ordinal map.
406- numNamedEntries++;
398+ // Remember the completed data.
399+ nameMap.nameAllocEntry = std::move( nameAllocEntry );
407400 }
408401 }
409402
403+ const std::uint32_t numExportEntries = (std::uint32_t)expDir.functions.size();
404+
410405 // Commit the export module name.
411406 if ( !expDir.nameAllocEntry.IsAllocated() )
412407 {
@@ -534,20 +529,20 @@
534529
535530 std::uint32_t index = 0;
536531
537- for ( auto& keyIter : allocInfos )
532+ for ( const auto& nameMapIter : expDir.funcNameMap )
538533 {
539- size_t funcIndex = keyIter.first;
534+ size_t funcIndex = nameMapIter.second;
540535
541536 // Write the name.
542- PEExportDir::func& funcInfo = expDir.functions[ funcIndex ];
543-
544537 std::uint16_t ordinal = (std::uint16_t)funcIndex;
545538
546539 // Write this name map entry.
540+ const PEExportDir::mappedName& nameMap = nameMapIter.first;
541+
547542 const std::uint32_t namePtrOff = ( sizeof(std::uint32_t) * index );
548543 const std::uint32_t ordOff = ( sizeof(std::uint16_t) * index );
549544
550- namePtrTableAlloc.RegisterTargetRVA( namePtrOff, funcInfo.nameAllocEntry );
545+ namePtrTableAlloc.RegisterTargetRVA( namePtrOff, nameMap.nameAllocEntry );
551546 ordMapTableAlloc.WriteToSection( &ordinal, sizeof(ordinal), ordOff );
552547
553548 index++;
--- src/peloader.read.cpp (revision 5)
+++ src/peloader.read.cpp (revision 6)
@@ -790,8 +790,6 @@
790790 expInfo.minorVersion = expEntry.MinorVersion;
791791 expInfo.ordinalBase = expEntry.Base;
792792
793- size_t ordinalBase = ( expInfo.ordinalBase - 1 );
794-
795793 // Read the name.
796794 PESection *sectOfName;
797795 {
@@ -847,7 +845,7 @@
847845 for ( std::uint32_t n = 0; n < expEntry.NumberOfFunctions; n++ )
848846 {
849847 PEExportDir::func fentry;
850- fentry.isNamed = false; // by default no export is named.
848+ // by default no export is named.
851849
852850 bool isForwarder;
853851 {
@@ -854,46 +852,56 @@
854852 std::uint32_t ptr;
855853 addrPtrStream.Read( &ptr, sizeof(ptr) );
856854
857- // Determine if we are a forwarder or an export.
855+ // We could be an empty entry.
856+ // (encountered in system DLLs)
857+ if ( ptr != 0 )
858858 {
859- typedef sliceOfData <std::uint32_t> rvaSlice_t;
859+ // Determine if we are a forwarder or an export.
860+ {
861+ typedef sliceOfData <std::uint32_t> rvaSlice_t;
860862
861- rvaSlice_t requestSlice( ptr, 1 );
863+ rvaSlice_t requestSlice( ptr, 1 );
862864
863- rvaSlice_t expDirSlice( expDirEntry.VirtualAddress, expDirEntry.Size );
865+ rvaSlice_t expDirSlice( expDirEntry.VirtualAddress, expDirEntry.Size );
864866
865- rvaSlice_t::eIntersectionResult intResult = requestSlice.intersectWith( expDirSlice );
867+ rvaSlice_t::eIntersectionResult intResult = requestSlice.intersectWith( expDirSlice );
866868
867- isForwarder = ( rvaSlice_t::isFloatingIntersect( intResult ) == false );
868- }
869+ isForwarder = ( rvaSlice_t::isFloatingIntersect( intResult ) == false );
870+ }
869871
870- // Store properties according to the type.
871- PESection *exportOffPtrSect;
872- PEDataStream expOffStream;
873- {
874- bool gotStream = sections.GetPEDataStream( ptr, expOffStream, &exportOffPtrSect );
872+ // Store properties according to the type.
873+ PESection *exportOffPtrSect;
874+ PEDataStream expOffStream;
875+ {
876+ bool gotStream = sections.GetPEDataStream( ptr, expOffStream, &exportOffPtrSect );
875877
876- if ( !gotStream )
877- {
878- throw peframework_exception(
879- ePEExceptCode::CORRUPT_PE_STRUCTURE,
880- "failed to get PE export offset pointer"
881- );
878+ if ( !gotStream )
879+ {
880+ throw peframework_exception(
881+ ePEExceptCode::CORRUPT_PE_STRUCTURE,
882+ "failed to get PE export offset pointer"
883+ );
884+ }
882885 }
883- }
884886
885- // We store the location of the data entry, but NOTE that
886- // this behavior NEVER is an allocation!
887- if ( !isForwarder ) // we need to know nothing about forwarders.
888- {
889- std::uint32_t offStore = ( ptr - exportOffPtrSect->GetVirtualAddress() );
887+ // We store the location of the data entry, but NOTE that
888+ // this behavior NEVER is an allocation!
889+ if ( !isForwarder ) // we need to know nothing about forwarders.
890+ {
891+ std::uint32_t offStore = ( ptr - exportOffPtrSect->GetVirtualAddress() );
890892
891- fentry.expRef = PESectionDataReference( exportOffPtrSect, offStore );
893+ fentry.expRef = PESectionDataReference( exportOffPtrSect, offStore );
894+ }
895+ // Otherwise read the forwarder entry.
896+ else
897+ {
898+ ReadPEString( expOffStream, fentry.forwarder );
899+ }
892900 }
893- // Otherwise read the forwarder entry.
894901 else
895902 {
896- ReadPEString( expOffStream, fentry.forwarder );
903+ // Empty settings.
904+ isForwarder = false;
897905 }
898906 }
899907 fentry.isForwarder = isForwarder;
@@ -945,7 +953,7 @@
945953 addrNameOrdStream.Read( &ordinal, sizeof(ordinal) );
946954
947955 // Get the index to map the function name to (== ordinal).
948- size_t mapIndex = ( ordinal - ordinalBase );
956+ size_t mapIndex = ( ordinal );
949957
950958 if ( mapIndex >= funcs.size() )
951959 {
@@ -976,6 +984,7 @@
976984 }
977985 }
978986
987+ // Check some kind of sense behind the name.
979988 if ( realName.empty() )
980989 {
981990 // Kind of invalid.
@@ -985,22 +994,13 @@
985994 );
986995 }
987996
988- PEExportDir::func& fentry = funcs[ mapIndex ];
997+ // Store this link.
998+ PEExportDir::mappedName nameMap;
999+ nameMap.name = std::move( realName );
1000+
1001+ realNamePtrSect->SetPlacedMemory( nameMap.nameAllocEntry, namePtrRVA );
9891002
990- // Check for ambiguous name mappings.
991- // TODO: this is actually allowed and is called "alias"; pretty evil.
992- if ( fentry.isNamed )
993- {
994- throw peframework_exception(
995- ePEExceptCode::UNSUPPORTED,
996- "ambiguous PE export name mapping"
997- );
998- }
999-
1000- fentry.name = std::move( realName );
1001- fentry.isNamed = true; // yes, we have a valid name!
1002-
1003- realNamePtrSect->SetPlacedMemory( fentry.nameAllocEntry, namePtrRVA );
1003+ expInfo.funcNameMap.insert( std::make_pair( std::move( nameMap ), std::move( mapIndex ) ) );
10041004 }
10051005 }
10061006
--- src/peloader.exports.cpp (revision 0)
+++ src/peloader.exports.cpp (revision 6)
@@ -0,0 +1,60 @@
1+// Helper API for managing exports.
2+#include "peloader.h"
3+
4+#include "peexcept.h"
5+
6+std::uint32_t PEFile::PEExportDir::AddExport( func&& entry )
7+{
8+ size_t currentIndex = this->functions.size();
9+
10+ this->functions.push_back( std::move( entry ) );
11+
12+ // We need to rewrite stuff.
13+ this->allocEntry = PESectionAllocation();
14+ this->funcAddressAllocEntry = PESectionAllocation();
15+
16+ return (std::uint32_t)currentIndex;
17+}
18+
19+void PEFile::PEExportDir::MapName( std::uint32_t ordinal, const char *name )
20+{
21+ mappedName newNameMap;
22+ newNameMap.name = name;
23+
24+ this->funcNameMap.insert( std::make_pair( std::move( newNameMap ), ordinal ) );
25+
26+ // Need to recommit memory.
27+ this->allocEntry = PESectionAllocation();
28+ this->funcNamesAllocEntry = PESectionAllocation();
29+}
30+
31+void PEFile::PEExportDir::RemoveExport( std::uint32_t ordinal )
32+{
33+ size_t curNumFunctions = this->functions.size();
34+
35+ if ( ordinal >= curNumFunctions )
36+ {
37+ throw peframework_exception( ePEExceptCode::RUNTIME_ERROR, "ordinal out of bounds for removing export" );
38+ }
39+
40+ // Simply reset the function field.
41+ {
42+ func& expEntry = this->functions[ ordinal ];
43+ expEntry.isForwarder = false;
44+ expEntry.expRef = PESectionDataReference();
45+ expEntry.forwarder.clear();
46+ }
47+
48+ // Remove all name mappings of this ordinal.
49+ {
50+ auto iter = this->funcNameMap.begin();
51+
52+ while ( iter != this->funcNameMap.end() )
53+ {
54+ if ( iter->second == ordinal )
55+ {
56+ iter = this->funcNameMap.erase( iter );
57+ }
58+ }
59+ }
60+}
\ No newline at end of file
Show on old repository browser