Lyn
조회 수 33226 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

사후 디버깅을 위해 가장 많이 쓰이는 방법중 하나가 메모리 덤프를 남기는 방법입니다.

보통 아래와 같은 형태로 구현 하게 되는데요. 과연 이 프로그램은 덤프가 남을까요?


#include <Windows.h>
#include <DbgHelp.h>
#include <cstdio>
#include <string>


using namespace std;

#pragma comment(lib, "dbghelp.lib")

LONG __stdcall TopLvFilter(PEXCEPTION_POINTERS pExceptionPointer)
{
	MINIDUMP_EXCEPTION_INFORMATION MinidumpExceptionInformation;
	std::wstring DumpFileName = L"dmpfile.dmp";

	MinidumpExceptionInformation.ThreadId = ::GetCurrentThreadId();
	MinidumpExceptionInformation.ExceptionPointers = pExceptionPointer;
	MinidumpExceptionInformation.ClientPointers = FALSE;

	if (DumpFileName.empty() == true)
	{
		::TerminateProcess(::GetCurrentProcess(), 0);
	}

	HANDLE hDumpFile = ::CreateFile(DumpFileName.c_str(),
		GENERIC_WRITE,
		FILE_SHARE_WRITE,
		nullptr,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, nullptr);

	MiniDumpWriteDump(GetCurrentProcess(),
		GetCurrentProcessId(),
		hDumpFile,
		MiniDumpNormal,
		&MinidumpExceptionInformation,
		nullptr,
		nullptr);

	::TerminateProcess(::GetCurrentProcess(), 0);

	return 0;
}

void main()
{
	SetUnhandledExceptionFilter(TopLvFilter);	
	atoi(nullptr);
}


네. 결론부터 말하자면 위 코드에서는 덤프가 남지 않습니다.
왜냐면 CRT 에서 에러가 발생하면 UnhandledExceptionFilter 를 CRT가 자신의 예외 핸들러로 다시 세팅 하기 때문입니다.

그러나 우리가 바라는건 별로 친절하지도 않은 (...) CRT의 에러메세지가 아니라 메모리 덤프지요.

우리가 원하는대로 덤프를 남기는 방법은 여러 가지가 있지만 그 중 한가지로 해결 해 보겠습니다.

이번에 사용 할 방법은 코드를 패치해서 CRT가 감히 내가 만든 예외처리기를 바꾸지 못하도록 (...) 하는 방법입니다



#include <Windows.h>
#include <DbgHelp.h>
#include <cstdio>
#include <string>

using namespace std;

#pragma comment(lib, "dbghelp.lib")

BYTE HotPatchingBackup[5];

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI NullSetUnhandledExceptionFilter(
  _In_  LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
)
{
    return nullptr;
}

void InstallAPIHook_SetUnhandledExceptionFilter()
{
    BYTE *pSetUnhandledExceptionFilter;

    DWORD ProtectOption = 0;
    DWORD Temp = 0;

    pSetUnhandledExceptionFilter = (BYTE*)&SetUnhandledExceptionFilter;

	HANDLE hSelfProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE , FALSE, ::GetCurrentProcessId());
	VirtualProtectEx(hSelfProcess, (void *)pSetUnhandledExceptionFilter, 5, PAGE_EXECUTE_WRITECOPY, &ProtectOption);     	

    memcpy(HotPatchingBackup, pSetUnhandledExceptionFilter, 5);

    *pSetUnhandledExceptionFilter = 0xE9;
	pSetUnhandledExceptionFilter++;
    *((DWORD *)(pSetUnhandledExceptionFilter)) = ((DWORD)NullSetUnhandledExceptionFilter) - ((DWORD)pSetUnhandledExceptionFilter + 4);	
	pSetUnhandledExceptionFilter--;

	VirtualProtectEx(hSelfProcess, (void *)pSetUnhandledExceptionFilter, 5, ProtectOption, &Temp);

	CloseHandle(hSelfProcess);
}

void UnInstallAPIHook_SetUnhandledExceptionFilter()
{
    BYTE *pSetUnhandledExceptionFilter;

    DWORD ProtectOption;
    DWORD Temp;

    pSetUnhandledExceptionFilter = (BYTE*)&SetUnhandledExceptionFilter;
	
	HANDLE hSelfProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE , FALSE, ::GetCurrentProcessId());
	VirtualProtectEx(hSelfProcess, (void *)pSetUnhandledExceptionFilter, 5, PAGE_EXECUTE_READWRITE, &ProtectOption);    

    memcpy(pSetUnhandledExceptionFilter, HotPatchingBackup, 5);

	VirtualProtectEx(hSelfProcess, (void *)pSetUnhandledExceptionFilter, 5, ProtectOption, &Temp);     

	CloseHandle(hSelfProcess);
}

