본문 바로가기
[보안 Archive] ~2017/파이썬 해킹 프로그래밍

파해프 3.1 - 디버기

by Joy L. 2015. 1. 19.
반응형

이번 장의 목적은 순수파이썬 윈도우 디버거인 PyDbg를 제대로 이해하기 !!


3.1 디버기


프로세스 디버깅을 하려면 - 

* 해당 프로세스에 연결해야함

* 디버깅 할 프로세스를 실행시키거나 이미 실행돼 있는 프로세스에 attach 해야함.


윈도우는 이 두가지 작업을 쉽게 수행할수 있게 하는 디버깅 API를 제공한다. (더 추가할꺼임)


프로세스를 실행시키는것과 프로세스에 붙이는 것에는 약간의 차이가 있음. 


<프로세스를 실행 시킬 때> :

프로세스를 실행 시킬 때는 해당 프로세스의 코드가 실행되기 전에 제어를 할 수 있다.(장점) 그래서 악의적인 코드를 분석할 때 편리함.


<프로세스에 붙일 때> :

프로세스에 붙이는거는 이미 실핼중인 프로세스에 연결하는거임. 그래서 프로세스가 실작되면서 실행되는 코드를 건너뛸 수 있으며 관심 있는 특정 영역의 코드만을 분석할 수 있다.


디버깅 하려는 대상 프로세스가 어떤 것인지, 분석하려는 목적이 무엇인지에 따라 두 가지 방법 중 하나를 선택하면 됨.



=====================================================================================

<프로세스를 실행시켜 디버깅 할때>


프로세스를 실행시켜 디버깅 할때는 디버거가 실행 바이너리를 직접 실행시키는거임. 윈도우에서 프로세스를 실행시키려면 CreateProcessA() 함수를 호출해야함. 그리고 함수에 전달하는 특정 플래그의 값을 설정함으로써 프로세스를 디버깅 모드로 실행시킬 수 있다.


CreateProcessA() 함수의 포로토타입 : 

-----

BOOL WINAPI CreateProcessA(

LPCSTR lpApplicationName,

LPTSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation

);

-----


여기서 디버거가 프로세스를 실행시키기 위해 함수에 전달하는 주요 파라미터는 lpApplicationName, lpCommandLine, dwCreationFlags, lpStartupInfo, lpProcessInformation이다. 

그 외 나머지 파라미터에는 NULL 값을 입력해도 됨.  (함수에 대한 설명 msdn에서 찾아보기)


lpApplicationName lpCommandLine : 실행 시킬 바이너리의 경로와 커맨드라인 인자를 전달하기 위해 사용됨.


dwCreationFlags : 파라미터에 특별한 값을 전달함으로써 해당 프로세스가 디버깅 목적으로 실행된다는 점을 명시할 수 있음. (설명 더 알아보기)


lpStartupInfo  STARTUPINFO 구조체에 대한 포인터. (해당 구조체에는 프로세스가 어떻게 실행되야하는지에 대한 정보와 성공적으로 실행된 이후를 위한 정보가 포함된다.)


lpProcessInformation : PROCESS_INFORMATION 구조체에 대한 포인터. (해당 구조체에는 프로세스가 어떻게 실행되야하는지에 대한 정보와 성공적으로 실행된 이후를 위한 정보가 포함된다.)


(([[코드 예제]]))



=====================================================================================


<프로세스에 디버거를 붙일 때>



1. 먼저 프로세스에 대한 핸들을 구해야 함. 


프로세스 핸들을 얻기 위해서는 OpenProcess() 함수를 사용함. kernel32.dll에서 익스포트하는 함수임.


-----

HANDLE WINAPI OpenProcess(

DWORD dwDesiredAccess,

BOOL bInheritHandle,

DWORD dwProcessId

);

-----


dwDesiredAccess : 어떤 종류의 접근 권한을 가진 프로세스를 원하는지 입력. 프로세스에 대한 디버깅을 수행하려면 PROCESS_ALL_ACCESS 값으로 설정해야함.


bInheritHandle는 항상 False 값으로 설정.


dwProcessId : 핸들을 얻고자 하는 프로세스의 PID를 입력.


함수가 성공적으로 수행되면 해당 프로세스 객체에 대한 핸들을 반환할 것이다.



2. 프로세스에 붙이기


프로세스에 붙일 때는 DebugActiveProcess() 함수를 이용.


-----

BOOL WINAPI DebugActiveProcess(

DWORD dwProcessId

);

-----

Attach 할 프로세스의 PID를 전달하면 됨. 시스템은 디버거가 프로세스에 대한 올바른 권한을 갖고 있다고 판단하면 디버거가 해당 프로세스의 디버그 이벤트를 처리할 준비가 됐다고 가정하고 그 프로세스에 대한 제어권을 디버거에서 넘겨준다.


==================================================================================


<디버그 이벤트 처리>


디버거는 다음과 같은 WaitForDebugEvent() 함수를 이용해 디버그 이벤트를 처리한다.


-----

BOOL WINAPI WaitForDebugEvent(

  LPDEBUG_EVENT lpDebugEvent,

DWORD dwMilliseconds

);

-----


lpDebugEvent : 디버그 이벤트를 설명해주는 DEBUG_EVENT 구조체에 대한 포인터.


dwMilliseconds를 INFINITE로 설정하면 디버그 이벤트가 발생할 때까지 WaitForDebugEvent() 함수는 리턴하지 않고 대기한다.



발생하는 각 이벤트에 대해서는 그걸 처리하기 위한 이벤트 핸들러가 각기 있음. 이벤트 헨들러는 이벤트에 맞는 어떤 작업을 수행한 다음에 프로세스가 실행을 계속하게 해준다. 그래서 이벤트 헨들러의 작업이 완료되면 프로세스가 실행을 계속하게 만들어줘야함. 이때 사용하는 함수는 ContinueDebugEvent()이다.


-----

BOOL WINAPI ContinueDebugEvent(

DWORD dwProcessId,

DWORD dwThreadId,

DWORD dwContinueStatus

);

-----


dwProcessIddwThreadId : 디버그 이벤트가 발생할 때 설정되는 DEBUG_EVENT 구조체의 필드 내용이다.


dwContinueStatus  : 하나의 상태를 계속 유지하는거. 이걸 이용해 프로세스가 실행을 계속하게(DBG_CONTINUE) 만들거나 계속해서 예외를 처리하게(DBG_EXCEPTION_NOT_HANDLED) 만든다.


붙였던 프로세스에서 때어내는 detach일. PID를 파라미터로 DebugActiveProcessStop() 함수에 전달하면 해당 프로세스에서 떼어낼 수 있다.



<지금까지의 내용 모아서 my_debugger 클래스 확장 해보기>


(ie. 프로세스 붙이고 때는 것, 프로세스 핸들 얻는 기능을 my_debugger 클래스에 추가하는것, 디버그 인벤트를 처리하는 루프 작성)



(([[코드 예제]]))



calc.exe의 PID를 이용해서 my_test.py를 실행시킨다.

화면에 press a key to continue..가 출력됬을때 계산기 GUI 버튼이 안먹힘. 왜냐하면 계산기 프로세스가 일시 정지된 상태라서.


이걸 다 했으면 이제 my_debugger.py파일에서 다음 두 라인을 주석처리한다. (왜?!?!?)







반응형

댓글