티스토리 뷰

디버거의 기능 열거

  • 디버거 자체의 기능
    - 디버거 내에서 프로세스를 실행, 실행된 프로세스를 디버거에 붙이기
    - 디버거에 붙은 프로세스 실행, 종료, 브레이크 포인트 설정
  • 디버거 발생 이벤트 처리 
  • Code Section의 바이너리에 대한 디스어셈블러
  • CPU Register 값 파싱
  • Memory 파싱


디버거에 대한 함수는 마이크로소프트의 Windows에서 이미 API로 제공한다. 디버거를 만드는데 필요한 함수는 잘 가져와서 사용하면 된다.


디버깅 구조체 목록
※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679305(v=vs.85).aspx



디버거 기능 관련 함수

  • CreateProcess() : Windows에서 프로세스 실행, 특정 플래그 값을 설정하면 디버깅 모드 실행 가능
    ※ MSDN : https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
    - 첫 번째(lpApplicationName) 인자 : 실행파일의 경로 입력
    - 두 번째(lpCommandLine) 인자 : 파일 실행에 필요한 인자
    - 여섯 번째(dwCreationFlags) 인자 : CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS 입력!
    - 아홉 번째(lpStartupInfo) 인자 : STARTUPINFO 구조체 포인터(MSDN 참고)
    - 열 번째(lpProcessInformation) 인자 : PROCESS_INFORMATION 구조체 포인터(MSDN 참고)
    - 나머지 인자는 NULL을 입력해도 충분

  • OpenProcess() : 프로세스의 핸들을 얻기 위해 사용, 프로세스를 붙이기 위해서는 프로세스에 대한 핸들을 구할 필요가 있음
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms684320(v=vs.85).aspx
    - 첫 번째(dwDesiredAccess) 인자 : 원하는 접근 권한을 가진 프로세스 핸들 입력
    - 두 번째(bInheritHandle) 인자 : 항상 False
    - 세 번째(dwProcessId) 인자 : 핸들을 얻고자 하는 프로세스의 PID 입력

  • DebugActiveProcess() : 프로세스에 붙일 때 사용
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679295(v=vs.85).aspx
    - 첫 번째(dwProcessId) 인자 : 붙이고자 하는 프로세스의 PID

  • WaitForDebugEvent() : 디버그가 준비가 다 되었을 때 사용, 이를 통해 프로세스의 제어권을 받을 수 있음
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms681423(v=vs.85).aspx
    - 첫 번째(lpDebugEvent) 인자 : 디버그 이벤트를 설명해줄 DEBUG_EVENT 구조체의 포인터
    - 두 번째(dwMilliseconds) 인자 : 디버그 이벤트를 기다리는 시간(TTL), INFINITE 상수 존재

  • ContinueDebugEvent() : 디버그 이벤트 처리 후 프로세스를 이어서 실행
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679285(v=vs.85).aspx
    - 첫 번째(dwProcessId) 인자 : 디버그 이벤트 발생 시 설정되는 DEBUG_EVENT 구조체의 프로세스 PID
    - 두 번째(dwThreadId) 인자 : 디버그 이벤트 발생 시 설정되는 DEBUG_EVENT 구조체의 스레드 PID
    - 세 번째(dwContinueStatus) 인자 : DBG_CONTINUE or DBG_EXCEPTION_NOT_HANDLED

  • DebugActiveProcessStop() : 붙였던 프로세스를 떼어낼 때 사용
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679296(v=vs.85).aspx
    - 첫 번째(dwProcessId) 인자 : 떼어내고자 하는 프로세스의 PID

  • struct DEBUG_EVENT : 디버그 이벤트 구조체
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679308(v=vs.85).aspx
    - 첫 번째(dwDebugEventCode) 내용 : 디버그의 특정 이벤트에 맞는 이벤트 코드 값이 들어가게 됨



