[리버싱] : MS에서 지원하는 안티 디버깅 (IsDebuggerPresent)
#REVERSINGMicrosoft에서 지원하는 안티 디버깅 IsDebuggerPresent의 작동 방식
x64dbg에 kernel32.dll
을 올리고 CTRL+G
를 눌러 IsDebuggerPresent
을 검색하여 해당 명령어로 이동하면
아래와 같은 코드가 등장한다. 고작 3줄에 불가하는 코드이다.
고작 3줄의 코드로 어떻게 디버깅을 감지하는 것인가
mov rax, qword ptr gs:[60]
gs
레지스터는 Windows의 TEB(Thread Environment Block)
를 가리킨다. TEB는 각 스레드마다 고유하게 존재하며, 여러 가지 스레드 관련 정보를 가지고 있다.
gs:[60]
는 gs 레지스터가 가리키는 주소에 0x60바이트(10진수로 96바이트)만큼 떨어진 곳을 나타낸다.
그렇다면 우선 TEB
의 구조를 알 필요가 있다. MSDN에서
TEB의 구조체를 보면 다음과 같다.
PVOID
자료형의 크기는 실행되는 시스템에 따라 다른데 일반적으로 32bit의 경우 4바이트 64bit의 경우 8바이트라고 한다.
개별 원소가 8바이트인 배열의 크기가 12이므로 12 * 8 = 96 위에 나온 0x60바이트와 정확히 일치한다.
이로 인해 gs:[60]은 PEB(ProcessEnvironmentBlock)
을 가리킨다는 것을 확인했다.
이로써 첫 번째 명령어의 의도를 파악했다.
첫 번째 명령어는 PEB의 주소를 rax
레지스터에 로드한다.
movzx eax, byte ptr ds:[rax+2]
현재 rax
에는 PEB
의 주소를 가지고 있다.
rax+2
는 PEB의 특정 오프셋을 가리키는데 MSDN에서 PEB 구조체를 보면 다음과 같다.
위로 알 수 있는 것은 rax+2
의 오프셋은 BeingDebugged
이다. 여기에 1이 들어가 있으면 디버깅 중인거고 0이 들어가 있으면 디버깅 중이 아닌 것이다.
ret
위의 BeingDebugged
의 값이 eax
레지스터에 들어있으니 이대로 리턴하여 함수를 종료한다.
MS사의 IsDebuggerPresent 함수를 알아봤다. 간단하고 유명한 함수라서 우회하는 방법도 흔히 알려졌다.
그래도 정 쓰고 싶다면 kernel32.dll에서 로드해서 쓰는 것보다 아래와 같이 어셈블리로 직접 코딩해서 쓰는 편이 낫다.