2016.01.03 11:53

VMWare 12 + Windows 10 Bug

Lyn
조회 수 3225 추천 수 0 댓글 0
Atachment
첨부 '2'
?

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

VMWare 12에 Windows 10 을 올리면 OS에서 CPU 갯수를 인식하지 못하는 버그가 있습니다.

 

vm.PNG

 

위 스샷처럼 VMWare 에서 2 Processor * 1 Core 로 세팅을 하면 OS의 작업관리자에선 1Socket * 1 Virtual Processor 로 잡힙니다.

반대로 1 Processor * 2 Core 로 세팅하면 작업관리자에서도 정상적으로 잡힙니다.

vmw.PNG

 

 

어느쪽 버그인진 모르겠지만 주의해야 할 점입니다.

TAG •
?

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

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

윈도 10을 쓰고 있다가 어느날 게임을 하려는데 그래픽드라이버에 문제가 있는것을 발견했습니다.

그래서 드라이버를 다운그레이드 했는데... 이 빌어먹을 윈도 업데이트가 자동으로 드라이버를 올려버리는겁니다 (...)

그래서 방법을 찾다보니, 아래와 같은 툴을 MS가 제공 하고 있습니다.

드라이버 업데이트를 선택적으로 끌 수 있게 되어 있네요.

 

.. 다행입니다.

 

https://support.microsoft.com/en-us/kb/3073930

TAG •
?

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

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

Windows 는 Vista 부터 고 DPI 지원을 하기 시작 했는데, 이게 버전마다 좀 차이가 있다.

 

Vista : DPI 변경시 재부팅 필요함

7 : DPI 변경시 로그아웃 필요함

8 : DPI 변경시 로그아웃 필요함.

8.1 : DPI 변경시 로그아웃 필요 없음!!!

 

여기서 중요한 이슈가 발생 하는데, 8.1에서 로그아웃이 필요 없다는 것은 프로그램 실행중에 DPI 가 바뀔 수 있다는점이다. 결국 MS는 이 문제를 해결하기 위해 메시지 하나를 추가하는데 바로 WM_DPICHANGED 이다. 당연하겠지만 Windows 8.1 이상에서만 발생하며, Windows SDK 도 8.1 이상을 써야한다(뭐 어차피 달랑 정수값 하나니 그냥 선언해서 써도 되긴 하지만 ...)

 

 

참조 : https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx

TAG •
?

Lyn
조회 수 3636 추천 수 0 댓글 0
Atachment
첨부 '4'
?

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

네. 요즘 고해상도 디스플레이(맥북 프로 레티나 라거나, 4K 모니터 라거나, 아니면 Razer Blade나 Aorus X3 Plus 같은) 디바이스가 꽤 늘어 났습니다.

이런놈들 말이죠


dpi3.png


dpi4.png






하지만 윈도는 고해상도 지원 꽤 느린편이어서 Vista 부터 일단 지원은 햇지만 거의 쓰이지 않았고 본격적인 지원은 역시 8 부터라고 보이는데요. 뭐 사실 윈도 7이 나온 2009년보다도 한참 지난 2012년 맥북 프로 레티나 부터 PC/랩탑용 고해상도 디스플레이가 등장 했으니 그러려니 합니다.


어쨋든 중요한건 이제 저런 장비를 쓰는 사람들도 있고 하니 고 DPI 지원을 해야 한다는거겠지요.
그러려면 DPI 를 가져와야 하는데 그 방법중 하나인 Direct2D 를 이용한 방법을 간단히 정리 해 둡니다.


개발자 답게 코드부터 보자면 

#include <iostream>
#include <D2d1.h>

using namespace std;

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

void wmain()
{
    ID2D1Factory* pD2DFactory = nullptr;
    if (SUCCEEDED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory)))
    {
        float dpix, dpiy;
        pD2DFactory->ReloadSystemMetrics();
        pD2DFactory->GetDesktopDpi(&dpix, &dpiy);
        pD2DFactory->Release();

        wcout << L"X : " << dpix << endl << L"Y : " << dpiy << endl;
    }
    else
    {
        wcout << L"Direct 2D Create Error";
    }    
}

