/* Benjamin DELPY `gentilkiwi` https://blog.gentilkiwi.com benjamin@gentilkiwi.com Licence : https://creativecommons.org/licenses/by/4.0/ */ #include "kull_m_minidump.h" BOOL kull_m_minidump_open(IN HANDLE hFile, OUT PKULL_M_MINIDUMP_HANDLE *hMinidump) { BOOL status = FALSE; *hMinidump = (PKULL_M_MINIDUMP_HANDLE) LocalAlloc(LPTR, sizeof(KULL_M_MINIDUMP_HANDLE)); if(*hMinidump) { (*hMinidump)->hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if((*hMinidump)->hFileMapping) { if((*hMinidump)->pMapViewOfFile = MapViewOfFile((*hMinidump)->hFileMapping, FILE_MAP_READ, 0, 0, 0)) status = (((PMINIDUMP_HEADER) (*hMinidump)->pMapViewOfFile)->Signature == MINIDUMP_SIGNATURE) && ((WORD) (((PMINIDUMP_HEADER) (*hMinidump)->pMapViewOfFile)->Version) == MINIDUMP_VERSION); } if(!status) kull_m_minidump_close(*hMinidump); } return status; } BOOL kull_m_minidump_close(IN PKULL_M_MINIDUMP_HANDLE hMinidump) { if(hMinidump->pMapViewOfFile) UnmapViewOfFile(hMinidump->pMapViewOfFile); if(hMinidump->hFileMapping) CloseHandle(hMinidump->hFileMapping); return TRUE; } LPVOID kull_m_minidump_RVAtoPTR(IN PKULL_M_MINIDUMP_HANDLE hMinidump, RVA64 rva) { return (PBYTE) (hMinidump->pMapViewOfFile) + rva; } LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STREAM_TYPE type, OUT OPTIONAL DWORD *pSize) { ULONG32 i; PMINIDUMP_DIRECTORY pStreamDirectory = (PMINIDUMP_DIRECTORY) kull_m_minidump_RVAtoPTR(hMinidump, ((PMINIDUMP_HEADER) (hMinidump->pMapViewOfFile))->StreamDirectoryRva); for(i = 0; i < ((PMINIDUMP_HEADER) (hMinidump->pMapViewOfFile))->NumberOfStreams; i++) { if(pStreamDirectory[i].StreamType == type) { if(pSize) *pSize = pStreamDirectory[i].Location.DataSize; return kull_m_minidump_RVAtoPTR(hMinidump, pStreamDirectory[i].Location.Rva); } } return NULL; } BOOL kull_m_minidump_copy(IN PKULL_M_MINIDUMP_HANDLE hMinidump, OUT VOID *Destination, IN VOID *Source, IN SIZE_T Length) { BOOL status = FALSE; PMINIDUMP_MEMORY64_LIST myDir = NULL; //MINIDUMP_STREAM_TYPE types[] = {Memory64ListStream, MemoryListStream}; PBYTE ptr; ULONG64 nMemory64; PMINIDUMP_MEMORY_DESCRIPTOR64 memory64; ULONG64 offsetToRead, offsetToWrite, lengthToRead, lengthReaded = 0; if(myDir = (PMINIDUMP_MEMORY64_LIST) kull_m_minidump_stream(hMinidump, Memory64ListStream, NULL)) { ptr = (PBYTE) kull_m_minidump_RVAtoPTR(hMinidump, myDir->BaseRva); for(nMemory64 = 0; nMemory64 < myDir->NumberOfMemoryRanges; nMemory64++, ptr += memory64->DataSize) { memory64 = &(myDir->MemoryRanges[nMemory64]); if( (((ULONG64) Source >= memory64->StartOfMemoryRange) && ((ULONG64) Source < (memory64->StartOfMemoryRange + memory64->DataSize))) || (((ULONG64) Source + Length >= memory64->StartOfMemoryRange) && ((ULONG64) Source + Length < (memory64->StartOfMemoryRange + memory64->DataSize))) || (((ULONG64) Source < memory64->StartOfMemoryRange) && ((ULONG64) Source + Length > (memory64->StartOfMemoryRange + memory64->DataSize))) ) { if((ULONG64) Source < memory64->StartOfMemoryRange) { offsetToRead = 0; offsetToWrite = memory64->StartOfMemoryRange - (ULONG64) Source; } else { offsetToRead = (ULONG64) Source - memory64->StartOfMemoryRange; offsetToWrite = 0; } lengthToRead = Length - offsetToWrite; if(offsetToRead + lengthToRead > memory64->DataSize) lengthToRead = memory64->DataSize - offsetToRead; RtlCopyMemory((PBYTE) Destination + offsetToWrite, ptr + offsetToRead, (SIZE_T) lengthToRead); lengthReaded += lengthToRead; } } status = (lengthReaded == Length); } return status; } LPVOID kull_m_minidump_remapVirtualMemory64(IN PKULL_M_MINIDUMP_HANDLE hMinidump, IN VOID *Source, IN SIZE_T Length) { BOOL status = FALSE; LPVOID myDir; PBYTE startPtr = NULL, ptr; ULONG64 nMemory64, previousPtr = 0, previousSize = 0, size = 0; PMINIDUMP_MEMORY_DESCRIPTOR64 memory64; myDir = kull_m_minidump_stream(hMinidump, Memory64ListStream, NULL); if(myDir) { ptr = (PBYTE) kull_m_minidump_RVAtoPTR(hMinidump, ((PMINIDUMP_MEMORY64_LIST) myDir)->BaseRva); for(nMemory64 = 0; nMemory64 < ((PMINIDUMP_MEMORY64_LIST) myDir)->NumberOfMemoryRanges; nMemory64++, ptr += memory64->DataSize) { memory64 = &(((PMINIDUMP_MEMORY64_LIST) myDir)->MemoryRanges[nMemory64]); if(((ULONG64) Source >= memory64->StartOfMemoryRange) && ((ULONG64) Source < memory64->StartOfMemoryRange + memory64->DataSize)) { startPtr = ptr; previousPtr = memory64->StartOfMemoryRange; previousSize = memory64->DataSize; size = (memory64->StartOfMemoryRange + memory64->DataSize) - (ULONG64) Source; } else if(((ULONG64) Source < memory64->StartOfMemoryRange)) { if(startPtr && (memory64->StartOfMemoryRange == previousPtr + previousSize)) { previousPtr = memory64->StartOfMemoryRange; previousSize = memory64->DataSize; size += memory64->DataSize; } else break; } if(size >= Length) return startPtr; } } return NULL; }