본문 바로가기

My Study/Programming&Theory

Application Verifier 로 프로그램 체크

어떠한 모듈을 개발하다보면 올바르게 동기화 관련 함수를 사용했는지, 유효하지 않은 핸들에 접근 한다던지, 메모리 커럽션이 발생할 수 있는 상황이 있는지 등등을 체크가 필요할 때가 있다. 작은 프로젝트의 경우 어느정도 눈으로 보이지만 수 만줄 수 십만줄 되는 모듈에서는 이를 개발자가 직접 찾는다는건 해킹대회 게싱문제 푸는 것 보다 더 빡치는 상황이 벌어질 수 있다. 애당초에 개발을 신경써서 제대로 하면 되지 않느냐? 라고 질문하시는 분이 계실탠데.. 제품 개발하는 정도로 제대로 프로그래밍을 해보신 분이라면 그건 말도 안되는 일이라는 것을 알 수 있을 것이다. 개발 잘한다는 MS 직원들이 왜 Application Verifier 툴을 만들었을까..? 답이 나온다.


아무튼 이 툴은 만들어진 모듈 안에서 발생될 수 있는 위협들을 자동적으로 잡아준다.



생긴건 이렇게 생겼다. Applications 부분에 검사할 프로세스를 추가하고 Tests 부분에서 원하는 테스트 목록을 선택 후 Save를 눌러주면 모든 준비는 끝난다.


Tests 목록은 상당히 많다.

Basic

 - Exceptions

 - Handles

 - Heaps

 - Leak

 - Locks

 - Memory

 - SRWLock

 - Threadpool

 - TLS

Compatibility

 - HighVersionLie

Cuzz

Low Resource Simulation

LuaPriv

Miscellaneous

 - DangerousAPIs

 - DirtyStacks

 - TimeRollOver

Networking

NTLM

 - NTLMCaller

 - NTLMDowngrade

Printing

 - PrintAPI

 - PrintDriver

Webservices


각각 항목들에 대해선 이름만 가지고 유추하거나 관심있으면 찾아보길..

아무튼 Basic에만 체크해보고 notepad.exe를 돌려보겠다.



로그창으로 와보니 notepad.exe에 대한 log가 하나 생성되어 있다. 역시 notepad 답게 어떠한 에러도 발생하지 않는다.

고로 샘플 코드를 만들어서 테스트 해보자.



초간단 샘플코드이다.

malloc 함수를 통해 힙에 공간을 할당후 해제를 하는데 한번 해제된 메모리를 또 해제하고 있는 코드이다.

이 코드를 그냥 실행하면 어떻게 될까?



아무런 에러도 나지않고 잘 종료된다.

이제 Application Verifier에서 Basic 부분을 활성화 시켜주고 실행해보자.


뻑이나면서



로그가 남았고 Error가 1이라고 되어 있다. View를 눌러보자.



Application Verifier에서 사용하는 로그 형태는 XML 포맷을 사용한다.

콜스택을 확인해보니 어디서 문제가 생겼는지 바로 알 수 있다.


또한 WinDbg와 연결되어 있으면 프로세스에 붙어있는 Application Verifier 모듈이 break point를 걸어서 제어를 WinDbg로 넘겨주도록 되어 있다. 그러면 WinDbg에서 바로 콜스택을 보고 해당 프레임으로 이동하면 소스코드가 솩! 하고 나오는 멋진 장면을 볼 수 있을 것이다. 당근 커널 디버깅 상태에서도 가능 :p


이러한 Application Verifier를 구현하면 당연히 타겟 프로세스에 dll injection이 수행되어져야함을 알 수 있다.



3개의 모듈이 추가로 들어가 있는 것을 확인할 수 있다. 그리고 API후킹도 할 것이다. 유저에서는 프로세스의 동작을 가로채서 확인하려면 후킹말고는 답이 없으니깐..



왼쪽이 원본 Import Table이고 오른쪽이 Application Verifier에 의해 후킹된 Import Table이다. 위 그림에선 15개정도 후킹되어 있는걸로 보인다. 다양한 기능 활성화 시키고 그러면 더 많은 함수들을 후킹할 것이다. 내부적으로 구현은? 분석안할꺼임..


Application Verifier 프로그램이 모듈 상에 잠재되어있는 모든 버그를 잡아내진 않지만 삼겹살의 초벌구이라고 생각하고 어느정도 개발된 모듈이 있다면 한번쯤은 돌려보는 것도 나쁘지 않은 것 같다.


현재 필자가 개발하고 있는 모듈이 하나 있어서 돌려보니 Warning이 하나 나왔는데 계속적으로 돌아가고 있는 스레드를 외부에서 종료시키기 위해 TerminateThread 를 사용한 부분이 있는데 위험한 API라면서 잡는다. =_=;; 안고쳤다.

왜냐하면 해당 스레드 안에서는 스레드 스택을 제외한 그 어떠한 리소스도 사용하고 있지 않았기 때문... 


아무튼 괜찮은 툴 같아서 포스팅.. 귀찮다. 아 네이티브 코드로 돌아가는 프로그램만 지정해서 해봤는데 바이트코드 기반 C# 같은 언어로 개발된 프로그램도 될련지 모르겠다.. 해보신 분들 있다면 알려주세요~