[2주] 03장 - 윈도우 디버거 개발 (1)

Posted by dw0rdptr
2015. 1. 17. 22:12 Study/파이썬 해킹 프로그래밍

프로세스를 디버깅하려면 해당 프로세스를 연결해야하는데, 두가지 방법이 있다.


첫번째는 디버거가 직접 바이너리를 실행시키는 것이다. 이 경우에는 해당 프로세스의 코드가 실행되기 전에 제어 할 수 있다는 장점이 있으므로 악성코드나 기타 다른 형태의 악의적인 코드를 분석할 때 편리하다.

두번째 방법은 디버거를 이미 실행중인 프로세스에 attach(붙이는) 하는 방법이다. 이는 프로세스가 시작되면서 실행되는 코드를 건너뛸 수 있으며 특정 영역의 코드만을 분석할 수 있다.

윈도우에서는 이 두가지 작업을 쉽게 수행할 수 있게 하는 디버깅 api를 제공한다.

* 구동환경은 윈도우7 32bit


CreateProcessA함수로 계산기(calc.exe)를 열어보자



#my_debugger_defines.py
#-*- coding: utf-8 -*-
from ctypes import *

# ctypes 형태의 타입을 마이크로소프트의 타입으로 매핑
WORD	= c_ushort
DWORD	= c_ulong
LPBYTE	= POINTER(c_ubyte)
LPTSTR	= POINTER(c_char)
HANDLE	= c_void_p

#상수
DEBUG_PROCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010

#CreateProcesssA() 함수를 위한 구조체
class STARTUPINFO(Structure):
	_fields_= [
		("cb",				DWORD),
		("lpReserved",		LPTSTR),
		("lpDesktop",		LPTSTR),
		("lpTitle",			LPTSTR),
		("dwX",				DWORD),
		("dwY",				DWORD),
		("dwXSize",			DWORD),
		("dwYSize",			DWORD),
		("dwXCountChars",	DWORD),
		("dwYCountChars",	DWORD),
		("dwFillAttribute",	DWORD),
		("dwFlags",			DWORD),
		("wShowWindow",		WORD),
		("cbReserved2",		WORD),
		("lpReserved2",		LPBYTE),
		("hStdInput",		HANDLE),
		("hStdOutput",		HANDLE),
		("hStdError",		HANDLE),
	]


class PROCESS_INFORMATION(Structure):
	_fields_ = [
		("hProcess",		HANDLE),
		("hThrea",			HANDLE),
		("dwProcessId",		DWORD),
		("dwThreadId",		DWORD),
	]
구조체,유니온,상수를 미리 정의해놓는다.
#my_debugger.py
#-*- coding: utf-8 -*-
from ctypes import *
from my_debugger_defines import *


kernel32 = windll.kernel32

class debugger():
	def __init__(self):
		pass

	def load(self,path_to_exe):
		#dwCreation 플래그를 이용해 프로세스를 어떻게 생성할 것인지 판단.
		creation_flags = DEBUG_PROCESS
		
		#구조체 인스턴트화
		startupinfo			= STARTUPINFO()
		process_information	= PROCESS_INFORMATION()

		#프로세스가 독립적인 창으로 실행되게 해줌
		#STARTUPINFO struct구조체의 내용에 따라 디버기프로세스에 어떤영향을 미치는지 보여줌
		startupinfo.dwFlags		= 0x1
		startupinfo.wShowWindow = 0x0


		#STARTUPINFO struct 구조체 자신의 크기를 나타내는 cb 변수값을 초기화
		startupinfo.cb = sizeof(startupinfo)

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

			print "[*] We have successfully launched the process!"
			print "[*] PID : %d" % process_information.dwProcessId

		else:
			print "[*] Error : 0x%08x." % kernel32.GetLastError()
#my_test.py
import my_debugger

debugger = my_debugger.debugger()

debugger.load("C:\\Windows\\System32\\calc.exe")

raw_input("")
세 파일을 같은 디렉토리에 두고 my_test.py를 실행하면  
[*] We have successfully launched the process! 
[*] PID : 1588 

calc.exe 프로세스를 열었다. PID는 1588 
하지만 디버거로부터 실행을 계속하게 하는 명령을 받지 못해서 계산기 프로그램의 GUI를 볼수는 없다. 
이부분은 나중에 하자.


두번째 방법인 디버거를 프로세스에 attach하는 방법은 다음 글에서 정리하겠다.




'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글

[2주] 03장 - 윈도우 디버거 개발 (3)  (0) 2015.01.19
[2주] 03장 - 윈도우 디버거 개발 (2)  (0) 2015.01.18
api 기초  (0) 2015.01.12
[1주] 02장-디버거  (0) 2015.01.12
[1주] 01장 - 개발환경 구축  (0) 2015.01.12

