본문으로 바로가기

SetUnhandledExceptionFilter를 이용한 안티 디버깅
예외 기반 안티 디버깅은 예외를 발생 시키고, 예외 처리기(SEH, VEH, ..)에 중요한 루틴을 숨기거나 안티 디버깅 유무를 판단하여 코드의 흐름(EIP)을 변경시키는 방법
일반적인 실행 인 경우 예외가 발생되면 예외 처리기에 의해 실행 흐름이 정상적으로 진행되지만, 디버거에 의한 실행일 경우 예외를 디버거가 받게 되고, INT3 예외인 경우 디버거의 처리에 의해 예외 처리기가 실행되지 않은 상태에서 코드가 진행됨 
SEH를 이용할 경우 예외 기반 안티 디버깅을 수행할 수 있으며, 직접 핸들러를 등록하거나 __try, __except를 이용하여 구현
SetUnhandledExceptionFilter 함수를 이용할 경우 Top Level Filter를 변경할 수 있으며, 이를 이용하여 안티 디버깅 수행


예외가 발생됬을 때 예외가 처리되지 않은 경우 또는 예외 처리기가 없는 경우
1) 예외 발생!
2) 예외가 처리되지 않음
3) kernel32.dll!UnhandledExceptionFilter 함수 호출
4) UnhandledExceptionFilter 내부적으로 NtQueryInformationProcess의 DebugPort를 호출하여 디버깅 중인 경우 예외(제어권)를 디버거에 넘김
5) 디버깅 중이지 않은 경우 Top Level Filter 호출(기본 Top Level Filter는 faultrep.dll!ReportFault가 호출되며 다음 그림과 같은 창이 뜸)


 

소스 코드


안티 디버깅 우회 방법
1. Top Level Filter 주소를 알고 있는 경우 : Top Level Filter로 등록된 예외처리기에 Break Point -> UnhandledExceptionFilter 내부의 ZwQueryInformationProcess의 DebugPort 요청 시 Debugging 상황이 아닌 값으로 수정(3번째 인자 반환되는 값 0으로 변경) -> 예외처리기까지 진행
2. 
Top Level Filter 주소를 모를 경우 : UnhandledExceptionFilter 내부의 ZwQueryInformationProcess의 DebugPort 요청 시 Debugging 상황이 아닌 값으로 수정(3번째 인자 반환되는 값 0으로 변경) -> 루틴 진행하다 보면 다음과 같이 예외 처리기를 호출하는 부분이 보임(DLL의 버전에 따라 주소 값은 다를 수 있음)

3. 디버거의 안티 디버깅 플러그인 이용(OllyDbg의 Olly Advanced 플러그인에서 UnhandledExceptionFilter와 ZwQueryInformationProcess 체크)