55#include " PEParser.h"
66#include " CLRMetadataParser.h"
77#include < unordered_map>
8+ #include < algorithm>
89#pragma comment(lib,"imagehlp")
910
1011
@@ -23,8 +24,8 @@ PEParser::PEParser(const wchar_t* path) :_path(path) {
2324 return ;
2425
2526 CheckValidity ();
26- if (IsValid () && IsManaged () ) {
27-
27+ if (IsValid ()) {
28+ GetSectionHeaders ();
2829 }
2930}
3031
@@ -33,6 +34,22 @@ PEParser::PEParser(void* base) {
3334 _moduleBase = (DWORD_PTR)base;
3435 _isFileMap = false ;
3536 CheckValidity ();
37+ if (IsValid ()) {
38+ GetSectionHeaders ();
39+ }
40+ }
41+
42+ void PEParser::GetSectionHeaders () {
43+ _PESections.clear ();
44+ int count = GetSectionCount ();
45+ _PESections.reserve (count);
46+
47+ PEFileSection peFileSection;
48+
49+ for (WORD i = 0 ; i < count; i++) {
50+ memcpy_s (&peFileSection._sectionHeader , sizeof (IMAGE_SECTION_HEADER), &_sections[i], sizeof (IMAGE_SECTION_HEADER));
51+ _PESections.push_back (peFileSection);
52+ }
3653}
3754
3855HANDLE PEParser::GetFileHandle () {
@@ -370,9 +387,8 @@ void PEParser::CheckValidity() {
370387
371388 _dosHeader = reinterpret_cast <IMAGE_DOS_HEADER*>(_address);
372389 if (_dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
373- // perhaps object file / static library
374- _fileHeader = (IMAGE_FILE_HEADER*)_address;
375- _sections = (PIMAGE_SECTION_HEADER)(_fileHeader + 1 );
390+ _valid = false ;
391+ return ;
376392 }
377393 else {
378394 auto ntHeader = (PIMAGE_NT_HEADERS64)(_address + _dosHeader->e_lfanew );
@@ -660,6 +676,10 @@ void PEParser::AlignAllSectionHeaders() {
660676
661677 newFileSize = sections[i].PointerToRawData + sections[i].SizeOfRawData ;
662678 }
679+
680+ std::sort (_PESections.begin (), _PESections.end (), [](const PEFileSection& d1, const PEFileSection& d2) {
681+ return d1._sectionHeader .VirtualAddress < d2._sectionHeader .VirtualAddress ;
682+ });
663683}
664684
665685void PEParser::FixPEHeader () {
@@ -792,4 +812,205 @@ bool PEParser::AddNewLastSection(const char* pSectionName, DWORD sectionSize, BY
792812 SetSectionCount (GetSectionCount () + 1 );
793813
794814 return true ;
815+ }
816+
817+ void PEParser::SetEntryPointRVA (DWORD rva) {
818+ if (IsPe64 ()) {
819+ _opt64->AddressOfEntryPoint = rva;
820+ }
821+ else {
822+ _opt32->AddressOfEntryPoint = rva;
823+ }
824+ }
825+
826+ void PEParser::SetEntryPointVA (DWORD_PTR entryPoint) {
827+ DWORD rva = (DWORD)(entryPoint - _moduleBase);
828+ SetEntryPointRVA (rva);
829+ }
830+
831+ bool PEParser::DumpProcess (DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* pDumpFilePath) {
832+ _moduleBase = modBase;
833+ GetPESections ();
834+ SetDefaultFileAligment ();
835+ SetEntryPointVA (entryPoint);
836+ AlignAllSectionHeaders ();
837+ FixPEHeader ();
838+
839+ return SavePEFileToDisk (pDumpFilePath);
840+ }
841+
842+ void PEParser::GetPESections () {
843+ DWORD_PTR offset = 0 ;
844+
845+ int count = GetSectionCount ();
846+ _PESections.reserve (count);
847+
848+ for (WORD i = 0 ; i < count; i++) {
849+ _PESections[i]._normalSize = _sections[i].Misc .VirtualSize ;
850+ offset = _sections[i].VirtualAddress ;
851+ GetPESectionData (offset, _PESections[i]);
852+ }
853+ }
854+
855+ void PEParser::GetPESectionData (DWORD_PTR offset, PEFileSection& peFileSection) {
856+ peFileSection._pData = new BYTE[peFileSection._dataSize ];
857+ memcpy (peFileSection._pData , _address + offset, peFileSection._dataSize );
858+ }
859+
860+ void PEParser::SetModuleBase (DWORD_PTR va) {
861+ _moduleBase = va;
862+ }
863+
864+ bool PEParser::OpenWriteFileHandle (const WCHAR* pNewFile) {
865+ if (pNewFile) {
866+ _hFile = ::CreateFile (pNewFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0 , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
867+ }
868+
869+ return _hFile != INVALID_HANDLE_VALUE;
870+ }
871+
872+ bool PEParser::WriteMemoryToFile (HANDLE hFile, LONG offset, DWORD size, LPVOID pData) {
873+ DWORD bytes;
874+ DWORD ret;
875+ DWORD error;
876+
877+ if (hFile != INVALID_HANDLE_VALUE) {
878+ ret = SetFilePointer (hFile, offset, nullptr , FILE_BEGIN);
879+ if (ret == INVALID_SET_FILE_POINTER) {
880+ error = GetLastError ();
881+ return false ;
882+ }
883+ return WriteFile (hFile, pData, size, &bytes, nullptr );
884+ }
885+ return false ;
886+ }
887+
888+ bool PEParser::SavePEFileToDisk (const WCHAR* pNewFile) {
889+ bool ret = true ;
890+
891+ DWORD fileOffset = 0 , writeSize = 0 ;
892+
893+ do
894+ {
895+ ret = OpenWriteFileHandle (pNewFile);
896+ if (!ret)
897+ break ;
898+
899+ writeSize = sizeof (IMAGE_DOS_HEADER);
900+
901+ if (!WriteMemoryToFile (_hFile, fileOffset, writeSize, GetBaseAddress ())) {
902+ ret = false ;
903+ break ;
904+ }
905+
906+ fileOffset += writeSize;
907+
908+ LONG e_lfanew = GetDosHeader ().e_lfanew ;
909+ DWORD dosStubSize = 0 ;
910+ if (e_lfanew > sizeof (IMAGE_DOS_HEADER)) {
911+ dosStubSize = e_lfanew - sizeof (IMAGE_DOS_HEADER);
912+
913+ BYTE* pDosStub = GetDosStub ();
914+ if (pDosStub) {
915+ writeSize = dosStubSize;
916+ if (!WriteMemoryToFile (_hFile, fileOffset, writeSize, pDosStub)) {
917+ ret = false ;
918+ break ;
919+ }
920+ fileOffset += writeSize;
921+ }
922+ }
923+
924+ if (!IsPe64 ()) {
925+ writeSize = sizeof (IMAGE_NT_HEADERS32);
926+ }
927+ else {
928+ writeSize = sizeof (IMAGE_NT_HEADERS64);
929+ }
930+ PIMAGE_NT_HEADERS64 pNtHeader = GetNtHeader ();
931+ if (!WriteMemoryToFile (_hFile, fileOffset, writeSize, pNtHeader)) {
932+ ret = false ;
933+ break ;
934+ }
935+
936+ fileOffset += writeSize;
937+
938+ writeSize = sizeof (IMAGE_SECTION_HEADER);
939+ auto sections = GetSections ();
940+ for (WORD i = 0 ; i < GetSectionCount (); i++) {
941+ auto section = sections[i];
942+ if (!WriteMemoryToFile (_hFile, fileOffset, writeSize, §ion)) {
943+ ret = false ;
944+ break ;
945+ }
946+ fileOffset += writeSize;
947+ }
948+
949+
950+ for (WORD i = 0 ; i < GetSectionCount (); i++) {
951+ auto section = sections[i];
952+ if (!section.PointerToRawData )
953+ continue ;
954+
955+ if (section.PointerToRawData > fileOffset) {
956+ writeSize = section.PointerToRawData - fileOffset;
957+
958+ if (!WriteZeroMemoryToFile (_hFile, fileOffset, writeSize)) {
959+ ret = false ;
960+ break ;
961+ }
962+ fileOffset += writeSize;
963+ }
964+
965+ writeSize = section.SizeOfRawData ;
966+
967+ if (writeSize) {
968+ BYTE* pData = GetFileAddress (section.PointerToRawData );
969+ if (!WriteMemoryToFile (_hFile, section.PointerToRawData , writeSize, pData)) {
970+ ret = false ;
971+ break ;
972+ }
973+ fileOffset += writeSize;
974+ }
975+ }
976+
977+ DWORD overlayOffset = GetSectionHeaderBasedFileSize ();
978+
979+ LARGE_INTEGER fileSize = GetFileSize ();
980+ if (fileSize.QuadPart > 0 ) {
981+ DWORD overlaySize = fileSize.QuadPart - overlayOffset;
982+
983+ if (overlaySize) {
984+ writeSize = overlaySize;
985+ BYTE* pOverlayData = GetFileAddress (overlayOffset);
986+ if (!WriteMemoryToFile (_hFile, fileOffset, writeSize, pOverlayData)) {
987+ ret = false ;
988+ break ;
989+ }
990+ fileOffset += writeSize;
991+ }
992+ }
993+
994+ SetEndOfFile (_hFile);
995+ } while (false );
996+
997+
998+ if (_hFile != INVALID_HANDLE_VALUE) {
999+ CloseHandle (_hFile);
1000+ _hFile = INVALID_HANDLE_VALUE;
1001+ }
1002+
1003+ return ret;
1004+ }
1005+
1006+ bool PEParser::WriteZeroMemoryToFile (HANDLE hFile, DWORD fileOffset, DWORD size) {
1007+ bool ret = false ;
1008+ PVOID pZeroMemory = calloc (size, 1 );
1009+
1010+ if (pZeroMemory) {
1011+ ret = WriteMemoryToFile (hFile, fileOffset, size, pZeroMemory);
1012+ free (pZeroMemory);
1013+ }
1014+
1015+ return ret;
7951016}
0 commit comments