api 기초

Posted by dw0rdptr
2015. 1. 12. 18:11 Study/파이썬 해킹 프로그래밍

API(Application Programming Interface) 함수 

윈도우 프로그램을 작성할 수 있도록 윈도우즈에서 지원하는 C 함수들

    - API 함수를 사용하려면 Windows.h를 포함하여야 한다.


핸들(handle)

    - 구체적인 어떤 대상에 붙여진 번호이며 문법적으로는 32비트의 정수값이다.
             *구분을 위해서는 문자열보다 정수를 사용하는 것이 훨씬 더 속도가 빠르기 때문이다.

     - 핸들을 사용하는 이유는 구분을 위한 것이므로 같은 종류의 핸들끼리는 중복되지 않아야 한다.

    - 핸들을 담기 위한 데이터형으로는 HWND, HPEN, HBRUSH, HDC 등이 있다.(모두 부호없는 정수형)

     - 핸들은 단순한 표식이므로 그 실제값을 알 필요는 없다.


변수와 데이터형

- 변수형은 길지도 짧지도 않게 정하며 자주쓰는 변수 형식에 대해선 관습적로 정해진 접두어를 사용한다

접두어         원래말            의미

cb          Count of Bytes        바이트 수

dw            double word        부호없는 long형 정수

h                handle               윈도우, 비트맵, 파일 등의 핸들

sz            Null Terminated    NULL 종료 문자열

w                 Word               부호없는 정수형

i                 Integer              정수형

b                Bool                 논리형


-새로운 변수명을 만들어서 사용하기도 한다


데이터형            의미

BYTE               unsigned char형

WORD              unsigned short형

DWORD            unsigned long형

LONG              long형과 동일

LPSTR             char *와 동일

BOOL              정수형이며 TRUE, FALSE 중 한 값을 가짐







[1주] 02장-디버거

Posted by dw0rdptr
2015. 1. 12. 17:31 Study/파이썬 해킹 프로그래밍

디버거 

디버거는 실행중인 프로세스를 트레이스하거나 동적 분석을 할수 있게 도와준다.

특히 동적분석은 악성코드 조사나 퍼저 적용에 있어 필수적이기 때문에 해커에게 디버거는 매우 중요하다고 볼 수 있다


디버거에는 화이트박스 디버거와 블랙박스 디버거가 있다.

화이트박스 디버거 : 개발플랫폼이나 IDE 등이 개발자가 자신이 작성한 코드를 디버그할 수 있게 자체적으로                             내장하고 있는 디버거이다.

블랙박스 디버거 : 리버스 엔지니어링이나 버그를 찾아내는 등 원본 소스코드가 없는 상태에서 분석을 목적으로                         사용되는 디버거이다.




범용 CPU 레지스터

레지스터는 CPU 내의 작은 저장공간으로 매우 빠르다.x86 아키텍처에서 CPU는                                       다음 8개의 범용 레지스터를 사용한다.


EAX : 산술 연산을 수행하기위해 또는 함수의 리턴값을 전달하기 위해 사용

EDX : 복잡한 연산을 위해 추가적으로 데이터를 저장할때 사용(또는 범용목적의 저장소)

ECX : 반복적으로 수행되는 연산에 주로 사용(미리 반복할 값을 넣어두고 감소시키면서 카운트를 셈)

ESI  : 시작지 인덱스(Source Index)

EDI  : 목적지 인덱스(Destination Index)

EBX : 특정한 목적이 없으므로 사용자가 목적에 맞게 씀

스택 레지스터

EBP : base pointer 레지스터. 스택을 위에서부터 아래로 자란다고 할때, 가장 위쪽이되는 위치를 가리키는 레지스터

ESP : stack pointer레지스터, 스택을 위에서부터 아래로 자란다고 할때, 스택의 가장 낮은 위치를 가리키는 레지스터



스택

스택은 FILO 구조이며 보통 스택을 아래에서부터 쌓아올리는 방식으로 표현하는데, 실제로 스택은 메모리를 효율적으로 쓰기 위해 높은주소부터 낮은주소로 쌓이므로 고드름처럼 자라는 방식으로 이해했다.

예시는 1장에서 함수호출규약을 정리할때 쓴 소스이다


ex) int c_fun(a,b,c){

int a_fun

{
        

         

cdecl 호출규약을 기준으로 파라미터 c,b,a 순서대로 push되고 지역변수 a_fun 을 선언했을때 스택프레임 모습이다.