CPU 레지스터 상태 파싱 관련 함수 : 레지스터의 상태 정보를 구하려면 해당 프로세스 내부에서 실행 중인 모든 스레드의 리스트는 필수

  • OpenThread() : 현재 실행 중인 스레드의 핸들을 얻기 위해 사용
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms684335(v=vs.85).aspx
    - 첫 번째(dwDesiredAccess) 인자 : 원하는 접근 권한을 가진 프로세스 핸들 입력
    - 두 번째(bInheritHandle) 인자 : 항상 False
    - 세 번째(dwThreadId) 인자 : 핸들을 얻고자 하는 스레드의 TID 입력

  • CreateToolhelp32Snapshot() : 스레드 리스트, 프로세스와, 프로세스의 힙 리스트, 프로세스에 로드된 모듈 리스트를 수집하고자 할 때 사용
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms682489(v=vs.85).aspx
    - 첫 번째(dwFlags) 인자 : 얻고자 하는 정보, 스레드 리스트는 TH32CS_SNAPTHREAD(0x04)
    - 두 번째(th32ProcessID) 인자 : 원하는 정보를 뽑아낼 프로세스의 PID,
    (두 번째 인자의 조건 : TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPMODULE32, TH32CS_SNAPALL 모드)

  • Thread32First() : 스레드의 리스트를 열거하기 위한 함수
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms686728(v=vs.85).aspx
    - 첫 번째(hSnapshot) 인자 : CreateToolhelp32Snapshot() 함수가 반환한 핸들값
    - 두 번째(lpte) 인자 : THREADENTRY32 구조체의 포인터

  • Thread32Next() : 스레드 리스트에서 다음 스레드의 엔트리 정보 수집을 위해 사용
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms686731(v=vs.85).aspx
    - 첫 번째(hSnapshot) 인자 : CreateToolhelp32Snapshot() 함수가 반환한 핸들값
    - 두 번째(lpte) 인자 : THREADENTRY32 구조체의 포인터

  • GetThreadContext() : 모든 레지스터의 내용을 수집
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms679362(v=vs.85).aspx
    - 첫 번째(hThread) 인자 : OpenThread() 함수를 통해 얻을 수 있는 스레드의 핸들값
    - 두 번째(lpContext) 인자 : 모든 레지스터의 값을 담고 있는 CONTEXT 구조체 포인터



