Skip to content

Commit a9dd48b

Browse files
Added PE dump.
1 parent ddb15d7 commit a9dd48b

5 files changed

Lines changed: 395 additions & 11 deletions

File tree

PEParser/PEParser.cpp

Lines changed: 226 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
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

3855
HANDLE 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

665685
void 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, &section)) {
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
}

PEParser/PEParser.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,17 @@ class PEParser {
179179
bool IsSystemFile() const;
180180

181181
void FixPEHeader();
182+
bool DumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* pDumpFilePath);
183+
void GetPESections();
184+
void GetPESectionData(DWORD_PTR offset, PEFileSection& peFileSection);
185+
void SetEntryPointVA(DWORD_PTR entryPoint);
186+
void SetEntryPointRVA(DWORD rva);
187+
void SetModuleBase(DWORD_PTR va);
188+
bool SavePEFileToDisk(const WCHAR* pNewFile);
189+
bool OpenWriteFileHandle(const WCHAR* pNewFile);
190+
bool WriteMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPVOID pData);
191+
bool WriteZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size);
192+
void GetSectionHeaders();
182193

183194
int GetSectionCount() const;
184195
void SetSectionCount(WORD count);

WinArk/ProcessAccessHelper.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ bool ProcessAccessHelper::OpenProcessHandle(DWORD pid) {
2121
}
2222
}
2323
}
24+
return false;
2425
}
2526

2627
void ProcessAccessHelper::CloseProcessHandle() {
@@ -349,7 +350,6 @@ bool ProcessAccessHelper::DisassembleMemory(BYTE* pMemory, SIZE_T size, DWORD_PT
349350

350351
bool ProcessAccessHelper::GetProcessModules(HANDLE hProcess, std::vector<ModuleInfo>& moduleList) {
351352
ModuleInfo module;
352-
WCHAR fileName[MAX_PATH] = { 0 };
353353
DWORD needed = 0;
354354

355355
_moduleList.reserve(20);
@@ -361,17 +361,18 @@ bool ProcessAccessHelper::GetProcessModules(HANDLE hProcess, std::vector<ModuleI
361361
auto infos = tracker.GetModules();
362362

363363
for (auto& info : infos) {
364-
module._modBaseAddr = (DWORD_PTR)info.get()->ImageBase;
364+
std::wstring path = info.get()->Path;
365+
if (path.empty())
366+
continue;
367+
368+
module._modBaseAddr = (DWORD_PTR)info.get()->Base;
365369
module._modBaseSize = info.get()->ModuleSize;
366370
module._isAlreadyParsed = false;
367371
module._parsing = false;
368372

369-
fileName[0] = 0;
370373
module._fullPath[0] = 0;
371374

372-
wcscpy_s(module._fullPath, info.get()->Path.c_str());
373-
374-
wcscpy_s(fileName, info.get()->Name.c_str());
375+
wcscpy_s(module._fullPath, path.c_str());
375376

376377
_moduleList.push_back(module);
377378
}

0 commit comments

Comments
 (0)