프로세스 디버깅을 하려면 프로세스에 연결해야한다. 고로 실행시키거나 동작중인 프로세스에 attach 해야한다. 둘의 차이는 실행시키는 경우 해당 프로세스의 실행전에 제어가 가능한 장점이 있다. 이는 악성 코드나 다른 형태의 악의적 코드 분석시 편리하다. attach의 경우 프로세스의 실행시의 코드를 건너뛰어 원하는 영역만 분석이 가능하다는 장점이 있다.
1. 프로세스 실행
: 디버거가 실행바이너리를 직접 실행하는 것 이다.
윈도우에서는 CreateProcessA() 함수가 사용된다.
-----------------------------------------------------------------------------
BOOL WINAPI CreateProcess(
LPCTSTR lpApplicationName, // 실행 바이너리 경로
LPTSTR lpCommandLine, // 커맨드라인 인자
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags, // 특별한 값을 구분으로 디버깅 목적 실행 명시
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory, // 구조체에 대한 포인터
LPSTARTUPINFO lpStartupInfo, // 구조체에 대한 포인터
LPPROCESS_INFORMATION lpProcessInformation
);
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
-----------------------------------------------------------------------------
2. 프로세스에 attach
a. 핸들을 얻기 위해 사용되는 함수 OpenProcess()
-----------------------------------------------------------------------------
HANDLE WINAPI OpenProcess(
DWORD dwDesiredAccess, // 어떤 종류의 접근권한을 가진 프로세스핸들을 원하는지입력 (PROCESS_ALL_ACCESS 값으로 설정해야한다.)
BOOL bInheritHandle, // 항상 false
DWORD dwProcessId // 핸들을 얻고자 하는 프로세스의 PID 값
);
-----------------------------------------------------------------------------
b. 프로세스에 붙일 때 DebugActiveProcess() 함수
: 시스템은 일단 디버거가 프로세스에 대한 올바른 권한을 갖고 있다고 판단하면 디버거가 해당 프로세스의 디버그 이벤트를 처리할 준비가 됐다고 가정한다. 그리고 해당 프로세스에 대한 제어권을 디버거에게 넘겨준다.
-----------------------------------------------------------------------------
BOOL WINAPI DebugActiveProcess(
DWORD dwProcessId // attach할 PID
);
c. 디버그 이벤트 처리 WaitForDebugEvent()
-----------------------------------------------------------------------------
BOOL WINAPI WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent, // 디버그 이벤트를 설명해주는 DEBUG_EVENT 구조체 포인터
DWORD dwMilliseconds // INFINITE로 설정하면 디버그 이벤트 발생까지 리턴하지않고 대기
);
-----------------------------------------------------------------------------
※ 발생하는 각 이벤트에 대해서는 그것을 처리하기 위한 이벤트 핸들러가 있으며, 이벤트 핸들러는
이벤트에 맞는 어떤 작업을 수행한 다음에 프로세스가 실행을 계속하게 해준다. 따라서 일단
이벤트 핸들러의 작업이 완료되면 프로세스가 실행을 계속하게 만들어 줘야한다. 아래 함수 사용
d. 프로세스의 계속 실행 ContinueDebugEvent()
-----------------------------------------------------------------------------
BOOL WINAPI ContinueDebugEvent(
DWORD dwProcessId, // 디버그 이벤트 발생시 설정되는 DEBUG_EVENT 구조체 필드
DWORD dwThreadId, // 디버그 이벤트 발생시 설정되는 DEBUG_EVENT 구조체 필드
DWORD dwContinueStatus // DBG_CONTINUE 계속실행, DBG_EXCEPTION_NOT_HANDLED 예외처리
);
-----------------------------------------------------------------------------
e. 프로세스 detach
-----------------------------------------------------------------------------
DebugActiveProcessStop() // PID를 전달하면 프로세스에서 떼어 낼 수 있다.
-----------------------------------------------------------------------------