메모리 읽기 및 브레이크 포인트 관련 함수, 방법

  • ReadProcessMemory() : 프로세스의 메모리를 읽어들임(소프트 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms680553(v=vs.85).aspx
    - 첫 번째(hProcess) 인자 :  읽어들일 프로세스의 핸들
    - 두 번째(lpBaseAddress) 인자 : 메모리 영역에서 읽어들이기 시작할 시작 주소
    - 세 번째(lpBuffer) 인자 : 읽어들인 메모리를 저장할 버퍼의 포인터
    - 네 번째(nSize) 인자 : 읽고자 하는 메모리의 크기
    - 다섯 번째(lpNumberOfBytesRead) 인자 : 지정한 버퍼에 전송된 바이트 크기를 저장할 변수의 포인터

  • WriteProcessMemory() : 프로세스의 메모리를 씀(소프트 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms681674(v=vs.85).aspx
    - 첫 번째(hProcess) 인자 :  쓰고자 하는 프로세스의 핸들
    - 두 번째(lpBaseAddress) 인자 : 쓰기 시작할 메모리 영역의 시작 주소
    - 세 번째(lpBuffer) 인자 : 메모리에 쓰고자 하는 내용을 저장하고 있는 버퍼의 포인터
    - 네 번째(nSize) 인자 : 메모리에 쓰기할 크기
    - 다섯 번째(lpNumberOfBytesRead) 인자 : 지정한 버퍼에 전송된 바이트 크기를 저장할 변수의 포인터

  • GetProcAddress() : 프로세스에서 특정 함수의 가상 메모리 주소를 알아냄(소프트 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms683212(v=vs.85).aspx
    - 첫 번째(hModule) 인자 : 특정 DLL 모듈의 핸들(LoadLibrary, GetModuleHandle 등과 같은 함수로 라이브러리를 로드하면 알아낼 수 있음)
    - 두 번째(lpProcName) 인자 : 변수 또는 함수의 서수 값, 함수의 이름 입력

  • GetModuleHandle() : 로드된 모듈의 핸들 값을 알아냄, 단순하게 모듈의 핸들 값을 알아내고 싶을 때 사용(소프트 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms683199(v=vs.85).aspx
    - 첫 번째(lpModuleName) 인자 : 로드된 모듈의 이름

  • LoadLibrary() : 라이브러리를 로드할 때 사용, 지속적으로 모듈의 핸들 값이 필요할 때 사용(소프트 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms684175(v=vs.85).aspx
    - 첫 번째(lpFileName) 인자 : 로드할 파일의 이름

  • GetSystemInfo() : 메모리 페이지의 크기를 구하기 위해 사용(메모리 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms724381(v=vs.85).aspx
    - 첫 번째(lpSystemInfo) 인자 : SYSTEM_INFO 구조체의 포인터

  • VirtualQueryEx() : 메모리가 속해있는 페이지 정보를 알기 위해 사용(메모리 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa366907(v=vs.85).aspx
    - 첫 번째(hProcess) 인자 : 프로세스의 핸들
    - 두 번째(lpAddress) 인자 : 얻고자하는 페이지가 속한 메모리의 시작 주소 포인터
    - 세 번째(lpBuffer) 인자 : MEMORY_BASIC_INFORMATION 구조체의 포인터
    - 네 번째(dwLength) 인자 : lpBuffer를 통해 가리키고 있는 버퍼의 크기

  • VirtualProtectEx() : 페이지의 접근 권한 변경(메모리 브레이크 관련 함수)
    ※ MSDN : https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa366899(v=vs.85).aspx
    - 첫 번째(hProcess) 인자 : 프로세스의 핸들
    - 두 번째(lpAddress) 인자 : 접근 권한을 변경할 페이지의 시작 주소
    - 세 번째(dwSize) 인자 : 접근 권한을 변경할 페이지의 크기
    - 네 번째(flNewProtect) 인자 : 새롭게 변경할 메모리 보호 옵션
    - 다섯 번째(lpflOldProtect) 인자 : 변경하기 전의 메모리 보호권한을 저장할 포인터

소프트웨어 브레이크 포인터

  1. GetModulHandle() 함수를 통해 모듈의 핸들 값
  2. GetProcAddress()를 통해 특정 함수의 주소를 획득
  3. ReadProcessMemory()를 통해 특정 함수의 주소 + 오프셋의 opcode를 읽어와 저장
  4. WriteProcessMemory()를 통해 특정 함수의 주소 + 오프셋의 opcode를 0xCC로 변경
  5. WriteProcessMemory()를 통해 특정 함수의 주소 + 오프셋의 opcode를 본래의 opcode로 다시 돌려놓음

하드웨어 브레이크 포인터

  1. 모든 스레드의 리스트를 구함
  2. 각 스레드의 CPU 컨텍스트 레코드를 구함
  3. 모든 컨텍스트 레코드의 디버그 레지스터 중 하나에 브레이크포인트 주소 입력
  4. INT 1에 대한 인터럽트 처리 핸들러 추가

메모리 브레이크 포인터

  1. 브레이크 포인트를 설정할 메모리 영역의 주소와 크기를 구함
  2. 해당 영역의 접근 권한을 보호 페이지로 설정
  3. GUARD_PAGE_EXCEPTION 예외 발생 대기
  4. 예외 발생 시 예외처리 핸들러는 페이지 속성을 본래 권한으로 되돌림




'Project > Windows Debugger' 카테고리의 다른 글

디버거&디스어셈블러 제작 참고 자료 목록  (0) 2016.10.15
Simple PE Viewer  (5) 2016.10.07
Debugger 소스코드  (0) 2016.10.05
Single Step 구현  (3) 2016.09.30
브레이크 포인트(Break Point)  (0) 2016.09.19
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31