본문 바로가기

스터디/파이썬 해킹 프로그래밍

디버거와 프로세스를 연결하는 방법, CPU 레지스터 값을 출력하는 방법

지식출처: http://scytalezz.tistory.com/21

BOOL CreateProcess {



}


프로세스를 디버깅 하려면 일단 디버거와 프로세스를 연결해야 한다.

그래서 디버거에서 직접 프로세스를 실행시키거나, 이미 실행한 프로세스의 PID를 이용해 붙여야 한다.


프로세스를 실행시키는 경우, 프로세스의 코드가 실행되기 전 디버거가 제어를 할 수 있다는 장점이 있다.

윈도우에서 프로세스를 실행시킬 때 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 에 특별한 값을 전달하면 해당 프로세스를 디버깅 목적으로 실행 시킬 수 있다.

실행 중인 프로세스를 디버거에 붙이기 위해서는 일단 해당 프로세스에 대한 핸들을 구해야 한다.

프로세스와 디버거를 붙이는 데는 직접 쓰이지는 앉지만 여기서 사용하는 대부분의 함수가 프로세스 핸들을 필요로 하기 때문에 미리 구해 놓는 것이다.

핸들을 구하는 방법은 OpenProcess() 함수에 핸들을 얻고자 하는 PID를 넘겨주면 구할 수 있다.

그리고 DebugActiveProcess() 함수에 넘겨주면 해당 프로세스를 붙일 수 있다.


[+] CPU 레지스터 상태 얻기

CPU 레지스터 상태를 얻으려면 일단 실행 중인 쓰레드의 핸들을 얻어야 한다.

프로세스 핸들은 OpenProcess() 함수를 이용했지만, 쓰레드의 핸들은 OpenThread() 함수를 이용한다.

이 때, OpenProcess() 에 PID를 넘겨준 것 처럼 OpenThread()에도 TID를 넘겨줘야 하는데, 지금으로서는 알 수 있는 방법이 없다.

따라서 프로세스 내부에서 실행중인 모든 쓰레드 리스트를 구해야 한다.


이 쓰레드 리스트는 CreateToolhelp32Snapshot() 이라는 함수를 사용한다.




HANDLE WINAPI CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID 

);

dwFlags 에 구할 정보의 종류를전달해준다.

구할 수 있는 정보는 다음과 같다.

1. Thread

2. Process

3. Module

4. Heap


쓰레드 리스트를 리턴 받기 위해서는 TH32CS_SNATHREAD(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값을 얻어내고, (여기 TID값은 OpenThread() 함수의 인자로 전달)

그리고 th32OwnerProcessID 를 통해 쓰레드가 속한 프로세스의 PID를 얻을 수 있다.

이를 통해 구한 TID(쓰레드)가 디버깅 하는 프로세스에 속하는 쓰레드인지 판단할 수 있다.


그리고 GetThreadContext() 함수에 넘겨주면

--> 해당 레지스터 값이 CONTEXT 구조체에 저장된다.




디버거와 프로세스를 연결하는 방법과 CPU 레지스터 값을 출력하는 방법을 알아보았다.

'스터디 > 파이썬 해킹 프로그래밍' 카테고리의 다른 글

파이썬 해킹 프로그래밍 서적 오류 수정  (0) 2015.01.17
디버거 이벤트 헨들러 구현  (0) 2015.01.15
DLL 기초개념  (0) 2015.01.14
스터디 질문 답변  (0) 2015.01.14
2015-01-15 스터디  (0) 2015.01.12