라는 대단히 심플 한 코드로 가져올 수 있습니다.

D2D 팩토리를 생성후 ReloadSystemMetrics 호출 후 GetDesktopDpi 를 통해서 가져오는 매우 심플한 방식인데, ReloadSystemMetrics  를 하지 않으면 팩토리 생성 후 변화된 Dpi 설정을 가져오지 못합니다(내부에서 캐시하는듯)


dpi1.png




위와 같은 실행 결과가 나옵니다. 윈도우의 기본 DPI(100%) 값은 96 으로서 이는 23인치 FullHD에 맞도록 세팅 된 값입니다(사실 "현재까지 쓰인 일반적인" 모니터의 크기와 해상도라면 대부분 매칭 됩니다. 17인치 1280*1024 도 96DPI 입니다)

그럼 125%로 바꿔서 한번 테스트 해 보겠습니다.

dpi2.png


 

네. 96 * 1.25 = 120 이니까 정확히 나오네요.

 

당연하겠지만 Direct2D 를 사용 한 방식이므로 Windows Vista Sp2 or Higher 를 요구합니다.

TAG •
?

Atachment
첨부 '3'
?

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

오늘 같은 MS VC++ MVP이신 유영천 님께서 개인 프로젝트로 출시하신 Project D Online(Steam에서 즐기실 수 있습니다)에 재밋는 이슈가 발생하였습니다.

바로 vmovd eax,xmm0 명령어에서 illegal instruction 오류를 내면서 크래시가 난다는건데요, 원인분석의 결과를 한번 공유해 보겠습니다.


인텔에서는 2011년 새로운 SIMD 명령어인 AVX를 지원하는 CPU를 출시 하였고, 당연히 그 이후 각 컴파일러들은 해당 명령어에 대한 지원을 시작하엿고 당연히 현재 최신의 MS C++ 컴파일러인 VC++2013버전에서는 2011년에 출시된 AVX 명령어를 지원 하고 있습니다.


AVX를 지원하는 CPU는 아래와 같습니다. 출처는 영문판 위키입니다

원본 : http://en.wikipedia.org/wiki/Advanced_Vector_Extensions

 


인텔은 샌디브릿지 이상, AMD는 불도저 이상이군요. 저도 하스웰-E 가지고싶습니다...


VC++2013의 intrin.h에는 각 어셈명령어와 매칭되는 함수들과 타입이 제공 되고, dvec.h 에는 2개의 클래스 F32vec8과 F64vec4가 제공됩니다.
각각 단정밀도 8개, 배정밀도 4개를 동시에 계산할 수 있는 클래스인데요


극히 간단한 샘플 코드를 돌려 보겠습니다


#include <cstdio>
#include <dvec.h>

int main()
{	
	F32vec8 A(1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f);
	F32vec8 B(1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f);		
	
	A += B;

	printf("%f %f %f %f %f %f %f %f", A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7]);
		
	return 0;
}


아래와 같은 경고가 발생하는데, 뭐 일단 여기에선 무시해도 상관 없고, 빌드 옵션에 추가해도 상관 없습니다.
어차피 바이너리엔 영향 없으니까요.


01.png


그럼 위 코드는 어떤 바이너리를 만들어 낼까요?

02.png


대충 이와 같습니다.
v 로 시작하는 명령어들이 AVX명령어 들인데 8개의 float += 연산을 단 한줄로 끝내는것을 볼 수 있습니다.


하지만 세상엔 똥컴(.....) 을 쓰시는분들이 참 많고 당연히 AVX를 지원하지 않는 CPU에서도 프로그램을 돌려야할 경우가 있습니다. 하지만 그렇게 되면 최적화를 상당부분 포기하게 되죠. java나 .net 처럼 JIT 을 지원하는 환경이라면 처음 실행할때 가상머신이 CPU 를 확인해서 최적의 명령어셋으로 만들어 내겠지만(이게 닷넷, 자바의 속도가 간혹 C보다 빨라지는 이유중 하나이기도 합니다) 미리 다 바이너리로 만들어져 있는 Native Application 들은 이런 방법이 불가능 합니다. 

