안티 디버깅(Anti-debugging, 디버거 탐지) – FindWindow (프로세스 확인)

How to debugging detect?

프로그램 역분석, 즉 프로그램 디버깅 방법을 배웠다면, 해당 프로그램의 코드를 그대로 보는 것과 같아서, 숙달되면 프로그램의 모든 코드를 손쉽게 확인할 수 있다. 이를 통해 개발자가 원하지 않았던 방식으로 처리 흐름을 바꾸거나 데이터를 바꿔 치기 하는 등 악용할 수 있는 소지가 많다.

이를 방지하기 위해 개발된 기술이 바로 안티 디버깅으로, 말 그대로 디버깅 방지를 위한 기술들이라고 할 수 있다. 디버깅 자체를 막는 기술은 많이 개발되었으나, 이에 맞춰 안티-안티 디버깅 역시 함께 발전하면서 서로 뚫고 막고를 반복하고 있는 상황이다.

그리고 안티 디버깅 방법들은 대부분 이미 여러 포럼에서 공개해 놓은 상태이다. 아래는 시만텍에서 공개한 안티 디버깅 코드 참조용 내용이니 학습 전에 먼저 들러보기 바란다.

http://www.symantec.com/connect/articles/windows-anti-debug-reference

이외에도 많은 사이트에서 안티 디버깅과 관련된 참조 문서들을 많이 확인할 수 있는 만큼 안티 디버깅은 프로그램 보안 기술 중 기본 중 기본이라 할 수 있다(실제 대부분의 안티 디버깅 역시 방어 방법이 이미 나와 있다).

여기서는 안티 디버깅 중 유용한 몇 가지 방법에 대해 소개하여, 여러분이 안티 디버깅이라는 기술의 시각을 넓힐 수 있는 기본 지식을 다질 수 있도록 원리와 기법을 여러분들에게 소개하는 데 목적을 두고 진행하도록 하겠다.

디버거 탐지는 사용자가 프로그램을 분석하기 위해서 디버깅을 진행하는지에 대해 탐지하여 분석을 할 수 없도록 프로그램을 오동작하도록 하거나 중지, 함정에 빠뜨리는 방법이다.

이렇게 컴파일한 기계어인 프로그램의 보호가 필요한 이유는 3부에서 배웠듯이 역분석을 진행하면, 해당 프로그램의 동작 상황을 소설책을 읽어 내려가듯 분석하게 되면, 원하는 문장을 고쳐, 처리 흐름을 바꿔놓거나, 해당 프로그램의 목적과 반대로 동작하도록 수정할 수도 있다.+

따라서 디버깅을 진행하는 프로그램에 대한 제재를 진행해야 하는데, 이를 실행하기 위해 프로그램 자체에 디버깅을 방지하는 보호 코드를 삽입하여야 한다. 이러한 안티 디버깅 코드들은 유명 개발 커뮤니티에도 다수 공개되어 있으므로, 전체적인 내용을 진행하는 것에는 큰 의미 없으므로, 여기서 에서는 몇 가지 개념 이해를 돕기에 유용한 분석을 진행해보도록 하겠다.

FindWindow (프로세스 확인)

이쯤 되면 어느 정도 안티 디버깅의 감이 왔을 거라 생각된다. FindWindow는 말 그대로 윈도우의 이름을 통해 디버깅 프로그램이 동작 중인지를 확인하는 안티 디버깅 방법이다. 예전 안티 디버깅으로 많이 사용되었으며 지금도 여러 보안 솔류션들이 해킹 도구 탐지 용도로 해킹 프로그램에서 사용되는 문자열 검사와 함께 사용하는 방식이기도 하다. 바로 코드를 확인해 보자.

findwindow.cpp
#include
<stdio.h>#include
<windows.h>void main()

{

while(true)

{

Sleep(1000);

if(FindWindow(0, “OllyDbg” ))

{

printf(“Debugging Detected\n”);

exit(0xD000BE05);

}

else

printf(“Safe\n”);

}

return;

}

