안티 리버싱

리버싱 2022. 10. 19. 09:39

앞서 안티 디버깅에 대한 간단한 예제를 살펴보았다.

2020/08/04 - [SECURITY/REVERSING] - 안티 리버싱 :: 03 - 안티 디버깅 예제

 

 

이제는 안티 디버깅에 대한 이론적인 것들을 간단하게 개념적으로 정리해볼 것이다.

 

대다수 안티 디버깅 기법은 FS:[0x30] 에 접근해 윈도우 API 를 이용하거나, 

디버깅하면 그냥 실행했을 때보다 실행 시간이 길어짐을 이용하여 시간을 검사하는 기법을 자주 사용한다.

 

 

 

 

------------------- 목차 -------------------

 

1. Windows API 

1.1 IsDebuggerPresent
1.2 CheckRemoteDebuggerPresent

1.3 NTQueryInformationProcess

1.4 OutputDebugString

1.5 FindWindow

 

2. structure (구조체) 를 수동으로 검사

2.1 BeingDebugged 플래그

 

3. 디버거로 실행할 때 프로세스에 미치는 변화를 감지

3.1 INT

3.2 Checksums

3.3 시간 체크

 

4. TLS Callback

 

-------------------------------------------- 

 

 

 

 

1. Windows API 

 

 

1.1 IsDebuggerPresent

https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent

 

앞선 예제에서 살펴본, 가장 간단한 디버거 탐지 윈도우 API 함수이다.

이 함수는 PEB 구조에서 IsDebugged 필드를 찾아 디버그가 동작 중인지 판단하여 동작 중이 아니라면 0을, 동작 중이라면 0이 아닌 값을 반환한다.

 

** PEB 는 FS 레지스터를 통해 접근 가능. TEB 의 0x30 이 PEB 를 가리킴

  --> FS:[0x30] 이라 되어있으면 PEB 를 가리키는 것

** TEB, PEB 란?

더보기
접기

* TEB (Therad Environment Block)

: win32 의 자료 구조로서, 현재 실행 중인 스레드에 대한 정보를 저장하고 있다.

다양한 윈도우 DLL 에 대한 컨텍스트 정보를 담고 있다.

이 요소들이 유저 모드에서 구동되므로 유저 모드에서 쓰기가 가능한 구조체가 필요했다.

그래서 이 구조체는 커널 모드에서만 쓰기가 가능한 시스템 주소 공간이 아닌 프로세스 주소 공간에 위치한다. 

 

* PEB (Process Environment Block)

 

: 윈도우 NT 에서의 데이터 구조체.

운영체제 내부에서 사용하는 구조체로, 이미지 로더, 힘 관리자, 윈도우 시스템 DLL 등 유저 모드 상에서 접근할 필요가 있는 정보를 가지고 있다.

 

