[컴][디버그] windows 에서 guard page 설정하기 - memory breakpoint

memory breakpoint using page fault on windwos

 

아직 부정확한 부분이 있어서, 정리차원으로 적어놓는다. PyDbg 부분에 대한 분석 이후에 update 를 해야 할 듯 하다.

 

Procedure

  1. page size 를 알아내고,
  2. page 에 permission 을 설정해서 guard page 처럼 작동하도록 한다.
  3. GUARD_PAGE_EXCEPTION 이 발생한다.
  4. exception handler 에서 다시 page 의 permission 을 돌려놓고(이 부분은 OS가 해준다.[ref. 1]), execution 을 계속 이어나간다.

 

 

Page Size

우리가 다룰 page 의 정확한 사이즈를 구하기 위해서, Operating System(OS) 에 default page size 를 물어봐야 한다. GetSystemInfo() 로 할 수 있다. 이 함수에서 SYSTEM_INFO structure 를 채워주는데 이 structure 가 dwPageSize 를 가지고 있다. 이 값이 default page size 가 된다.

 

Permission

page 정보

page permission 을 조정해 보자. 그러기 위해서 먼저 우리가 breakpoint 를 걸고 싶은 주소에 해당하는 page 의 정보를 가져오자. VirtualQueryEx() 로 가능하다. 이 함수에서 MEMORY_BASIC_INFORMATION structure 에 값이 채워지는데, 이 structure 가 가지고 있는 정보가 memory page 에 대한 정보를 가지고 있다.

 

permission 설정

여기에 있는 BaseAddress 정보가 시작점이 된다. permission 을 설정하는 함수는 VirtualProtectEx() 인데, 여기 2번째 인자로 들어가는 주소로 BaseAddress 를 넣어주면 된다.


guar page 에 access 를 해서 exception 이 발생하면 OS 가 메모리에 있는 그 page 의 exception 을 알아서 제거해 준다. 그래서 굳이 permission 을 제거하는 루틴을 짜지 않아도 괜찮다.

 

 

Demo

 

# source from Gray Hat Python
# edited by namh



memory_breakpoints = {}

creation_flags = DEBUG_PROCESS

# instantiate the structs
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()

startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb = sizeof(startupinfo)

kernel32.CreateProcessA(path_to_exe,
None,
None,
None,
None,
creation_flags,
None,
None,
byref(startupinfo),
byref(process_information)):

pid = process_information.dwProcessId
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)

system_info = SYSTEM_INFO()
kernel32.GetSystemInfo(byref(system_info))

page_size = system_info.dwPageSize


mbi = MEMORY_BASIC_INFORMATION()


# Attempt to discover the base address of the memory page
if kernel32.VirtualQueryEx(\
h_process, address, byref(mbi), sizeof(mbi)) < sizeof(mbi):
return False


current_page = mbi.BaseAddress

# We will set the permissions on all pages that are
# affected by our memory breakpoint.
while current_page <= address + size:

# Add the page to the list, this will
# differentiate our guarded pages from those
# that were set by the OS or the debuggee process
guarded_pages.append(current_page)

old_protection = c_ulong(0)
if not kernel32.VirtualProtectEx(\
h_process, current_page, size,\
mbi.Protect | PAGE_GUARD, byref(old_protection)):
return False

# Increase our range by the size of the
# default system memory page size
current_page += self.page_size

# Add the memory breakpoint to our global list
memory_breakpoints[address] = (address, size, mbi)

return True

 


References



  1. Chapter 3, Gray Hat Python
  2. http://www.codeproject.com/Articles/186230/Extending-windbg-with-Page-Fault-Breakpoints

댓글 없음:

댓글 쓰기