LONG __stdcall TopLvFilter(PEXCEPTION_POINTERS pExceptionPointer)
{
    MINIDUMP_EXCEPTION_INFORMATION MinidumpExceptionInformation;
    std::wstring DumpFileName = L"dmpfile.dmp";

    MinidumpExceptionInformation.ThreadId = ::GetCurrentThreadId();
    MinidumpExceptionInformation.ExceptionPointers = pExceptionPointer;
    MinidumpExceptionInformation.ClientPointers = FALSE;

    if (DumpFileName.empty() == true)
    {
        ::TerminateProcess(::GetCurrentProcess(), 0);
    }

    HANDLE hDumpFile = ::CreateFile(DumpFileName.c_str(),
        GENERIC_WRITE,
        FILE_SHARE_WRITE,
        nullptr,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, nullptr);

    MiniDumpWriteDump(GetCurrentProcess(),
        GetCurrentProcessId(),
        hDumpFile,
        MiniDumpNormal,
        &MinidumpExceptionInformation,
        nullptr,
        nullptr);

    ::TerminateProcess(::GetCurrentProcess(), 0);

    return 0;
}

void main()
{
    SetUnhandledExceptionFilter(TopLvFilter);
    InstallAPIHook_SetUnhandledExceptionFilter();
    atoi(nullptr);
    UnInstallAPIHook_SetUnhandledExceptionFilter();
}


API 훅을 해서 필터를 바꾸려 하면 아무 일도 하지 않는 NullSetUnhandledExceptionFilter 이 호출되도록 하여 막는 방법입니다...
멋있어 보이기는 하지만 이 코드는 64bit/32bit 를 따로 만들어야 하고, 심지어 윈도우 8 에서는 이 코드가 정상적으로 동작 하지 않습니다 (....) 아마도 강화된 보안때문에 그런게 아닌가 싶은데...

어쨋든 윈도우7 까지는 정상적으로 덤프가 남습니다.


그럼 이런 편법 말고 좀 정석적인 방법이 필요한데... 그건 다음글로...

TAG •
?

  1. boostpro 문 닫았네요....

    Date2013.11.02 ByLyn Views24050
    Read More
  2. Visual Studio 2013 새로 추가된 기능 둘러보기

    Date2013.10.28 ByLyn Views19973
    Read More
  3. Microsoft C++ MVP 리워드를 개봉 해 보았습니다.

    Date2013.10.11 ByLyn Views51212
    Read More
  4. MS SQL Server 2012 언인스톨시 Rsfx Driver 의존성으로 인해 언인스톨이 되지 않는 경우

    Date2013.10.09 ByLyn Views20042
    Read More
  5. Visual C++ 2013 RC 추가기능 1. Raw String Literal

    Date2013.10.07 ByLyn Views15869
    Read More
  6. Microsoft VC++ MVP를 받았습니다....

    Date2013.10.02 ByLyn Views15264
    Read More
  7. 서버를 Windows 2012 R2로 교체 하였습니다.

    Date2013.09.29 ByLyn Views22223
    Read More
  8. VS2013 RC 설치해봄

    Date2013.09.28 ByLyn Views14139
    Read More
  9. 현재 MSDN Download Page

    Date2013.09.23 ByLyn Views19681
    Read More
  10. boost::icl::interval_map 원하는대로 변경해서 사용해보기

    Date2013.09.23 ByLyn Views22406
    Read More
  11. MSDN 에 릴리즈된 MS 제품들입니다.

    Date2013.09.10 ByLyn Views20681
    Read More
  12. C Runtime Library Exception Dump 남기기 두번째 방법

    Date2013.06.25 ByLyn Views26014
    Read More
  13. C Runtime Library Exception Dump 남기기 첫번째방법

    Date2013.06.11 ByLyn Views33226
    Read More
  14. Visual Studio 2012 Update2 Offline 설치

    Date2013.04.11 ByLyn Views23650
    Read More
  15. C++11 표준 라이브러리 확장 (cbegin, cend)

    Date2012.10.04 ByLyn Views34620
    Read More
  16. C++11 표준 라이브러리 확장 (string)

    Date2012.09.10 ByLyn Views28517
    Read More
  17. 대기하는 쓰래드 모두 깨우기 (Java의 notifyAll)

    Date2012.09.04 ByLyn Views38096
    Read More
  18. C++ 템플릿 상속에서 베이스 클래스의 멤버에 접근하는 경우의 문제

    Date2012.08.29 ByLyn Views30558
    Read More
  19. [윈도8] 윈도8 구경1

    Date2012.08.17 ByLyn Views26691
    Read More
  20. C++ string&형 인자에 기본값 주기

    Date2012.07.24 ByLyn Views26073
    Read More
Board Pagination Prev 1 ... 2 3 4 5 6 7 ... 8 Next
/ 8