@@ -30,6 +30,7 @@ PEParser::PEParser(const wchar_t* path) :_path(path) {
3030
3131PEParser::PEParser (void * base) {
3232 _address = reinterpret_cast <PUCHAR>(base);
33+ _moduleBase = (DWORD_PTR)base;
3334 CheckValidity ();
3435}
3536
@@ -82,6 +83,10 @@ int PEParser::GetSectionCount() const {
8283 return _fileHeader->NumberOfSections ;
8384}
8485
86+ void PEParser::SetSectionCount (WORD count) {
87+ _fileHeader->NumberOfSections = count;
88+ }
89+
8590const IMAGE_SECTION_HEADER* PEParser::GetSectionHeader (ULONG section) const {
8691 if (!IsValid () || section >= _fileHeader->NumberOfSections )
8792 return nullptr ;
@@ -107,6 +112,23 @@ const IMAGE_DOS_HEADER& PEParser::GetDosHeader() const {
107112 return *_dosHeader;
108113}
109114
115+ BYTE* PEParser::GetDosStub () {
116+ BYTE* pDosStub = nullptr ;
117+
118+ if (_dosHeader->e_lfanew > sizeof (IMAGE_DOS_HEADER)) {
119+ pDosStub = (BYTE*)((DWORD_PTR)_dosHeader + sizeof (IMAGE_DOS_HEADER));
120+ }
121+ else if (_dosHeader->e_lfanew < sizeof (IMAGE_DOS_HEADER)) {
122+ _dosHeader->e_lfanew = sizeof (IMAGE_DOS_HEADER);
123+ }
124+
125+ return pDosStub;
126+ }
127+
128+ IMAGE_NT_HEADERS64* PEParser::GetNtHeader () {
129+ return _ntHeader;
130+ }
131+
110132void * PEParser::GetBaseAddress () const {
111133 return _address;
112134}
@@ -262,6 +284,10 @@ void* PEParser::GetAddress(unsigned rva) const {
262284 return ::ImageRvaToVa (::ImageNtHeader (_address), _address, rva, nullptr );
263285}
264286
287+ BYTE* PEParser::GetFileAddress (DWORD offset) {
288+ return _address + offset;
289+ }
290+
265291SubsystemType PEParser::GetSubsystemType () const {
266292 if (IsPe64 ())
267293 return static_cast <SubsystemType>(GetOptionalHeader64 ().Subsystem );
@@ -307,6 +333,19 @@ unsigned PEParser::RvaToFileOffset(unsigned rva) const {
307333 return rva;
308334}
309335
336+ DWORD_PTR PEParser::FileOffsetToRva (DWORD_PTR offset) {
337+ auto sections = _sections;
338+ for (int i = 0 ; i < GetSectionCount (); ++i) {
339+ if ((sections[i].PointerToRawData <= offset) &&
340+ ((sections[i].PointerToRawData + sections[i].SizeOfRawData ) > offset))
341+ {
342+ return ((offset - sections[i].PointerToRawData ) + sections[i].VirtualAddress );
343+ }
344+ }
345+
346+ return 0 ;
347+ }
348+
310349DWORD_PTR PEParser::RVAToRelativeOffset (DWORD_PTR rva) const {
311350 auto sections = _sections;
312351 for (int i = 0 ; i < GetSectionCount (); ++i) {
@@ -327,6 +366,19 @@ int PEParser::RVAToSectionIndex(DWORD_PTR rva) const {
327366 return -1 ;
328367}
329368
369+ DWORD PEParser::GetSectionHeaderBasedSizeOfImage () {
370+ DWORD lastVirtualOffset = 0 , lastVirtualSize = 0 ;
371+
372+ for (WORD i = 0 ; i < GetSectionCount (); i++) {
373+ if ((_sections[i].VirtualAddress + _sections[i].Misc .VirtualSize ) > (lastVirtualOffset + lastVirtualSize)) {
374+ lastVirtualOffset = _sections[i].VirtualAddress ;
375+ lastVirtualSize = _sections[i].Misc .VirtualSize ;
376+ }
377+ }
378+
379+ return lastVirtualSize + lastVirtualOffset;
380+ }
381+
330382bool PEParser::GetImportAddressTable () const {
331383 auto dir = GetDataDirectory (IMAGE_DIRECTORY_ENTRY_IAT);
332384 if (dir->Size == 0 )
@@ -546,4 +598,136 @@ void PEParser::AlignAllSectionHeaders() {
546598
547599 newFileSize = sections[i].PointerToRawData + sections[i].SizeOfRawData ;
548600 }
601+ }
602+
603+ void PEParser::FixPEHeader () {
604+ DWORD size = _dosHeader->e_lfanew + sizeof (DWORD) + sizeof (IMAGE_FILE_HEADER);
605+
606+ if (!IsPe64 ()) {
607+ _opt32->DataDirectory [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0 ;
608+ _opt32->DataDirectory [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0 ;
609+
610+ for (DWORD i = _opt32->NumberOfRvaAndSizes ; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
611+ _opt32->DataDirectory [i].Size = 0 ;
612+ _opt32->DataDirectory [i].VirtualAddress = 0 ;
613+ }
614+ _opt32->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
615+ _fileHeader->SizeOfOptionalHeader = sizeof (IMAGE_OPTIONAL_HEADER32);
616+
617+ _opt32->SizeOfImage = GetSectionHeaderBasedSizeOfImage ();
618+
619+ if (_moduleBase) {
620+ _opt32->ImageBase = _moduleBase;;
621+ }
622+
623+ _opt32->SizeOfHeaders = AlignValue (size + _ntHeader->FileHeader .SizeOfOptionalHeader
624+ + GetSectionCount () * sizeof (IMAGE_SECTION_HEADER), _opt32->FileAlignment );
625+ }
626+ else {
627+ _opt64->DataDirectory [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0 ;
628+ _opt64->DataDirectory [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0 ;
629+
630+ for (DWORD i = _opt64->NumberOfRvaAndSizes ; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
631+ _opt64->DataDirectory [i].Size = 0 ;
632+ _opt64->DataDirectory [i].VirtualAddress = 0 ;
633+ }
634+
635+ _opt64->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
636+ _fileHeader->SizeOfOptionalHeader = sizeof (IMAGE_OPTIONAL_HEADER64);
637+
638+ if (_moduleBase) {
639+ _opt64->ImageBase = _moduleBase;
640+ }
641+
642+ _opt64->SizeOfHeaders = AlignValue (size + _fileHeader->SizeOfOptionalHeader +
643+ +GetSectionCount () * sizeof (IMAGE_SECTION_HEADER), _opt64->FileAlignment );
644+ }
645+
646+ RemoveIATDirectory ();
647+ }
648+
649+ void PEParser::RemoveIATDirectory () {
650+ DWORD searchAddress = 0 ;
651+
652+ if (!IsPe64 ()) {
653+ searchAddress = _opt32->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress ;
654+ _opt32->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0 ;
655+ _opt32->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].Size = 0 ;
656+ }
657+ else {
658+ searchAddress = _opt64->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress ;
659+ _opt64->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0 ;
660+ _opt64->DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT].Size = 0 ;
661+ }
662+
663+ if (searchAddress) {
664+ for (WORD i = 0 ; i < GetSectionCount (); i++) {
665+ if (_sections[i].VirtualAddress <= searchAddress &&
666+ (_sections[i].VirtualAddress + _sections[i].Misc .VirtualSize ) > searchAddress) {
667+ _sections[i].Characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
668+ }
669+ }
670+ }
671+ }
672+
673+ DWORD PEParser::GetSectionHeaderBasedFileSize () {
674+ DWORD lastRawOffset = 0 , lastRawSize = 0 ;
675+
676+ for (WORD i = 0 ; i < GetSectionCount (); i++) {
677+ auto section = _sections[i];
678+ if ((section.PointerToRawData + section.SizeOfRawData ) > (lastRawOffset + lastRawSize))
679+ {
680+ lastRawOffset = section.PointerToRawData ;
681+ lastRawSize = section.SizeOfRawData ;
682+ }
683+ }
684+
685+ return lastRawSize + lastRawOffset;
686+ }
687+
688+ bool PEParser::AddNewLastSection (const char * pSectionName, DWORD sectionSize, BYTE* pSectionData) {
689+ size_t len = strlen (pSectionName);
690+ DWORD fileAlignment = 0 , sectionAlignment = 0 ;
691+ PEFileSection peFileSection;
692+
693+ if (len > IMAGE_SIZEOF_SHORT_NAME) {
694+ return false ;
695+ }
696+
697+ if (!IsPe64 ()) {
698+ fileAlignment = _opt32->FileAlignment ;
699+ sectionAlignment = _opt32->SectionAlignment ;
700+ }
701+ else {
702+ fileAlignment = _opt64->FileAlignment ;
703+ sectionAlignment = _opt64->SectionAlignment ;
704+ }
705+
706+ memcpy_s (peFileSection._sectionHeader .Name , IMAGE_SIZEOF_SHORT_NAME, pSectionName, len);
707+
708+ peFileSection._sectionHeader .SizeOfRawData = sectionSize;
709+ peFileSection._sectionHeader .Misc .VirtualSize = AlignValue (sectionSize, sectionAlignment);
710+
711+ peFileSection._sectionHeader .PointerToRawData = AlignValue (GetSectionHeaderBasedFileSize (), fileAlignment);
712+ peFileSection._sectionHeader .VirtualAddress = AlignValue (GetSectionHeaderBasedSizeOfImage (), sectionAlignment);
713+
714+ peFileSection._sectionHeader .Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
715+ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA;
716+
717+ peFileSection._normalSize = peFileSection._sectionHeader .SizeOfRawData ;
718+ peFileSection._dataSize = peFileSection._sectionHeader .SizeOfRawData ;
719+
720+ if (pSectionData == nullptr ) {
721+ peFileSection._pData = new BYTE[peFileSection._sectionHeader .SizeOfRawData ];
722+ ZeroMemory (peFileSection._pData , peFileSection._sectionHeader .SizeOfRawData );
723+ }
724+ else {
725+ peFileSection._pData = pSectionData;
726+ }
727+
728+ _PESections.push_back (peFileSection);
729+
730+ SetSectionCount (GetSectionCount () + 1 );
731+
732+ return true ;
549733}
0 commit comments