본문 바로가기

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

파이썬 해킹 프로그래밍 서적 오류 수정

다음은 Fandu 형이 정리하신

"파이썬 해킹 프로그래밍" 서적에 대한 오류 정리 글을 퍼온 것이다.

출처 : http://fandu.tistory.com/entry/Gray-Hat-Python%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%95%B4%ED%82%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%B1%85%EC%97%90-%EC%9E%88%EB%8A%94-%EC%98%A4%EB%A5%98-%EB%B0%8F-%ED%95%B4%EA%B2%B0%EB%B2%95%EB%B2%95-%EC%A0%95%EB%A6%AC


절대 내가 쓴것이 아님을 다시 한번 밝힌다.


출처

출처출처출처

출처출처출처출처

출처출처출처

출처



Grat Hat Python을 공부해 보신 분이라면 아마 책을 그대로 배꼈음에도 불구하고 소스코드가 제대로 작동하지 않은 경우를 많이 격어 보셨을 겁니다. 저도 그랬는 데 정말 암 걸리더라구요.

구글링해서 제가 직접 소스코드를 작성도 해보았지만 역부족이더라구요.

그래서 몇 일 동안의 삽질과 구글링을 통해 이 모든 것의 해결 방법을 찾았습니다 ㅎㅎ


이 글은 http://stacksmash.org/2009/06/gray-hat-python-by-justin-seitz-errata/ 와 http://www.nostarch.com/grayhatpython 에서 언급된 책에 있는 오류들을 한국어로 재정리한 것 입니다. 저도 영어 보면서 눈 아퍼서...


원문으로 보신 분들도 있고 번역판을 보시는 분들도 있으실 거 같아서 페이지는 영어판과 한국어판의 페이지를 모두 적어드리겠습니다. (괄호 안에 있는 게 한국어판 페이지입니다. 괄호가 없는 경우에는 한국어판에는 수정할 필요가 없습니다.) 순서는 책의 순서에 따라 작성되었고 각 항목의 제일 밑에 있는 창에는 수정 후의 소스 코드가 적혀 있습니다.


1.  31페이지

attach 함수 안에 있는 self.run()을 지웁니다.

def attach(self, pid):

self.h_process = self.open_process(pid)


if kernel32.DebugActiveProcess(pid):

self.debugger_active = True

self.pid       = int(pid)

else:

print "[*] Unable to attach to the process."


2. 37페이지

whlie함수 안에 있는 

kernel32.CloseHandle(snapshot)

return thread_list

이 두 줄을 while 함수와 같은 위치에 둔다.

def enumerate_threads(self):

thread_entry = THREADENTRY32()

thread_list = []

snapshot = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, self.pid)

if snapshot is not None:

thread_entry.dwSize = sizeof(thread_entry)

success = kernel32.Thread32First(snapshot, byref(thread_entry))

while success:

if thread_entry.th32OwnerProcessID == self.pid:

thread_list.append(thread_entry.th32ThreadID)

success = kernel32.Thread32Next(snapshot, byref(thread_entry))

kernel32.CloseHandle(snapshot)

return thread_list

else:

return False


3. 42페이지지 (73,74페이지)

함수에 있는 

if self.exception == EXCEPTION_ACCESS_VIOLATION:

print "Access Violation Detected."

elif self.exception == EXCEPTION_BREAKPOINT:

continue_status = self.exception_handler_breakpoint()

elif self.exception == EXCEPTION_GUARD_PAGE:

print "Guard Page Access Detected."

elif self.exception == EXCEPTION_SINGLE_STEP:

self.exception_handler_single_step()

이 부분을 if debug_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT: 안에 들어가야한다.

def get_debug_event(self):

debug_event = DEBUG_EVENT()

continue_status = DBG_CONTINUE

if kernel32.WaitForDebugEvent(byref(debug_event),100):

self.h_thread   = self.open_thread(debug_event.dwThreadId)

self.context    = self.get_thread_context(h_thread=self.h_thread)

self.debug_event    = debug_event

   

print "Event Code: %d Thread ID: %d" % \

(debug_event.dwDebugEventCode,debug_event.dwThreadId)

if debug_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT:

self.exception = debug_event.u.Exception.ExceptionRecord.ExceptionCode

self.exception_address = debug_event.u.Exception.ExceptionRecord.ExceptionAddress

if self.exception == EXCEPTION_ACCESS_VIOLATION:

print "Access Violation Detected."

elif self.exception == EXCEPTION_BREAKPOINT:

continue_status = self.exception_handler_breakpoint()

