' 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

CheckRemoteDebuggerPresent() 함수를 호출하여 &DebugCheck를 가리키는
[ebp-08] 값을 0인 지 검사 후 분기한다.

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 을 나타내는 값 |

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

반환 값은 디버깅 중이라면 0 이 아닌 다른값이 디버깅 중이 아니라면 0 을 반환하므로
해당 buffer 값을 0으로 패치하여 CheckRemoteDebuggerPresent() 함수를 우회한다.
'Reversing > Anti-Debugging' 카테고리의 다른 글
| [Dynamic 안티디버깅] Assembly instructions (0) | 2024.02.25 |
|---|---|
| [static 안티디버깅] BlockInput() (0) | 2023.06.10 |
| [static 안티디버깅] NtSetInformationThread() (0) | 2023.06.09 |
| [static 안티디버깅] NtQueryInformationProcess() (0) | 2023.06.07 |
| [static 안티디버깅] IsDebuggerPresent (0) | 2023.06.05 |