그래서 자주 쓰는 방법은, 미리 CPU 종류별로 다 코드를 컴파일 해 두고, 실행할때 CPU가 지원하는 최적의 명령어를 실행하도록 분기하는거죠... 실제로 극한의 속도를 요하는 라이브러리 (Intel IPP 등) 에서는 당연하다시피 쓰이고 있는 방식이고, 일반적인 라이브러리를 만들때도 쓰이는 경우가 있습니다. 혹시 리눅스에 관심있으신분이라면 최근버전의 리눅스 커널에서 아주 오래된 CPU의 지원이 조금씩 끊기고 있다는것을 아실 수 있는데, 이게 특정 이상의 명령어 셋을 기본적으로 사용하겟다는 의미이기도 합니다.


네 중요한건 바로 여기에 있습니다. VS2013은 내부적 라이브러리에 AVX코드를 생성해서 쓰는 경우가 있다는것이고, cpu의 명령어 셋을 체크 한 후에 쓰기때문에 실행엔 문제가 없어야 합니다만... 현재 명령어 셋을 체크하는것은 cpu만이 아닙니다. 각종 코드 보안 관련 기능에 사용하기 위해 OS도 명령어를 체크하지요.
아래 내용은 역시 영문위키에서 가져왔습니다.... 일일히 찾기귀찮아서