elif self.exception == EXCEPTION_GUARD_PAGE:

print "Guard Page Access Detected."

elif self.exception == EXCEPTION_SINGLE_STEP:

self.exception_handler_single_step()

kernel32.ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, continue_status)


4. 42페이지

exception_handler_breakpoint()을 exception_handler_breakpoint(self)로 바꾸는 것것을 포함해서 함수의 모든 내용을 바꿔야한다.

def exception_handler_breakpoint(self):

print "[*] Exception address: 0x%08x" % self.exception_address

if not self.breakpoints.has_key(self.exception_address):

if self.first_breakpoint == True:

   self.first_breakpoint = False

   print "[*] Hit the first breakpoint."

   return DBG_CONTINUE

   

else:

print "[*] Hit user defined breakpoint."

self.write_process_memory(self.exception_address, self.breakpoints[self.exception_address])

self.context = self.get_thread_context(h_thread=self.h_thread)

self.context.Eip -= 1

kernel32.SetThreadContext(self.h_thread,byref(self.context))

continue_status = DBG_CONTINUE


return continue_status


5. 페이지 31

h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, pid, False)이 부분은 아래와 같이 수정한다.

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


6. 페이지 42

이 페이지에 있는 ec는 exception으로 수정한다.


7. 페이지 42 

__inti__(self) 함수에 다음 소스를 추가한다.

 self.first_breakpoint = True


8. 페이지 44

self.breakpoints[address] = (address, orginal_byte)이 부분의 앞에 탭을 지워 위 소스와 위치를 맞추고 address를 지운다.

 self.breakpoints[address] = (original_byte)



9. get_thread_context 함수

이 함수는 전체를 아래의 소스코드로 대체한다.

def get_thread_context (self, thread_id=None,h_thread=None):

context = CONTEXT()

context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS

if h_thread is None:

self.h_thread = self.open_thread(thread_id)

if kernel32.GetThreadContext(self.h_thread, byref(context)):

return context 

else:

return False


10. get_debug_event 함수

이 함수는 전체를 아래의 소스코드로 대체한다.

def get_debug_event(self):

debug_event = DEBUG_EVENT()

continue_status = DBG_CONTINUE

if kernel32.WaitForDebugEvent(byref(debug_event),100):

self.h_thread   = self.open_thread(debug_event.dwThreadId)

self.context    = self.get_thread_context(h_thread=self.h_thread)

self.debug_event    = debug_event

   

print "Event Code: %d Thread ID: %d" % \

(debug_event.dwDebugEventCode,debug_event.dwThreadId)

if debug_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT:

self.exception = debug_event.u.Exception.ExceptionRecord.ExceptionCode

self.exception_address = debug_event.u.Exception.ExceptionRecord.ExceptionAddress

if self.exception == EXCEPTION_ACCESS_VIOLATION:

print "Access Violation Detected."

elif self.exception == EXCEPTION_BREAKPOINT:

continue_status = self.exception_handler_breakpoint()

elif self.exception == EXCEPTION_GUARD_PAGE:

print "Guard Page Access Detected."

elif self.exception == EXCEPTION_SINGLE_STEP:

self.exception_handler_single_step()

kernel32.ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, continue_status)


11. 48 페이지 

if   available == 0: context.Dr0 = address

elif available == 1: context.Dr1 = address

elif available == 2: context.Dr2 = address

elif available == 3: context.Dr3 = address

이 부분을 for thread_id in self.enumerate_threads(): 안으로 넣는다.

def bp_set_hw(self, address, length, condition):

if length not in (1, 2, 4):

return False

else:

length -= 1


if condition not in (HW_ACCESS, HW_EXECUTE, HW_WRITE):

return False

if not self.hardware_breakpoints.has_key(0):

available = 0

elif not self.hardware_breakpoints.has_key(1):

available = 1

elif not self.hardware_breakpoints.has_key(2):

available = 2

elif not self.hardware_breakpoints.has_key(3):

available = 3

else:

return False


for thread_id in self.enumerate_threads():

context = self.get_thread_context(thread_id=thread_id)


context.Dr7 |= 1 << (available * 2)


if   available == 0: context.Dr0 = address

elif available == 1: context.Dr1 = address

elif available == 2: context.Dr2 = address

elif available == 3: context.Dr3 = address


context.Dr7 |= condition << ((available * 4) + 16)


context.Dr7 |= length << ((available * 4) + 18)


h_thread = self.open_thread(thread_id)

kernel32.SetThreadContext(h_thread,byref(context))


self.hardware_breakpoints[available] = (address,length,condition)


return True