본문 바로가기

Reversing/Anti-Debugging

[static 안티디버깅] CheckRemoteDebuggerPresent()

 

 

'  CheckRemoteDebuggerPresent()  '

 

 

 

설명

지정된 프로세스가 디버그되고 있는지 여부를 확인합니다.

 

 

반환값

함수가 성공하면 반환 값이 0이 아닙니다.

함수가 실패하면 반환 값은 0입니다.

 

 

함수 원형

BOOL CheckRemoteDebuggerPresent(
  [in]      HANDLE hProcess,
  [in, out] PBOOL  pbDebuggerPresent
);

 

 

hProcess : 디버깅 중 인지 체크할 프로세스 핸들

 pbDebuggerPresent : 함수 리턴 값이 저장될 변수 bool 형

 

 

 

현재 자신 프로세스를 디버깅 여부를 체크하기 위해선 다음과 같은 코드를 작성해 볼 수 있다.

 

CODE

#include <stdio.h>
#include <Windows.h>


void anti() {
	BOOL DebugCheck;
	CheckRemoteDebuggerPresent(GetCurrentProcess(), &DebugCheck);
	if (DebugCheck)
		MessageBoxA(NULL, "Detect", "", MB_OK);
}


int main()
{
	anti();
	return 0;
}

 

CheckRemoteDebuggerPresent 함수의 1번쨰 매개변수인 hProcess를 자기 자신의 프로세스 핸들을 가져오기 위해선

GetCurrentProcess() 함수를 사용하여 자기 자신 핸들을 가져 올 수 있다.

 

GetCurrentProcess()는 현재 프로세스에 대한 핸들을 반환 해주는 함수이다.

 

 

원격 프로세스에 디버깅을 여부를 체크 하고자 할 떄는 다음과 같은 코드를 작성한다.

 

 

CODE

#include <stdio.h>
#include <Windows.h>


void anti() {
	BOOL DebugCheck;
	HANDLE hProcess;
	HWND h_wnd;
	DWORD pid;

	h_wnd = FindWindow(L"NotePad", L"제목 없음 - Windows 메모장");
	GetWindowThreadProcessId(h_wnd, &pid);
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

	CheckRemoteDebuggerPresent(hProcess, &DebugCheck);
	if (DebugCheck)
		MessageBoxA(NULL, "Detect", "", MB_OK);
}


int main()
{
	anti();
	return 0;
}

 

FindWinow 함수로 클래스 이름과 창 이름을 검색하여 해당 프로세스의 핸들을 가져온다.

GetWidowProcessId 함수로 FindWinow()로 반환 받은 핸들의 PID 를 가져온다.

원격 프로세스에 액세스 하기 위하여 OpenProcess() 함수를 이용하여 해당 프로세스의 PROCESS_ALL_ACCESS 

권한을 가져오고 CheckRemoteDebuggerPresent() 함수를 호출하여 디버깅 여부를 체크한다.

 

 

Disassemble

main()

CheckRemoteDebuggerPresent() 함수를 호출하여 &DebugCheck를 가리키는

[ebp-08] 값을 0인 지 검사 후 분기한다.

 

CheckRemoteDebuggerPresent()

CheckRemoteDebuggerPresent()  함수 내부로 진입 해보면

내부에서 NtQueryInformationProcess 함수를 사용한다.

 

NtQueryInformationProcess 함수의 원형은 다음과 같다.

 

__kernel_entry NTSTATUS NtQueryInformationProcess(
  [in]            HANDLE           ProcessHandle,
  [in]            PROCESSINFOCLASS ProcessInformationClass,
  [out]           PVOID            ProcessInformation,
  [in]            ULONG            ProcessInformationLength,
  [out, optional] PULONG           ReturnLength
);

 

NtQueryInformationProcess 함수의 2번째 매개변수인 ProcessInformationClass의 반환하는

타입 유형은 보면 다음과 같다.

 

의미
ProcessBasicInformation (0) PEB 구조에 대한 포인터와 시스템이 지정된 프로세스를 식별하는 데 사용하는 고유 값을 검색합니다.
ProcessDebugPort (7) 디버거의 포트 번호 인 값입니다. 0이 아닌 값은 프로세스가 링 3 디버거의 제어하에 실행되고 있음을 나타냅니다.
ProcessWow64Information (26) 프로세스가 WOW64 환경에서 실행되고 있는지 확인
ProcessImageFileName (27) 프로세스의 이름을 반환 (유니코드 형식)
ProcessBreakOnTermination (29) 프로세스가 중요한 것으로 간주되는지 여부를 나타내는 값.
ProcessSubsystemInformation (75) 프로세스의 subsystem type 을 나타내는 값

 

 

ProcessInformationClass (7)

 

CheckRemoteDebuggerPresent() 함수는 ProcessDebugPort (7) 로 NtQueryInformationProcess() 함수에 전달한다.

 

 

 

 

 

실습

CheckRemoteDebuggerPresent() 리턴

 

반환 값은 디버깅 중이라면 0 이 아닌 다른값이 디버깅 중이 아니라면 0 을 반환하므로

해당 buffer 값을 0으로 패치하여 CheckRemoteDebuggerPresent() 함수를 우회한다.