티스토리 뷰

디버거 구현 시 중요한 세 가지 요소

  • Break Point
  • Memory Crash
  • Trap, Exception 처리

---------------------------------------------------------------------------------------------------------------------------------------

브레이크 포인트

  • Software Break Point :
    특징 : 명령을 실행하는 CPU를 일시 중지, 한 바이트 명령어를 사용해 디버깅 대상 프로세스의 실행을 중지
    코드 : 0xCC, INT 3
    용도 : 보통 어플리케이션을 디버깅할 때 사용되는 브레이크 포인트, 일반적임

    동작 방법
    1. 현재 IP의 opcode를 뽑아서 브레이크 포인터 테이블에 저장
    2. opcode를 0xcc로 교체
    3. 명령어 실행
    4. 원래의 opcode를 돌려놓음

     종류
    - 일회성 브레이크 포인트 : 한 번 브레이크 포인트 이벤트가 발생하면 디버거의 내부 브레이크 포인트 리스트에서 해당 브레이크 포인트 정보가 제거
    - 지속적인 브레이크 포인트 : 브레이크 포인트가 발생하고 CPU가 원래의 opcode를 실행한 후, 다시 브레이크 포인트 설정

    단점 : 메모리상의 실행 바이너리의 바이트를 변경하기 때문에 CRC 값이 변경됨(악성코드 분석 어려움)

  • Hardware Break Point :
    특징 : CPU 레벨에서 디버그 레지스트를 사용하여 브레이크 포인트를 설정
    코드 : INT 1, single step instruction(각 명령을 하나씩만 실행, 정밀 분석 가능)
    용도 : 설정할 브레이크 포인트 갯수가 적을 때, 디버깅할 소프트웨어의 코드가 변경되면 안 될 때 사용

    종류
    - DR0 ~ DR3 : 브레이크 포인트의 주소 저장
    - DR4 ~ DR5 : Reserved DR
    - DR6 : 브레이크 포인트에 의해 발생된 정보(디버깅 이벤트의 종류) 저장하는 디버깅 상태 레지스트
    - DR7 : 하드웨어 브레이크 포인트 스위치 역할, 서로 다른 브레이크 포인트의 조건 또한 저장


    단점 : 갯수가 부족(DR0 ~ DR3), 데이터 크기가 4바이트까지만 저장 가능(큰 메모리 영역에 접근 어려움)

  • Memory Break Point : 
    특징 : 정확히는 브레이크 포인트는 아니고, 하나의 분석 방법이다. 실행되는 어떤 코드도 변경하지 않으며 특정 메모리를 주시하거나 분리할 수 있다는 장점을 가짐
    설명 : 운영체제에서는 메모리를 할당하면 해당 메모리에 대해 기본적으로 쓰기, 읽기, 실행 권한을 부여, 추가적으로 보호 권한이 있는데 해당 페이지에 접근이 일어날 경우 Exception을 발생시켜 접근으로부터 보호하는 권한임
    용도 : 큰 메모리 영역에 접근한 후 분석을 하기 위해 사용, 보호 권한을 이용해서 특정 메모리를 주시하여 접근 확인을 통해 프로세스를 중지하거나 메모리 영역의 필요 이상의 할당을 확인하는데 유용, 스택에서 힙을 따로 분리할 수도 있음

    동작 방법
    1. 특정 메모리에 메모리 브레이크 포인트를 설정
    2. 특정 메모리의 권한이 변경되어 보호 권한이 설정됨
    3. 메모리에 대한 접근일 발생했을 경우 CPU에서 보호 페이지 디버그 예외처리를 발생시킴
    4. 해당 디버그를 통해 메모리 분석



참고 : 파이썬 해킹 프로그래밍(에이콘)



예제 소스코드(Software Break Point)

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <windows.h>
#include <TlHelp32.h>
 
#define BREAK_POINT 0xCC
 
using namespace std;
 
//Windows & Process Structure Information
class WINDOWS_INFO
{
protected:
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    HANDLE hProcess;
    HANDLE hThread;
};
 
class BREAKPOINT
{
public:
    DWORD Eip;
    WORD opcode;
};
 
//Windows Debugger Class
class DEBUGGER: public WINDOWS_INFO
{
private:
    char filepath[MAX_PATH];
    char cmdline[MAX_PATH];
    bool single_step;        //software breakpoint
    unsigned int bp_count;
    ATTACH at;                //attahed process check
    DEBUG_EVENT de;            //store debug event
    CONTEXT context;        //store register
    BREAKPOINT bp[1024];    //need linked list
 
public:
    //Configure Software BreakPonint
    BOOL Set_SoftBreakPoint()
    {
        MEMORY_BASIC_INFORMATION mbi;
        MEMORY_BASIC_INFORMATION temp_mbi;
        DWORD checksize = 0;
        BOOL ReadWrite_result;
        BYTE break_opcode = BREAK_POINT;
 
        /* 올바른 주소인지 체크 구문*/
        ReadWrite_result = ReadProcessMemory(hProcess, (LPCVOID)context.Eip, &bp[bp_count].opcode, 1&checksize);
        if((checksize != 1)||(ReadWrite_result != 1))
        {
            bp[bp_count].opcode = NULL;
            return FALSE;
        }
 
        VirtualQueryEx(hProcess, (LPCVOID)context.Eip, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
        if (!VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect))
        {
            bp[bp_count].opcode = NULL;
            return FALSE ;
        }
 
        bp[bp_count].Eip = context.Eip;
        break_opcode = BREAK_POINT;
        ReadWrite_result = WriteProcessMemory(hProcess, (LPVOID)context.Eip, (LPCVOID)&break_opcode, 1&checksize);
        if((checksize != 1)||(ReadWrite_result != 1))
        {
            bp[bp_count].opcode = NULL;
            return FALSE;
        }
 
        if (!VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &temp_mbi.Protect))
        {
            bp[bp_count].opcode = NULL;
            return FALSE ;
        }
 
        FlushInstructionCache(hProcess, mbi.BaseAddress, 1);
        bp_count++;
 
        return TRUE;
    }
};
 
DEBUGGER mydebugger;
cs
  1. EIP 위치의 opcode를 읽어와 EIP와 함께 저장
  2. EIP 위치의 페이지 권한을 가져와서 쓰기 권한 추가
  3. EIP 위치에 opcode를 0xCC로 변경
  4. EIP 위치의 페이지 권한을 본래의 권한으로 되돌림


'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
디버거의 기능 정리 및 기능별 함수 정리  (0) 2016.09.20
댓글
최근에 올라온 글
최근에 달린 댓글
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