원본 : http://en.wikipedia.org/wiki/Advanced_Vector_Extensions

  • Apple OS X: Support for AVX added in 10.6.8 (Snow Leopard) update[13] released on June 23, 2011.
  • Linux: supported since kernel version 2.6.30,[14] released on June 9, 2009.[15]
  • Windows: supported in Windows 7 SP1 and Windows Server 2008 R2 SP1,[16] Windows 8
  • Windows Server 2008 R2 SP1 with Hyper-V requires a hotfix to support AMD AVX (Opteron 6200 and 4200 series) processors, KB2568088
  • FreeBSD in a patch submitted on 21 January 2012,[17] which was included in the 9.1 stable release[18]
  • DragonFly BSD added support in early 2013.
  • Solaris 10 Update 10 and Solaris 11

  • 리눅스는 굉장히 삐른 편인데 대체 어디서 정보를 얻어서 구현했는진 모르겠습니다(....), 윈도우는 날자가 적혀있지 않아 확인해보니 2011년 3월 15일입니다. 맥은 좀 늦었군요 뭐 어차피 자기들이 하드웨어 내놓을때 같이 내 놓으면 상관없겠습니다. 어차피 OS가 아니라 펌웨어에 가까우니까요


    문제는 여기에서 발생합니다. 바로 CPU는 지원하는데 OS가 지원을 안할 경우입니다 (...)
    위에 써있는것을 보시면 알겠지만 Windows 7은 SP1 이상부터 AVX를 지원합니다. 즉 SP1이 설치되지 않은 구버전의 Windows 7 이라면 AVX명령어가 실행이 되지 않는다는 겁니다....


    그래서 MS는 VC++2013 재배포 패키지( http://www.microsoft.com/en-us/download/details.aspx?id=40784 )  에 다음과 같이 명시 해 두었습니다.

    Supported Operating System

    Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2, Windows XP 


    네 분명히 Windows7 SP1 이라고 적혀 있지요.
    문제는... 저게 SP1이 아닌데도 설치가 된다는겁니다 (....)


    03.png



    그냥 재배포 패키지설치시 확인 해서 올리라고 했었어야 할거 같은데... 어쨋든 안해줍니다 그래서 만약을 대비해 버전 체크를 하시는게 좋습니다.
    빌드넘버로 확인할 수 있는 Windows 7은 6.1.7600, Windows7 SP1은 6.1.7601 로 다르니까요.

    안그러면 이런 크래시가 발생할 수 있습니다.


    사실 AVX 같은 확장명령어로 최적화 될 상황이 그리 많지는 않습니다... 저런걸 쓸 상황이 오는건 진짜 대량의 계산을 요하는 프로그램이나, 영상관련 프로그램, 아니면 게임정도니까요.
    그래도 만약을 대비해서 나쁠건 없겟죠.


    그리고 서비스팩이 설치되지 않은 7600버전의 Windows 7은 더이상 어떤 패치도 제공 되지 않는 상황입니다(Sp1을 올려야 나머지 패치가 적용 됩니다) 그러니까 웬만하면 패치좀 하고 씁시다 (...)

    PS. Project D Online 많이좀 해주세요.

    TAG •
    ?

    2013.09.23 16:20

    현재 MSDN Download Page

    Lyn
    조회 수 19542 추천 수 0 댓글 0
    Atachment
    첨부 '1'
    ?

    단축키

    Prev이전 문서

    Next다음 문서

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

    단축키

    Prev이전 문서

    Next다음 문서

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

    page.png


    얼마전이랑 비교했을때 큰 변화는 없는데 Windows 8.1 Enterprise 가 올라왔네요.
    그외엔 바뀐게 없어보입니다.

    TAG •
    ?

    Lyn
    조회 수 20539 추천 수 0 댓글 1
    Atachment
    첨부 '1'
    ?

    단축키

    Prev이전 문서

    Next다음 문서

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

    단축키

    Prev이전 문서

    Next다음 문서

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

    111111.png

    SQL Server 2014를 제외한 거의 모든 제품이 정식 으로 등록되었네요.
    개인적으론 Hyper-V + WIndows 2012R2에 큰 기대중입니다. VMWare 보며 부러워 했던 기능들이 많이 추가되었네요.

    TAG •
    ?

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

    단축키

    Prev이전 문서

    Next다음 문서

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

    단축키

    Prev이전 문서

    Next다음 문서

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

    두번째 방법으로는 CRT의 예외 핸들러에서 UnhandledExceptionFilter로 데이터를 넘겨서 생성하는 방법인데요...
    이는 안정적이고 정석적이지만 치명적인 단점으로 CRT에서 던지는 예외가 하나가 아니라는겁니다... 


    어쨋든 코드를 보면


    #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 InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
    {
    	EXCEPTION_POINTERS ExceptionPointer;
    	EXCEPTION_RECORD ExceptionRecord;
    	_CONTEXT ContextRecord;
    
    	ZeroMemory(&ContextRecord, sizeof(ContextRecord));
    	RtlCaptureContext(&ContextRecord);
    
    	ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
    	ExceptionRecord.ExceptionCode = STATUS_INVALID_CRUNTIME_PARAMETER;	
    	ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Eip;
    		
    	ExceptionPointer.ExceptionRecord = &ExceptionRecord;
    	ExceptionPointer.ContextRecord = &ContextRecord;
    
    	TopLvFilter(&ExceptionPointer);
    }
    void main()
    {
    	SetUnhandledExceptionFilter(TopLvFilter);
    	_set_invalid_parameter_handler(InvalidParameterHandler);
    	atoi(nullptr);	 
    }



    구조는 간단합니다. RtlCaptureContext 를 이용해서 현재 쓰래드의 Context를 캡쳐 해 오고, 익셉션 코드와 현재 코드가 실행중인 위치를 넘겨 주면 되는데요..
    x86 시스템에서 현재 실행중인 위치는 Eip 레지스터에 있기 때문에 캡쳐해온 Context에서 Eip를 
    ExceptionAddress로 넘겨 주면 됩니다.


    이 방식은 안정적이고 백신이 오진을 할 가능성도 없고 Windows 8 에서도 아무 문제 없이 작동 하지만 ... 위에서 말한것처럼 예외가 이거 하나가 아니라는게 문제가 됩니다.
    예를들어 메모리 할당 예외는 _set_invalid_parameter_handler 로 처리 할 수 없습니다. 하지만 어차피 몇개 안되기도 하고 (...) 그냥 몇개 더 만들어주면 될 문제지요.


    정말 골때려 지는건 3rd party 에서 SetUnhandledExceptionFilter 를 호출해서 자기껄로 만들어버리는 라이브러리가 있다는겁니다 =_=; 적은 내안에만 있는게 아닌거죠...그래서 첫번째 방법과 두번째 방법을 모두 적용해 두는게 좋다고 생각 합니다


    TAG •
    ?

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

    Board Pagination Prev 1 Next
    / 1