[예제] Ollydbg가 실행 중인지 확인하는 명령

만약 조건을 추가하고 싶다면 다음과 if에 그리고 조건인 || 를 통해 추가하면 된다. 다음은 Windbg를 추가로 검사하고자 할 때 이용할 수 있다.

if(FindWindow( 0, “OllyDbg” ) || FindWindow( 0, “Windbg” ) )

다른 코드들의 조건 분기에 대해서는 이전 내용들을 통해 쉽게 이해가 갈 것이라 판단된다. 여기서는 FindWindow에 대해 집중적으로 알아보자.


[그림] main 함수 내용 중 우리가 사용하려 하는 FindWindow

역분석시 해당 API에서 사용되는 파라미터들에 대해 확인하는 것은 좋은 습관이라 할 수 있다. 여기서도 FindWindow를 분석하기 전 Win32 Programmer’s Reference를 이용하여 확인하는 습관을 기르도록 하자.


[그림] FindWindow는 2개의 인자를 받도록 되어 있다

그럼 FindWindowA에 브레이크 포인트(F2키)를 설정하고 Step into(F7키)로 세부 내용을 확인해 보자.

// MOV EBP,ESP까지 스택 프롤로그 부분이다.
75D28FF3 U> 8BFF MOV EDI,EDI75D28FF5 55 PUSH EBP

75D28FF6 8BEC MOV EBP,ESP

// 입력한 인자는 2개를 이용하여 USER32.Dll은 FindeWindowA를 호출하게 된다.

75D28FF8 33C0 XOR EAX,EAX EAX를 초기화한다.

75D28FFA 50 PUSH EAX 0을 스택에 삽입한다.

75D28FFB FF75 0C PUSH DWORD PTR SS:[EBP+C] “OllyDbg”라는 값을 스택에 삽입한다.

75D28FFE FF75 08 PUSH DWORD PTR SS:[EBP+8] FindWindow는 클래스를 추가 지정이 가능한데 “0”은 NULL과 같은 의미로 지정하지 않은 경우이 들어간다.

75D29001 50 PUSH EAX 0을 스택에 삽입한다.

75D29002 50 PUSH EAX 0을 스택에 삽입한다.

75D29003 E8 47FFFFFF CALL USER32.75D28F4F FindWindowA를 호출한다. 처리 결과는 EAX에 저장된다. 찾는 결과가 없는 경우 EAX는 0으로 지정된다.

75D29008 5D POP EBP ; findwind.010B13DA

75D29009 C2 0800 RETN 8

010B13DA 3BF4 CMP ESI,ESP

010B13DC E8 50FDFFFF CALL findwind.010B1131

010B13E1 85C0 TEST EAX,EAX 결과값을 확인해 0인지 아닌지를 찾는다. 즉 EAX가 0이라면 찾고 있는 윈도우가 없고, 0이외의 값이라면 해당 윈도우가 있다는 의미이다.

010B13E3 74 2D JE SHORT findwind.010B1412 TEST 결과에 따라 분기한다.

…중략

[실습] FindWindowA 처리 내용

이 내용 이외에도 많은 안티 디버깅 방법들이 있다. 여기서 중요한 것은 이와 같은 안티 디버깅의 적용보다 “이를 분석가들에게 어떻게 하면 탐지되지 않고 검사할 수 있도록 할 것인가.” 이다. 어떻게 보면 그들은 더 많은 것을 경험한 베테랑들이다. 그리고 우리는 사냥꾼과 같이 함정을 설치해 놓고 기다리는 헌터와 같다. 즉 눈에 잘 보이는 덫에는 사냥감은 걸려들지 않을 것이다. 우리가 상대해야 할 사냥감들은 이미 산전수전 다 경험해본 노련한 숙련자들이기 때문에 이를 기본발판으로 사용하여 더욱 완벽하게 감추고자 노력하고, 새로운 함정을 개발하기 위한 노력을 아끼지 않아야 할 것이다.

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.