개발을 하다보면 해당 포인터가 유효한지 아닌지를 판별해야하는 경우가 많이 있습니다. 일반적으로 NULL 체크를 하면 대부분 해결되지만 랜덤한 메모리 주소에 접근 시 해당 메모리에 있는 값을 read/write 할 수 있는지 체크하기란 매우 까다롭습니다.
인터넷을 찾아보니 여러 블로그에
- IsBadCodePtr
- IsBadReadPtr
- IsBadStringPtr
- IsBadWritePtr
와 같은 함수를 쓰라고 나와있지만 이 함수들은 MSDN 설명을 보더라도 사용하면 안될 뿐더러
직접 사용해보니 잘못된 메모리 영역을 인자로 넘기면 Crash가 발생하더군요.
그러면 스킵하고 또 어떠한 방법이 있을까요?
가장 간단하게는 VirtualQuery 를 사용하는 방법입니다.
MEMORY_BASIC_INFORMATION 구조체 내부의 몇몇 값들을 확인해주면 됩니다.
State 값이 == MEM_COMMIT 인가?
Protect 값이 PAGE_READONLY, PAGE_READWIRTE, ... , PAGE_EXECUTE_WRITECOPY 인가?
이 때 Protect가 PAGE_GUARD나 PAGE_NOACCESS 같은 값을 가지면 안되겠죠.
결론은 VirtualQuery를 사용해 읽을 메모리인지 쓸 메모리인지 속성들을 확인해 유효성을 판단하는 것입니다.
잘못된 메모리를 넘겼을 경우엔 해당 속성들에 이상한 값이 채워져 있으므로 쉽게 판단할 수 있습니다.
하지만 VirtualQuery는 System call을 사용하는 함수입니다. 즉, 커널 내부로 들어가 해당 프로세스의 VAD 구조체를 따라가면서 해당 메모리에 맞는 속성을 찾아가는 함수입니다. 한 두 번이 아닌 수 만번 수십 만번 호출이 된다면 분명 미세하게나마 속도가 느려지는 것을 느낄 것 같습니다. 저 또한 그런 점을 약간 느껴 이를 개선하고자 했지만 딱히 방법이 안떠오르더군요.
Windows 8부터는 Bad Memory를 체크하는 함수들이 생겼습니다.
- BadMemoryCallbackRoutine
- GetMemoryErrorHandlingCapabilities
- RegisterBadMemoryNotification
- UnregisterBadMemoryNotification
아직 써보진 않았지만 콜백을 이용하는 것이므로 오버헤드도 발생안하고 깔끔하게 처리될 것 같습니다.
하지만 실제 범용성(XP, Vista, 7, 8 .. )을 가져가면서 프로그램 개발을 해야하므로 위 함수들은 쓸 수가 없습니다.
( 계속 OS 새로운 버전을 내놓고 있는 Windows가 야속하기만 합니다 ㅜㅜ )
또 Windows kernel에서 사용할 수 있는 함수가 있습니다.
- MmIsAddressValid
이 함수는 주어진 가상 주소에 대해 read나 write를 할 때 페이지 폴트가 발생할 것인지 아닌지를 판별하는 함수입니다.
하지만 MSDN에서는 이 함수 사용하는 것을 추천하진 않는다고 나와있네요.
또한 내부를 직접 뜯어보니 어떠한 연산을 하지만 User에서는 사용할 수 없는 값들이라서 그냥 이 함수도 무시..
이번엔 VirtualAlloc을 사용해볼까요?
VirtualAlloc을 사용해서 할당이 안되면 이미 할당되어 있는 메모리이고, 할당이되면 읽을 수 없는 메모리인걸로 판별하려했지만.. 이 역시 system call을 사용하고 VAD 구조체를 따라가고 등등.. 많은 작업을 합니다. 이도 fail..
아무리 생각해봐도 유저에서 오버헤드도 발생안하면서 메모리 유효성 체크할 수 있는 방법이 안떠오릅니다;; 쩝..
System call을 사용하고 싶지 않은데.. 흐엉..;
'My Study > Programming&Theory' 카테고리의 다른 글
Application Verifier 로 프로그램 체크 (2) | 2014.03.01 |
---|---|
Dll Injection 으로 브라우저 URL 가져오기 (4) | 2014.01.26 |
PE text 섹션 속성에 따른 VirtualQuery (2) | 2013.09.25 |
Windows 32bit/64bit 어플리케이션 간 통신 시 주의할 점 (0) | 2013.09.24 |
Windows DEP Exception 모니터링 (0) | 2013.09.19 |