파이썬 해킹 프로그래밍 (Python Hacking Programming)
저자 : 저스틴 지이츠
출판사 : 에이콘
3장. 윈도우 디버거 개발
[3.1] 윈도우 디버거 개발
[3.2] CPU 레지스터 상태 얻기
소스코드 입니다.
역시 소스코드에 오타가 좀 있었군요 . . .
[3.1 윈도우 디버거 개발]
프로세스를 디버깅하려면 어떤 식으로든 먼저 해당 프로세스를 디버거와 연결해야 한다.
그래서 디버깅할 프로세스를 실행시키거나, 이미 실행돼 있는 프로세스에 attach를 해야 한다.
프로세스를 실행시키는 경우는 디버거가 실행 바이너리를 직접 실행하는 것인데,
이 경우 해당 프로세스의 코드가 실행되기 전에 제어를 할 수 있다는 장점이 있다.
윈도우에서는 프로세스를 실행시킬 때 CreateProcess() 함수를 호출한다.
BOOL CreateProcess( LPCWSTR pszImageName, // 실행시킬 실행 바이너리 경로 LPCWSTR pszCmdLine, // 커맨드라인 인자 전달 LPSECURITY_ATTRIBUTES psaProcess, LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles, DWORD fdwCreate, // 해당프로세스가 디버깅 목적으로 실행된다는 점 명시 LPVOID pvEnvironment, LPWSTR pszCurDir, LPSTARTUPINFOW psiStartInfo, // STARTUPINFO 포인터 LPPROCESS_INFORMATION pProcInfo // PROCESS_INFORMATION 포인터); |
fdwCreate에 특별한 값을 전달함으로써 해당 프로세스를 디버깅 목적으로 실행시킬 수 있다.
실행중인 프로세스를 디버거에 붙이기 위해서는 일단 해당 프로세스에 대한 핸들을 구해야 한다.
이는 attach에 직접 쓰이지는 않지만
여기서 사용하는 대부분의 함수가 프로세스 핸들을 필요로 하기 때문에 미리 구해놓는 것이다.
이 때 OpenProcess() 함수에 핸들을 얻고자하는 PID를 넘겨주면 구할 수 있다.
그리고 PID를 DebugActiveProcess()함수에 넘겨주면 해당 프로세스를 attach할 수 있다.
[3.2 CPU 레지스터 상태 얻기]
CPU 레지스터 상태를 얻기 위해서는 실행중인 스레드의 핸들을 얻어야 한다.
위에서 다룬 OpenProcess()함수와 유사한 OpenThread() 함수를 이용하면 된다.
이 때 TID값을 인자로 넘겨주어야 하는데 현재는 TID값을 알 수가 없다.
이를 알아내기 위해서는 프로세스 내부에서 실행중인 모든 스레드 리스트를 구해야 한다.
스레드 리스트를 알아내기 위해서 우리는 CreateToolhelp32Snapshot()이라는 강력한 함수를 이용하면 된다.
HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID); |
dwFlags에 구할 정보의 종류(스레드, 프로세스, 모듈, 힙)를 전달해준다.
스레드 리스트를 얻기 위해서는 TH32CS_SNAPTHREAD(0X00000004)를 전달한다.
th32ProcessID는 스냅샷을 구하고자 하는 프로세스의 PID를 의미하지만 이것은 특정모드에서만 사용된다.
따라서 우리는 구한 스레드가 어느 프로세스에 속한 것인지를 추가적으로 판단해야 한다.
BOOL WINAPI Thread32First( HANDLE hSnapshot, LPTHREADENTRY32 lpte); |
hSnapshot에는 CreateToolhelp32Snapshot() 함수가 반환한 핸들을 전달하고,
lpte에는 THREADENTRY32 구조체의 포인터를 전달한다.
Thread32First() 함수가 성공하면 첫 번째 스레드에 대한 정보가 lpte를 통해 전달된다.
typedef struct tagTHREADENTRY32 { DWORD dwSize; DWORD cntUsage; DWORD th32ThreadID; DWORD th32OwnerProcessID; LONG tpBasePri; LONG tpDeltaPri; DWORD dwFlags; DWORD th32AccessKey; DWORD th32CurrentProcessID; } THREADENTRY32; typedef THREADENTRY32* PTHREADENTRY32;typedef THREADENTRY32* LPTHREADENTRY32; |
th32ThreadID를 통해 TID값을 얻을 수 있다. (이는 앞서 설명한 OpenThread()함수의 인자로 전달된다.)
그리고 th32OwnerProcessID를 통해 스레드가 속한 프로세스의 PID를 얻을 수 있다.
이를 이용해 현재 구한 스레드가 디버깅 대상 프로세스에 속하는 것인지 판단할 수 있다.
그리고 구한 스레드 핸들을 GetThreadContext() 함수에 넘겨주면
해당 레지스터 값이 CONTEXT 구조체에 저장된다.
여기까지 디버거와 프로세스를 연결하는 방법과
CPU 레지스터 값을 출력하는 방법을 알아보았다.
'정상을향해 > Program Analysis' 카테고리의 다른 글
Mac OS에 Metasploit Framework 설치 방법 (0) | 2016.12.26 |
---|---|
Python Hacking Programming (3) (0) | 2013.11.10 |
Python Hacking Programming (2) (0) | 2013.11.10 |
PE File Format (4) (0) | 2013.11.10 |
PE File Format (3) (0) | 2013.11.10 |
PE File Format (2) (0) | 2013.11.10 |