(NT ZW ?? -> https://blog.naver.com/stgavriel/80044878343)

 

 

+ FS 레지스터

: 커널 모드에서는 KPCR(Kernel's Processor Control Region) 구조체를,

유저 모드에서는 TEB 구조체를 가리키고 있다.

 

따라서

FS:[0] 은 TEB 의 시작 위치, 

FS:[0x30] 은 PEB 의 시작 위치를 의미

 

실제로 함수 실행에 들어가보면 FS:[30] 으로 PEB 구조체에서 +2 를 하여 BeingDebugged 를 확인하는 것을 볼 수 있다.

 

 

 

1.2 CheckRemoteDebuggerPresent

https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-checkremotedebuggerpresent

 

PEB 구조의 IsDebugged 필드를 확인하며 IsDebuggerPresent 와 거의 동일한 기능을 한다. 

다만 자신이나 로컬 컴퓨터의 프로세스에 대해서만 검사할 수 있다.

 

파라미터로 프로세스 헨들을 받아 프로세스가 디버거 환경에서 실행 중인지를 판단한다.

 

Use the IsDebuggerPresent function to detect whether the calling process is running under the debugger.

 

 

1.3 NTQueryInformationProcess

https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess

 

첫 번쨰 파라미터로 프로세스 헨들을, 두 번째 파라미터로 얻고자 하는 프로세스 정보의 타입을 요구한다.

두 번째 파라미터인 ProcessInformationClass  ProcessDebugPort(0x7) 을 준다면 해당 프로세스가 디버깅 중인지에 대한 여부를 반환한다.

 

디버깅 중이라면 0, 아니면 디버거 포트 번호를 반환한다.

 

(NT ZW ?? -> https://blog.naver.com/stgavriel/80044878343)

 

 

1.4 OutputDebugString

https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringw

 

디버거에 출력할 문자열을 전달하는 데 사용되는 함수이므로 디버거의 존재를 탐지하는 데 사용할 수 있다.

 

이 함수를 실행했는데 오류가 발생하지 않는다면 디버거로 실행중이라는 의미이다.

 

 

1.5 FindWindow

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowa

 

특정 프로그램(디버그)가 실행되고 있는지 검색할 수 있다.

첫번째 파라미터로 검색할 프로그램(디버그) 이름을 주고, 만일 해당 프로그램이 실행 중이라면 그 헨들을, 실행하고 있지 않다면 NULL 값을 반환한다.

 

ex. FindWindow("OllyDbg", NULL)

 

 

 

2. Structure (구조체) 를 수동으로 검사

 

PEB 구조체에서 디버거가 존재하는지에 대한 정보를 제공한다.

 

운영 체제는 실행 중인 각 프로세스에 대해 윈도우 PEB 구조체를 관리한다.

환경 변수 값, 로드된 모듈 목록, 메모리 주소, 디버거 상태 등의 프로세스 환경 데이터를 포함한다.

 

프로세스 실행 중에 FS:[0x30] 으로 PEB 를 접근할 수 있다.

https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb

 

2.1 BeingDebugged 플래그

 

이 플래그는 PEB 구조체의 오프셋 2에 있다. (0x2) (향후 윈도우 버전에 따라 변경 가능)

이 플래그 값이 0 이면 디버거가 동작하고 있지 않다는 것이고, 1 이면 디버거가 동작하고 있다는 뜻이다.

 

 

그리고 다른 플래그들이 존재하지만, 향후 윈도우 버전에 의해 구조가 달라질 수 있으므로 해당 문서를 참조하길 바란다.

 

 

3. 디버거로 실행할 때 프로세스에 미치는 변화를 감지

 

3.1 INT 3

 

INT 3 는 소프트웨어 BP 를 설정하는 기본 메커니즘이다.

 

INT 3 의 OPCODE 는 0xCC 로, 이 OPCODE 를 검색하여 본래의 코드가 INT 3 로 변경되었는지 프로세스를 스캔한다.

0xCC 가 발견되면 디버거가 존재한다는 뜻이다.

 

혹은 코드에 INT 3 구문이 있을 때, 디버거로 실행하면 오류가 나지 않지만 그냥 실행하면 해당 구문은 오류를 뱉는다. 오류를 뱉는지에 대한 여부로도 디버그의 존재 여부를 파악할 수 있다.

 

 

이를 우회하기 위해서는 소프트웨어 BP 대신 하드웨어 BP 를 설정하면 된다.

 

 

 

 

3.2 Checksums

 

특정 코드 영역의 CheckSum 값을 구하고, 원본 CheckSum 과 비교하여 BP 설정 혹은 각종 코드 패치 여부를 검사할 수 있다. 

 

그 중 Hash Checking 기법은 함수 코드들의 Hash 값을 미리 구해 둔 다음, 그 값과 실행 중간에 호가인한 Hash 값이 같은지 확인하여 패치 여부를 탐지하는 것이다.

 

 

 

3.3 시간 체크

 

디버거로 프로세스를 실행하면 그냥 프로세스를 실행했을 때보다 속도가 현저히 느려진다.

이런 시간 차이를 탐지하는 몇 가지 기술이 존재한다.

 

 

3.3.1 타임 스탬프

 

특정 동작 수행 전후에 타임 스탬프를 기록하고 비교한다.

 

혹은 예외 발생 전후의 타임 스탬프를 가져와서 비교한다. 디버거가 예외를 처리하는 경우 상당한 지연이 발생하기 때문에 구분할 수 있다. (예외를 무시하거나 지나치게 하는 기능을 제공하는 디버거들도 있지만, 그럼에도 차이가 발생한다.)

 

 

3.3.2 rdtsc (OPCODE 0x0F31)

 

가장 일반적인 시간 검사 방법이다.

 

가장 최근에 시스템이 리부팅한 이후 흐른 시간 값을 저장한 64비트를 반환한다.

이 명령어를 실행한 후 두 값의 차가 특정한 정도를 넘으면 디버거가 실행 중임으로 판단할 수 있다.

 

 

3.3.3 QueryPerformanceCounter & GetTickCount

https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter

https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount

 

 

rdtsc 와 같이 시간차를 분석할 수 있는 윈도우 API 함수이다.

 

 

4. TLS Callback

 

일반적으로 대다수 디버거는 PE 헤더에서 정의한 프로그램 지입점에서 시작한다.

그런데 TLS(Thread Local Storage) Callback 은 진입점 전에 실행되는 코드로, 디버거 몰래 실행할 수 있다.

 

즉, TLS Callback 에 악성 코드 기능을 삽입한다면 디버거로는 감지하지 못한다.

 

일반적인 프로그램은 .tls 섹션을 사용하지 않기 때문에 .tls 섹션이 있는 경우 가장 먼저 안티 디버깅을 의심해야 한다.

 

출처: https://kali-km.tistory.com/entry/Anti-Debugging?category=490391

관련 내용을 더 알고 싶다면 - https://flack3r.tistory.com/entry/TLS-%EC%BD%9C%EB%B0%B1-%EC%95%88%ED%8B%B0%EB%94%94%EB%B2%84%EA%B9%85

 

 

참고 사이트들

https://blog.naver.com/sol9501/70128619541

https://kali-km.tistory.com/entry/Anti-Debugging?category=490391

'리버싱' 카테고리의 다른 글

Lab05-01.dll  (0) 2022.05.02
IAT & EAT 정리  (0) 2022.04.27
RVA to RWA 쉽게 계산하기 [펌]  (0) 2022.04.27
EAT IAT 계산  (0) 2022.04.25
C#은 SecureSting 클래스  (0) 2021.07.09
블로그 이미지

wtdsoul

,