#include "StdAfx.h" #include "DumpProcess.h" //funtionÁ¤º¸¸¦ ¾Ë±âÀ§Çؼ­ »ç¿ëµÊ #include "ProcessManager.h" bool CDumpProcess::LoadFile( const TCHAR* SymbolName ) { //µðÄÚµùÀÌ µÇÁö ¾Ê¾Ò´Ù¸é ·Îµå µÇÁö ¾ÊÀ½! // if (!decodeDumpfile(SymbolName)) // { // return false; // } if(!ReadDumpFile(SymbolName)) { return false; } if(pMapping_) { UnmapViewOfFile(pMapping_); } if(handleMap_) { CloseHandle(handleMap_); } if(handleFile_ != INVALID_HANDLE_VALUE) { CloseHandle(handleFile_); } //·Îµå ÇßÀ¸´Ï±ñ ÀÎÄÚµù! // if (!decodeDumpfile(SymbolName)) // { // return false; // } return true; } void CDumpProcess::Clean() { } bool CDumpProcess::ReadDumpFile( const TCHAR* FileName ) { //ÆÄÀÏ ÇÚµé »ý¼º. handleFile_ = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, NULL,NULL); if( handleFile_ == NULL || handleFile_ == INVALID_HANDLE_VALUE) return false; handleMap_ = CreateFileMapping(handleFile_,NULL,PAGE_READONLY,0,0,NULL); if(handleMap_ == NULL) return false; pMapping_ = (byte*)MapViewOfFile(handleMap_,FILE_MAP_READ,0,0,0); if (memcmp(pMapping_,"MDMP",4) != 0) { return false; } return OnReadDmpFile(); } //»ç¿ëÇÏÁö ¾Ê´Â ¸Þ¼Òµå!!!!!!!!!!!! bool CDumpProcess::OnSearch( DWORD ExceptionAddr , sExceptionInfomation& ExceptionInfo ) { assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess"); return false; } bool CDumpProcess::OnSearch( const char* ExceptionAddr,sExceptionInfomation& ExceptionInfo ) { assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess"); return false; } bool CDumpProcess::OnReadDmpFile() { if(!OnReadMiscInfo()) return false; if(!OnReadMoudleInfo()) return false; if(!OnReadSystemInfo()) return false; if(!OnReadCrashInfo()) return false; if(!OnReadMemoryInfo()) return false; if(!OnReadThreadInfo()) return false; return true; } bool CDumpProcess::OnReadMiscInfo() { MINIDUMP_MISC_INFO* pMiscInfo = (MINIDUMP_MISC_INFO*)GetDumpInfo(MiscInfoStream); if(!pMiscInfo) return false; if (pMiscInfo->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES) { ProcessTime_ = pMiscInfo->ProcessCreateTime; UserTime_ = pMiscInfo->ProcessUserTime; KerenlTime_ = pMiscInfo->ProcessKernelTime; } return true; } bool CDumpProcess::OnReadMoudleInfo() { MINIDUMP_MODULE_LIST* pModuleinfo = (MINIDUMP_MODULE_LIST*)GetDumpInfo(ModuleListStream); MINIDUMP_MODULE* pModule = NULL; MINIDUMP_STRING* pModuleString = NULL; if(!pModuleinfo) return false; //¸ðµâÀÇ °¹¼ö´Â 0°³º¸´Ù Ä¿¾ßµÊ. if(pModuleinfo->NumberOfModules > 0) { pModule = &pModuleinfo->Modules[0]; //ÀÌ·±°æ¿ì°¡ ÀÖÀ»Áö ¸ð¸£°ÚÁö¸¸... ¸ðµâÁ¤º¸´Â »ý¼ºµÇ¾úÁö¸¸ ¸ðµâÀÌ ¾øÀ»¼ö ÀÖ³ª? if(!pModule) return false; //óÀ½ ¸ðµâ Á¤º¸¸¸! pModuleString = (MINIDUMP_STRING*)((char*)pMapping_ + pModule->ModuleNameRva); _tcsncpy(stringModuleName_,pModuleString->Buffer,sizeof(TCHAR)*256); DumpModule_.reserve(pModuleinfo->NumberOfModules); for (size_t index = 0 ; index < pModuleinfo->NumberOfModules ; ++index) { DumpModule_.push_back(pModuleinfo->Modules[index]); } return true; } return false; } bool CDumpProcess::OnReadCrashInfo() { MINIDUMP_EXCEPTION_STREAM* pExceptionStream = (MINIDUMP_EXCEPTION_STREAM*)GetDumpInfo(ExceptionStream); if(!pExceptionStream) return false; ExcpetionStreamPointer_ = pExceptionStream; ExceptionCode_ = pExceptionStream->ExceptionRecord.ExceptionCode; ExceptionAddr_ = pExceptionStream->ExceptionRecord.ExceptionAddress; ExceptionInfo_ = pExceptionStream->ExceptionRecord; //¿¹¿Ü°¡ ³­ ¾²·¹µå Á¤º¸¸¦ ¹Þ±âÀ§Çؼ­! ThreadContext_ = pExceptionStream->ThreadContext; ThreadId_ = pExceptionStream->ThreadId; FIndExceptionCode(ExceptionCode_); return true; } bool CDumpProcess::OnReadSystemInfo() { MINIDUMP_SYSTEM_INFO* pSystemInfo = (MINIDUMP_SYSTEM_INFO*)GetDumpInfo(SystemInfoStream); if(!pSystemInfo) return false; ProcessorArchitecture_ = pSystemInfo->ProcessorArchitecture; ProcessorLevel_ = pSystemInfo->ProcessorLevel; ProcessorRevision_ = pSystemInfo->ProcessorRevision; MajorVersion_ = pSystemInfo->MajorVersion; MinorVersion_ = pSystemInfo->MinorVersion; BuildNumber_ = pSystemInfo->BuildNumber; PlatformId_ = pSystemInfo->PlatformId; return true; } //¸Þ¸ð¸® Á¤·Ä¿¡ »ç¿ë bool Compare(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b ) { return a.StartOfMemoryRange < b.StartOfMemoryRange; } bool CDumpProcess::OnReadMemoryInfo() { MINIDUMP_MEMORY_LIST* pMemList = (MINIDUMP_MEMORY_LIST*)GetDumpInfo(MemoryListStream); if (!pMemList) return false; DumpMemory_.reserve(pMemList->NumberOfMemoryRanges); for (size_t index = 0 ; index < pMemList->NumberOfMemoryRanges ; ++index) { const byte* ptrISRange = (byte*)pMapping_ + pMemList->MemoryRanges[index].Memory.Rva; UINT sizeIsRange = pMemList->MemoryRanges[index].Memory.DataSize; if(!IsBadReadPtr(ptrISRange,sizeIsRange) ) { DumpMemory_.push_back(pMemList->MemoryRanges[index]); } } MINIDUMP_MEMORY64_LIST* pMemList64 = (MINIDUMP_MEMORY64_LIST*)GetDumpInfo(Memory64ListStream); if (pMemList64) { DumpMemory_.reserve(pMemList64->NumberOfMemoryRanges); UINT rav = pMemList64->BaseRva; for (size_t index = 0 ; index < pMemList64->NumberOfMemoryRanges ; ++index) { MINIDUMP_MEMORY_DESCRIPTOR memoryDescriptor; memoryDescriptor.StartOfMemoryRange = pMemList64->MemoryRanges[index].StartOfMemoryRange; memoryDescriptor.Memory.DataSize = pMemList64->MemoryRanges[index].DataSize; memoryDescriptor.Memory.Rva = rav; rav += memoryDescriptor.Memory.DataSize; DumpMemory_.push_back(memoryDescriptor); } } std::sort(DumpMemory_.begin(),DumpMemory_.end(),Compare); return true; } bool CDumpProcess::OnReadThreadInfo() { MINIDUMP_THREAD_LIST* pThreadList = (MINIDUMP_THREAD_LIST*)GetDumpInfo(ThreadListStream); MINIDUMP_THREAD* pThread = NULL; if(!pThreadList) return false; if(pThreadList->NumberOfThreads > 0) { for (int threadID = 0 ; threadID < pThreadList->NumberOfThreads ; ++threadID ) { pThread = &pThreadList->Threads[threadID]; //ÀÌ ¾²·¹µå°¡ ¿¹¿Ü°¡ ³­ ½º·¹µåÀÌ´Ù! if(pThread->ThreadId == ThreadId_) break; } //ÀÌ·±°æ¿ì°¡ ÀÖÀ»Áö ¸ð¸£°ÚÁö¸¸... ¸ðµâÁ¤º¸´Â »ý¼ºµÇ¾úÁö¸¸ ¸ðµâÀÌ ¾øÀ»¼ö ÀÖ³ª? if(!pThread) return false; //ÄÝ ½ºÅØ ¸Þ¸ð¸® À籸¼º //µ¥ÀÌÅ͸¦ ÀÐÀ»¶§´Â 4¹ÙÀÌÆ®·Î Á¤·ÄµÇµµ·Ï Á¶Á¤ UINT stackAddr = UINT(pThread->Stack.StartOfMemoryRange); UINT stacksize = pThread->Stack.Memory.DataSize; if ((stackAddr % 4) != 0) { int addr = 4 - (stackAddr % 4); stackAddr += addr; stacksize -= addr; } UINT LastFrameAddrSave = 0; UINT LastFrameValueSave = 0; bool LastFrameLinked = false; //½ºÅØÀ» ÀÐÀ¸¸é¼­ È®ÀÎ ÀÛ¾÷. CONTEXT ThreadContext; const CONTEXT* ctx = (const CONTEXT*)(pMapping_ + pThread->ThreadContext.Rva); if(!IsBadReadPtr(ctx,sizeof(CONTEXT))) { ThreadContext = *ctx; LastFrameValueSave = ThreadContext.Ebp; } UINT stackaddrEnd = stackAddr + stacksize; for (UINT addr = stackAddr ; addr < stackaddrEnd ; addr += 4) { UINT value; if (ReadMemoryValue(addr,&value) == false) { break; } if (value >= stackAddr && value < stackAddr) { LastFrameLinked = (LastFrameValueSave == addr); LastFrameAddrSave = addr; LastFrameValueSave = value; } } } return true; } PVOID CDumpProcess::GetDumpInfo( ULONG Type ) { if(!pMapping_) return NULL; ULONG Size = 0; void* pStream = NULL; MINIDUMP_DIRECTORY* pDir = NULL; if (!MiniDumpReadDumpStream((PVOID)pMapping_,Type,&pDir,&pStream,&Size)) { return NULL; } return pStream; } void CDumpProcess::OnExceptionCause( DWORD exceptioncuase,TCHAR* String,size_t Size ) { struct ExceptionNames { DWORD ExceptionCode; TCHAR ExceptionName[256]; }; } //¸Þ¸ð¸® Á¤·Ä¿¡ »ç¿ë bool Compare2(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b ) { if(a.StartOfMemoryRange < b.StartOfMemoryRange) return true; return false; } int CDumpProcess::ReadMemory( int addr, int size, byte* buffer ) { UINT CurrentAddr = addr; int LeftSize = size; while (LeftSize > 0) { //¸Þ¸ð¸® Áß¿¡¼­ ÇöÀç ¸Þ¸ð¸®¸¦ °¡Áø ¾ÆÀÌÅÛÀ» ã´Â´Ù. MINIDUMP_MEMORY_DESCRIPTOR valueMemory; valueMemory.StartOfMemoryRange = CurrentAddr; std::vector::iterator iterMem = std::lower_bound(DumpMemory_.begin(),DumpMemory_.end(),valueMemory,Compare2); if(iterMem == DumpMemory_.begin()) break; iterMem--; int posInRange = CurrentAddr - UINT(iterMem->StartOfMemoryRange); int availableInRange = iterMem->Memory.DataSize - posInRange; if (availableInRange <= 0) break; if (LeftSize <= availableInRange) { memcpy(buffer + (CurrentAddr - addr) , pMapping_ + (iterMem->Memory.Rva + posInRange), LeftSize); CurrentAddr += LeftSize; LeftSize = 0; } else { memcpy(buffer + (CurrentAddr - addr) , pMapping_ + (iterMem->Memory.Rva + posInRange), availableInRange); CurrentAddr += availableInRange; LeftSize -= availableInRange; } } return size - LeftSize; } void CDumpProcess::OnInitation() { } void CDumpProcess::FIndExceptionCode( DWORD ExceptionCode ) { switch (ExceptionCode) { case STATUS_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_WAIT_0")); break; case STATUS_ABANDONED_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ABANDONED_WAIT_0")); break; case STATUS_USER_APC: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_USER_APC")); break; case STATUS_TIMEOUT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_TIMEOUT")); break; case STATUS_PENDING: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PENDING")); break; case DBG_EXCEPTION_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_HANDLED")); break; case DBG_CONTINUE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTINUE")); break; case STATUS_SEGMENT_NOTIFICATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SEGMENT_NOTIFICATION")); break; case DBG_TERMINATE_THREAD: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_THREAD")); break; case DBG_TERMINATE_PROCESS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_PROCESS")); break; case DBG_CONTROL_C: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_C")); break; case DBG_CONTROL_BREAK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_BREAK")); break; case DBG_COMMAND_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_COMMAND_EXCEPTION")); break; case STATUS_GUARD_PAGE_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_GUARD_PAGE_VIOLATION")); break; case STATUS_DATATYPE_MISALIGNMENT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_DATATYPE_MISALIGNMENT")); break; case STATUS_BREAKPOINT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_BREAKPOINT")); break; case STATUS_SINGLE_STEP: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SINGLE_STEP")); break; case DBG_EXCEPTION_NOT_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_NOT_HANDLED")); break; case STATUS_ACCESS_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ACCESS_VIOLATION")); break; case STATUS_IN_PAGE_ERROR: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_IN_PAGE_ERROR")); break; case STATUS_INVALID_HANDLE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_HANDLE")); break; case STATUS_NO_MEMORY: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NO_MEMORY")); break; case STATUS_ILLEGAL_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ILLEGAL_INSTRUCTION")); break; case STATUS_NONCONTINUABLE_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NONCONTINUABLE_EXCEPTION")); break; case STATUS_INVALID_DISPOSITION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_DISPOSITION")); break; case STATUS_ARRAY_BOUNDS_EXCEEDED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ARRAY_BOUNDS_EXCEEDED")); break; case STATUS_FLOAT_DENORMAL_OPERAND: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DENORMAL_OPERAND")); break; case STATUS_FLOAT_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DIVIDE_BY_ZERO")); break; case STATUS_FLOAT_INEXACT_RESULT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INEXACT_RESULT")); break; case STATUS_FLOAT_INVALID_OPERATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INVALID_OPERATION")); break; case STATUS_FLOAT_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_OVERFLOW")); break; case STATUS_FLOAT_STACK_CHECK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_STACK_CHECK")); break; case STATUS_FLOAT_UNDERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_UNDERFLOW")); break; case STATUS_INTEGER_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_DIVIDE_BY_ZERO")); break; case STATUS_INTEGER_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_OVERFLOW")); break; case STATUS_PRIVILEGED_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PRIVILEGED_INSTRUCTION")); break; case STATUS_STACK_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_STACK_OVERFLOW")); break; case STATUS_CONTROL_C_EXIT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_CONTROL_C_EXIT")); break; case STATUS_FLOAT_MULTIPLE_FAULTS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_FAULTS")); break; case STATUS_FLOAT_MULTIPLE_TRAPS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_TRAPS")); break; case STATUS_REG_NAT_CONSUMPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_REG_NAT_CONSUMPTION")); break; case STATUS_SXS_EARLY_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_EARLY_DEACTIVATION")); break; case STATUS_SXS_INVALID_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_INVALID_DEACTIVATION")); break; case 0xE06D7363: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("Microsoft C++ Exception")); break; default: _stprintf_s(stringExceptionCause_, 256, _T("0x%08X"), ExceptionCode); } } TCHAR* CDumpProcess::GetVersion(const _TCHAR* filename) { TCHAR* string_buffer; const int kVersion_Depth = 15; //strlen("120104_0410.dmp") string_buffer = _tcsstr(_tcslwr((_TCHAR*)filename), L"sungame_"); int string_length = 0; if (string_buffer) { string_length = (int)_tcslen(string_buffer); } if (string_length - kVersion_Depth >= 0) { _TCHAR* string_pointer = string_buffer + (string_length - kVersion_Depth); wsprintf(version_string, L"webzen@%d", _tstoi(string_pointer)); } else { wsprintf(version_string, L"webzen@version"); } return version_string; } bool CDumpProcess::decodeDumpfile( const TCHAR* DumpNmae ) { AuMD5Encrypt Decoder; std::fstream file; file.open(DumpNmae, std::ios::in | std::ios::out | std::ios::binary); if (!file) { MessageBox(NULL,L"ÆÄÀÏÀ» ¿­¼ö ¾ø½À´Ï´Ù",L"¿À·ù",MB_OK); return false; } file.seekg(0, std::ios::end); size_t size = file.tellg(); char* buffer = new char[size]; file.seekg(0, std::ios::beg); file.read(buffer, (unsigned int)size); TCHAR* VersionString = GetVersion(DumpNmae); char TempVersion[256]; WideCharToMultiByte ( CP_ACP, 0, VersionString, -1, TempVersion, 256, NULL, NULL ); if (!Decoder.DecryptString(TempVersion, buffer, (unsigned int)size)) { TCHAR ErrorData[256]; wsprintf(ErrorData,L"DecryptString ¿¡·¯(%s)",DumpNmae); MessageBox(NULL,ErrorData,L"¿À·ù",MB_OK); return false; } file.seekp(0, std::ios::beg); file.write(buffer, (unsigned int)size); file.close(); if (buffer) { delete[] buffer; } return true; }