본문 바로가기

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

Memory Breakpoint 이론, 함수 정리

메모리 브레이크 포인트는,

1. 브레이크 포인트를 설정할 메모리 영역의 베이스 주소와 페이지 크기를 구한다.

2. 해당 메모리 영역 페이지의 접근 권한을 변경해 보호 페이지 (Guard Page) 로 설정한다.

3. CPU가 보호 페이지에 접근하려 하면 GUARD_PAGE_EXCEPTION 가 발생.

4. 이 예외를 처리하는 핸들러에서 페이지 속성을 원래대로 바꾸고 실행이 계속되도록 한다.


페이지의 크기를 계산하려면 먼저 운영체제에게 디폴트 페이지 크기를 질의해야 한다.

이를 위해 GetSystemInfo() 함수를 이용해 SYSTEM_INFO 구조체 정보를 구한다.

SYSTEM_INFO 구조체의 dwPageSize가 시스템의 페이지 크기 값을 나타낸다.


페이지의 접근 권한 정보를 구하고 변경하는 방법은 ,

1. 메모리 브레이크포인트를 설정할 메모리가 속한 페이지를 구한다.

--> VirtualQueryEx() 함수를 이용하여 MEMORY_BASIC_INFORMATION 구조체를 구한다.

(MEMORY_BASIC_INFORMATION은 해당 페이지의 정보를 포함하는 구조체이다.)


함수 및 구조체 정의


SIZE_T WINAPI VirtualQuery(
    HANDLE hProcess,
    LPCVOID lpAddress,
    PMEMORY_BASIC_INFORMATION lpBuffer,
    SIZE_T dwLength
);

typedef struct MEMORY_BASIC_INFORMATION{
    PVOID BaseAddress,
    PVOID AllocationBase;
    DWORD AllocationProtect;
    SIZE_T RegionSize;
    DWORD State;
    DWORD Protect;
    DWORD Type;
}

MEMORY_BASIC_INFORMATION 구조체 정보를 구하면 구조체의 BaseAddress 를 이용해 페이지의 접근 권한을 변경하기 시작할 것이다. 

페이지의 접근 권한을 변경하는데 사용되는 함수는 VirtualProtectEx() 함수이다


VirtualProtectEx() 프로토 타입


BOOL WINAPI VirtualProtectEx(
    HANDLE hProcess,
    LPVOID lpAddress,
    SIZE_T dwSize,
    DWORD flNewProtect,
    PDWORD lpfloldProtect
);

전역 리스트를 이용해 보호 페이지로 설정한 페이지 정보와 메모리 브레이크 포인트의 주소를 관리하며,

GUARD_PAGE_EXCEPTION 발생 시 그것을 처리하는 핸들러에서 해당 리스트를 이용한다.

VirtualProtectEx() 로 메모리 영역이 속한 페이지의 접근 권한을 변경한다.

만약 브레이크 포인트를 설정할 메모리 영역이 여러 페이지에 걸쳐 있을 경우

해당 메모리 페이지 모두의 접근 권한이 변경된다.


my_debugger.py - 소스 참고


해당 소스 실행시

Guard Page Access Detected 라는 문구가 나와야 정상이다.


보호 페이지에 대한 접근으로 인해 예외가 발생할 때 운영체제는 해당 메모리 페이지의 보호 접근 권한을 제거하고 실행을 계속하므로 이벤트 핸들러에서 별도의 작업을 해줄 필요는 없다.

하지만 핸들러에서 다시 브레이크 포인트를 설정해 주거나 브레이크 포인트가 발생한 메모리 위치의 데이터를 읽는 등 다양한 기능을 수행하게 구현할 수 있다.