안티 디버깅(Anti-Debugging)이란?
디버깅을 방지하고 분석을 하지 못하도록 하는 기술이다.
디버깅을 당한다면 해당 디버거 프로그램을 종료시키거나 에러를 발생시키는 방법 등 다양한 방법을 사용하여 분석을 방해한다.
안티 디버깅 기술에는 수많은 방법들이 존재하며 계속 발전하고 있으며 이에 따라 이를 우회하는 기술도 계속적으로 발전하고 있다.
안티 디버깅을 배워야 하는 이유
- 디버깅을 방지하기 위해
- 각종 안티 디버깅 기법들의 동작 원리를 파악한 후 회피하기 위해
- 안티 디버깅 기법을 공부하는 과정에서 저절로 고급 리버싱을 배울 수 있기 때문에
안티 디버깅 종류
static vs dynamic
static
디버깅 시작할 때 한 번만 해체를 해주면 해결되는 기법이다.
주로 디버거를 탐지하여 프로그램이 정상적으로 실행되지 못하도록 한다.
따라서 Static 기법이 적용된 파일들은 디버거에 올렸을 때 제대로 실행(RUN)조차 되지 않는다.
그러다 적용된 Static 기법을 해체하면, 그제서야 디버거에서도 제대로 실행될 것이다.
dynamic
디버깅을 진행하면서 (해당 Anti 기법을) 만날 때마다 해결하는 기법이다.
디버거 트레이싱을 방해하여 원본 프로그램의 코드와 데이터를 확인할 수 없게 만드는 것이다.
※ 디버거 트레이싱 : 디버기(디버깅 당하는 쪽) 의 내부 Instruction을 하나씩 실행하면서 레지스터, 메모리(스택) 등을 실시간으로 확인하는 것이다. 한 줄 한 줄 디버깅한다와 같은 말이다.
Static 안티 디버깅
디버깅 프로세스에서 자신이 디버깅 당하는지 여부를 파악하는 기법이다.
만약 디버깅 중이라고 판단되면 일반 실행과는 다른 코드(주로 종료 코드)를 실행하는 것이 핵심이다.
구현 방법으로는 디버거를 탐지하는 방법, 디버깅 환경을 탐지하는 방법, 디버거를 강제 분리시키는 방법 등이 있다.
회피 방법은 탐지 코드에서 얻어 오는 정보를 파악하여 아예 그 정보 자체를 변경해버리는 것이다.
디버깅 기법
PEB
현재 프로세스의 디버깅 여부를 판단하기 위해 PEB(Process Environment Block)구조체 정보를 이용할 수 있다.
NtQueryInformationProcess()
ntdll!NtQueryInformationProcess() API를 이용하면 프로세스의 디버깅 관련 정보를 비롯하여 매우 다양한 정보를 얻을 수 있다.
NtQuerySystemInformation()
디버깅 환경을 체크하는 안티 디버깅 기법이다.
이 기법은 현재 OS가 Debug Mode로 부팅되었는지를 판단하는 안티 디버깅 기법이다.
※ 자신의 프로세스가 디버깅 당하는지를 체크하는 것이 직접적인 디버거 탐지 방법이라면, 디버깅 환경을 체크해서 디버거의 낌새가 조금이라도 보이면 즉시 실행을 멈추는 것은 간접적인 디버거 탐지 방법이라고 할 수 있다.
NTQueryObject()
시스템에서 어떤 디버거가 다른 프로세스를 디버깅 중이라면 그때 DebugObject타입의 커널 객체가 생성되는데, 그 DebugObject의 존재를 확인하는 것이다.
ntdll!NtQueryObject() API는 시스템의 다양한 종류의 커널 객체 정보를 구해오는 함수이다.
ZwSetInformationThread()
디버깅 당하는 쪽(디버기)에서 강제로 디버거를 떼어내는(Deacth) 기법에 대한 설명이다.
ZwSetInformationThread() API를 사용하면 자신을 디버깅하고 있는 디버거를 떼어낼 수 있다.
ZwSetInformationThread() 함수는 이름 그대로 스레드에게 정보를 세팅하는 System Native API이다.
TLS 콜백 함수
TLS 콜백 함수는 유용하게 사용되는 안티 디버깅 기법이다.
TLS 콜백은 그 자체로 안티 디버깅 기법이라고 볼 수 없지만 프로그램의 Entry Point 코드보다 먼저 실행되는 특징 때문에 안티 디버깅에 많이 활용된다.
TLS 콜백 함수 내에서 IsDebuggerPresent() 등의 함수로 간단히 디버깅 여부를 판별하여 프로그램을 계속 실행할지 말지를 결정할 수 있다.
Dynamic 안티 디버깅
내부 코드와 데이터를 리버싱으로부터 감추고 보호하는 것이다. 보통 PE 프로텍터들에서 많이 사용되며 원본 프로그램의 핵심 알고리즘을 보호하기 위하여 사용된다.
디버거로 해당 프로그램이 실행될 수는 있을지언정 원본 프로그램의 핵심 코드(OEP)로 트레이싱 하여 찾아갈 수 없도록 방해한다.
디버깅 기법
예외(Exception)
예외(Exception)를 이용하는 방법은 안티 디버깅의 단골 메뉴이다.
정상적으로 실행된 프로세스에서 예외가 발생하면 SEH(Structured Exception Handling) 메커니즘에 의해 OS에서 예외를 받아서 프로세스에 등록된 SEH를 호출해준다.
그러나 디버기에서 예외가 발생하면 디버거에서 예외처리를 담당한다.
바로 이러한 특징을 이용하여 정상 실행되는 경우와 디버깅 당하는 경우를 판별해서 서로 다른 동작을 수행할 수 있다.
Timing Check
디버거를 이용해 코드를 한 줄씩 트레이싱하면서 진행하면 그냥 정상적으로 실행될 때보다 엄청나게 오랜시간이 소요된다.
Timing Check 기법은 그러한 실행 시간의 차이를 측정하여 디버깅 여부를 판별하는 기법이다.
0xCC Detection
일반적으로 프로그램을 디버깅할 때 Software BP(BreakPoing)를 많이 설치한다.
BP의 x86 Instruction은 '0xCC'이다.
이 값을 정확히 발견할 수만 있다면 디버깅 여부를 판별할 수 있다.
'Study > Reversing' 카테고리의 다른 글
[리버싱] Stolen Byte (0) | 2017.09.19 |
---|---|
[리버싱] 언패킹 (0) | 2017.09.19 |
[리버싱] 패킹 (0) | 2017.09.18 |
[리버싱] IAT&EAT (0) | 2017.09.17 |
[리버싱] 정적&동적 라이브러리 (0) | 2017.09.16 |
댓글