Lyn
조회 수 33024 추천 수 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 •
?

List of Articles
번호 제목 글쓴이 날짜 조회 수
57 Visual Studio 2013 새로 추가된 기능 둘러보기 file Lyn 2013.10.28 19824
56 Microsoft C++ MVP 리워드를 개봉 해 보았습니다. 3 file Lyn 2013.10.11 51042
55 MS SQL Server 2012 언인스톨시 Rsfx Driver 의존성으로 인해 언인스톨이 되지 않는 경우 Lyn 2013.10.09 19910
54 Visual C++ 2013 RC 추가기능 1. Raw String Literal 3 file Lyn 2013.10.07 15728
53 Microsoft VC++ MVP를 받았습니다.... file Lyn 2013.10.02 15122
52 서버를 Windows 2012 R2로 교체 하였습니다. 1 Lyn 2013.09.29 22082
51 VS2013 RC 설치해봄 file Lyn 2013.09.28 14019
50 현재 MSDN Download Page file Lyn 2013.09.23 19526
49 boost::icl::interval_map 원하는대로 변경해서 사용해보기 file Lyn 2013.09.23 22200
48 MSDN 에 릴리즈된 MS 제품들입니다. 1 file Lyn 2013.09.10 20526
47 C Runtime Library Exception Dump 남기기 두번째 방법 Lyn 2013.06.25 25803
» C Runtime Library Exception Dump 남기기 첫번째방법 Lyn 2013.06.11 33024
45 Visual Studio 2012 Update2 Offline 설치 1 Lyn 2013.04.11 23450
44 C++11 표준 라이브러리 확장 (cbegin, cend) Lyn 2012.10.04 34452
43 C++11 표준 라이브러리 확장 (string) 3 file Lyn 2012.09.10 28238
42 대기하는 쓰래드 모두 깨우기 (Java의 notifyAll) Lyn 2012.09.04 37891
41 C++ 템플릿 상속에서 베이스 클래스의 멤버에 접근하는 경우의 문제 1 file Lyn 2012.08.29 30233
40 [윈도8] 윈도8 구경1 1 file Lyn 2012.08.17 26510
39 C++ string&형 인자에 기본값 주기 Lyn 2012.07.24 25860
38 [작성중] 윈도우 32bit, 64bit 프로그래밍시 주의할점 2 Lyn 2012.07.16 27598
Board Pagination Prev 1 ... 2 3 4 5 6 7 ... 8 Next
/ 8