1. 개요 MyCrackIt.exe 프로그램은기본적으로대화상자기반의윈도우용프로그램이다. 분석을위해서해당프로그램에서사용되는 API에대한내용을사전에조사하게될경우빠른분석이가능하다. 따라서, 이번 MyCrackIt.exe 에서사용하는 API 함수에대해서사전에조사하는것이필요하며

Similar documents
0: 윈도우가비활성화되었을때 1: 윈도우가마우스클릭이외의다른방법으로활성화되었을때 2: 윈도우가마우스클릭으로활성화되었을때 윈도우의상태를나타내며, 윈도우가아이콘으로변했을경우 LOWORD는 0이아닌값이고, 0일경우는다음과같이 lparam 는 wparam 에의존한다. wpar

Microsoft PowerPoint - 09-CE-5-윈도우 핸들

1장 윈도우 프로그래밍 들어가기

CKKeyPro 적용가이드

Microsoft PowerPoint - chap06-2pointer.ppt

슬라이드 1

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

04장 메시지 처리 유형

11장 포인터

(Microsoft Word - \270\256\271\366\275\314 \271\370\277\252.doc)

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

윈도우즈 프로그래밍

예제와 함께 배워보는 OllyDbg사용법

<4D F736F F F696E74202D203031C0E520C0A9B5B5BFEC20C7C1B7CEB1D7B7A1B9D620B1E2C3CA5FBFB5B3B2C0CCB0F8B4EB205BC8A3C8AF20B8F0B5E55D>

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

Chapter 4. LISTS

Microsoft PowerPoint - 04windows.ppt

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - 09-CE-14-리스트콤보박스

Deok9_Exploit Technique

Microsoft PowerPoint - ch07 - 포인터 pm0415

No Slide Title

MFC 프로그래밍

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - chap06-1Array.ppt

03_queue

PowerPoint 프레젠테이션

윈도우즈 프로그래밍

UI TASK & KEY EVENT

=

Microsoft PowerPoint - hci2-lecture1.ppt

PowerPoint 프레젠테이션

02.Create a shellcode that executes "/bin/sh" Excuse the ads! We need some help to keep our site up. List Create a shellcode that executes "/bin/sh" C

PowerPoint 프레젠테이션

chap 5: Trees

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

ISP and CodeVisionAVR C Compiler.hwp

Microsoft PowerPoint - chap06-5 [호환 모드]

Microsoft PowerPoint - additional01.ppt [호환 모드]

OCW_C언어 기초

Microsoft Word - building the win32 shellcode 01.doc

hlogin2

Microsoft PowerPoint - a9.ppt [호환 모드]

PowerPoint 프레젠테이션

설계란 무엇인가?

Microsoft PowerPoint - hci2-lecture5.ppt

Microsoft PowerPoint - a10.ppt [호환 모드]

윈도우 프로그래밍

Lab 3. 실습문제 (Single linked list)_해답.hwp

INTRO Basic architecture of modern computers Basic and most used assembly instructions on x86 Installing an assembly compiler and RE tools Practice co

<4D F736F F D20B9D9C0CCB7B5B9D9C0CCB7AFBDBA5FBCF6C1A42E646F63>

Microsoft Word - hook3.doc

버퍼오버플로우-왕기초편 10. 메모리를 Hex dump 뜨기 앞서우리는버퍼오버플로우로인해리턴어드레스 (return address) 가변조될수있음을알았습니다. 이제곧리턴어드레스를원하는값으로변경하는실습을해볼것인데요, 그전에앞서, 메모리에저장된값들을살펴보는방법에대해배워보겠습

Microsoft Word - FunctionCall

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

Codegate Preliminary Match Repot

UI TASK & KEY EVENT

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - a8a.ppt [호환 모드]

K&R2 Reference Manual 번역본

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Microsoft PowerPoint - hci2-lecture5-messagemap.ppt

PowerPoint Presentation

API 매뉴얼

Microsoft PowerPoint - e pptx

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

OCW_C언어 기초

Microsoft PowerPoint - hci2-lecture1.ppt

강의 개요

Chapter 1. MFC 시작하기

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

1. auto_ptr 다음프로그램의문제점은무엇인가? void func(void) int *p = new int; cout << " 양수입력 : "; cin >> *p; if (*p <= 0) cout << " 양수를입력해야합니다 " << endl; return; 동적할

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

Chapter #01 Subject

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

Microsoft Word - Static analysis of Shellcode.doc

슬라이드 1

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

Reusing Dynamic Linker For Exploitation Author : Date : 2012 / 05 / 13 Contact : Facebook : fb.me/kwonpwn

Microsoft PowerPoint - chap01-C언어개요.pptx

목 차 1. 개요 취약점분석추진배경 취약점요약 취약점정보 취약점대상시스템목록 분석 공격기법및기본개념 시나리오 공격코드

학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2

Visual Basic 반복문

3.20 테러 악성코드바이너리분석 손충호 (StolenByte) WOWHACKER Group 해당문서는 WOWHACKER Group 의문서이므로, 무단도용및수 정및변조는할수없습니다. 페이지 1 / 20

슬라이드 1

윤성우의 열혈 TCP/IP 소켓 프로그래밍

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

Lab 4. 실습문제 (Circular singly linked list)_해답.hwp

untitled

Microsoft PowerPoint - chap03-변수와데이터형.pptx

Microsoft Word - Crackme 15 from Simples 문제 풀이_by JohnGang.docx

설계란 무엇인가?

-. Data Field 의, 개수, data 등으로구성되며, 각 에따라구성이달라집니다. -. Data 모든 의 data는 2byte로구성됩니다. Data Type는 Integer, Float형에따라다르게처리됩니다. ( 부호가없는 data 0~65535 까지부호가있는

Microsoft PowerPoint - a6.ppt [호환 모드]

Frama-C/JESSIS 사용법 소개

12 강. 문자출력 Direct3D 에서는문자를출력하기위해서 LPD3DXFONT 객체를사용한다 LPD3DXFONT 객체생성과초기화 LPD3DXFONT 객체를생성하고초기화하는함수로 D3DXCreateFont() 가있다. HRESULT D3DXCreateFont

Microsoft PowerPoint - 제11장 포인터(강의)

BY-FDP-4-70.hwp

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

Transcription:

2007 년 2 학기해킹및크래킹 분석자료 #1 MyCrackIt.exe 분석자료 분석대상프로그램다운로드 : http://crackmes.de 분석도구 : OllyDebugger 질문연락처 : kyegeun.kim@initech.com < 문서열람후질문이있을시에는상기메일주소로연락할것 > [ 1/34 ]

1. 개요 MyCrackIt.exe 프로그램은기본적으로대화상자기반의윈도우용프로그램이다. 분석을위해서해당프로그램에서사용되는 API에대한내용을사전에조사하게될경우빠른분석이가능하다. 따라서, 이번 MyCrackIt.exe 에서사용하는 API 함수에대해서사전에조사하는것이필요하며이에대한설명은프로그램을분석하는과정에서설명하도록한다. 사용되는 API 함수는다음과같다. 1 DialogBoxParam 2 SendMessage 3 GetDlgItem 4 StrToInt 5 GetModuleHandle 6 GetProcAddress 7 lstrcat 8 MessageBox 9 EndDialog 또한, 다음의사항을기본적으로알고있는것이분석을위해서도움이된다. 1) 함수의전처리과정 (Prolog) 상응하는후처리과정이존재하는것은숙지하도록한다. 2) 스택의위치와계산법 EBP, ESP 레지스터를통한스택의계산 3) 자동변수, static 변수, 전역변수등의저장위치 stack인지? heap인지? 어떻게저장되는지? 저장시에어떤크기 (bytes) 단위로할당이되는지? 4) 약간의어셈블리언어해석능력 어셈블리명령은 reference를보면서이해하면된다 5) 윈도우프로그래밍개념 기본적인구조와 API함수에대한지식 [ 2/34 ]

2. 분석과정 분석을위해서올리디버거를통하여역어셈블된코드를보면서설명을한다. 프로그램을실행시켜보면알겠지만해당프로그램은대화상자를기반으로동작하는프로그램이다. 윈도우프로그램을분류하자면, SDI, MDI, Dialog Based 등으로나뉠수있는데 MycrackIt.exe는대화상자기반 (Dialog Based) 의프로그램이다. 따라서, 대화상자기반의프로그램을작성하기위한기본골격을알면된다. 일반적으로 MFC가아닌 SDK로작성된대화상자기반의프로그램은 WinMain과 rm 안에위치한 DialogBox 혹은 DialogBoxParam과메시지처리함수 ( 일반적으로 DlgProc를많이사용 ) 로이루어져있다. 즉, 다음과같은코드형태를지닌다. int APIENTRY WinMain( 변수들 ) { DialogBoxParam( 변수들 ); } BOOL CALLBACK DlgProc( 변수들 ) { switch( 메시지 ) { case WM_XXXXX : case WM_XXXXX : case WM_XXXXX : } } break; break; break; 올리디버거를통해서해당프로그램을역어셈블하여살펴보게되면두개의함수로이루어진것을쉽게알수있다. 올리디버거에서함수의시작과끝을크게연결시켜보여주기때문이다. 다음그림을보면알수있다. 두번째칸의왼쪽에굵은검정색으로위아래를연결하는굵은검정색선이보일것이다. 이게함수의시작과끝을알려주는것으로해석하면된다. ( 화면표시를위하여조금강조해서그렸음 ) [ 3/34 ]

전체적인구조를확인하였으면함수를하나씩분석해보기로한다. [ 4/34 ]

2.1. WinMain 함수분석 분석과정에서일반적인윈도우프로그램과약간의상이한점이있더라도이프로그램은초보자를위한 프로그램이므로불필요한부분은삭제된상태로만들어졌다고보면된다. 이제코드분석을위해서올리디버거에서역어셈블한 WinMain 함수부분을살펴보도록한다. 00401000 XOR EAX,EAX ; kernel32.basethreadinitthunk 00401002 PUSH EAX ; /lparam => NULL 00401003 PUSH MyCrackI.00401019 ; DlgProc = MyCrackI.00401019 00401008 PUSH EAX ; howner => NULL 00401009 PUSH 81 ; ptemplate = 81 0040100E PUSH EAX ; hinst => NULL 0040100F CALL DWORD PTR DS:[<&USER32.DialogBoxParamA>] ; \DialogBoxParamA 00401015 XOR EAX,EAX 00401017 INC EAX 00401018 RETN 위의코드는올리디버거에나온것을복사해놓은것이다. PE(Portable Executable) 형식의윈도우실행프로그램은적재시에기본시작주소번지인 00401000에서부터시작되며이부분이프로그램의진입점 (EntryPoint) 가된다. 또한, 주소번지 00401002에서부터 0040100F 까지를보면 PUSH 명령과 CALL 명령의조합으로이루어져있다. 이는함수를호출하기전에함수로전달되는인자값을스택에저장하고함수를호출하는전형적인형태로함수를호출하는것을알수있다. 호출하는함수는 DialogBoxParam함수이다. 00401002 번에서 0040100E 에이르기까지코드가차례대로수행되면스택에는다음과같은데이터가 들어가있게된다. 스택은우리의개념과달리 위에서아래로쌓인다. [ 그림 2-1] 스택에넣은인자값 여기서각각의값에해당하는것은 API 함수와비교해보면쉽게알수있다. 주소번지 0040100F 번 지의내용은 [ 5/34 ]

0040100F CALL DWORD PTR DS:[<&USER32.DialogBoxParamA>] 으로 USER32.DLL 함수에속한 DialogBoxParam 함수를호출하라는코드이다. 함수의호출은역어셈블을하게되면 PUSH 명령과 CALL 명령의조합으로나타나게되는데함수의인자로전달되는값을스택에넣고 CALL 하게되면해당인자를호출된함수에서스택에서꺼내어사용하도록되어있다. DialogBoxParam 함수의원형을보게되면 INT_PTR DialogBoxParam( HINSTANCE hinstance, // 대화상자템플릿을정의한실행프로그램의핸들 LPCTSTR lptemplatename, // 대화상자템플릿 ( 리소스편집기로편집 ) HWND hwndparent, DLGPROC lpdialogfunc, LPARAM dwinitparam // 대화상자를소유한부모윈도우의핸들 // 대화상자로들어오는메시지를처리할함수 // 대화상자초기화시에사용할 LPARAM // WM_INITDIALOG 전송시에같이보내어질 // LPARAM 값을의미 ); 와같이나타난다. 여기에그림 1 의스택에저장된값을대입해보면 로표시할수있다. 좀더정리를해보면 가 ) hinstance 는화면에표시되는대화상자의 resource를포함한실행파일에대한핸들이다. 여기에서는 NULL을넣었는데이는자기자신을의미한다고볼수있다. 나 ) lptemplatename은대화상자의템플릿을가리키는데 Visual C++ 의 resource 편집기를통해서화면설계를할때각각은고유 Control ID라는정수값을가지며, 이정수값이문자로표시되는이름과연결된다. 여기서 lptemplatename이라고하는것은바로고유 Control ID와연결된이름을의미한다. 단, 이름은문자열이므로이에연결되는숫자 ( 즉, Control ID) 가 81임을나타내는것이다. 다 ) hwndparent는대화상자를표시한응용프로그램에대한핸들을가리키는데이프로그램은대화상자가바로메인윈도우이므로 NULL을넣게된다. 즉, 부모윈도우가없다는의미이다. 라 ) lpdialogfunc는메시지를처리하는함수의주소번지를가리킨다. 여기서는 00401019번이이 [ 6/34 ]

메시지처리함수의시작주소임을나타내고있다. 마 ) lparam은대화상자가처음생성되는초기화과정 (WM_INITDIALOG 이벤트발생 ) 에서같이보내어질 LPARAM 값을설정해주는것이다. 여기서는아무설정을사용하지않아 NULL을넣어주었다. 위의내용을비추어볼때 C 언어로작성된코드는아래와같이표시된다. DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DIALOG_1), NULL, DialogProc, NULL); 이제역어셈블된코드의남은부분을해석하기위해보면아래와같은코드를볼수있다. 00401015 XOR EAX,EAX 00401017 INC EAX 00401018 RETN 해당코드를한줄씩분석해보면 1 EAX 를초기화, EAX = 0 2 EAX 의값을 1 증가, EAX = 1 3 함수를종료하고반환 의의미가있다. 그런데함수가종료하면그반환값은 EAX 레지스터를통해서반환되게되며, 위의코드를보면반환값이 1임을알수있다. WinMain 함수이므로 WinMain 함수의 return type이 int 이므로정수 1을반환할것으로추측된다. 즉, 완성된 WinMain 함수는다음과같을것으로추측할수있다. int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpszcmdparam, int ncmdshow) { DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc, NULL); } return 1; 위의코드에서 DialogBoxParam 함수의두번째인자는대화상자의 Control ID 를이야기하고있으며, 이 는 VC++ 을이용해서프로그램을하는과정에서아래의그림처럼확인할수있다. 다시말해서 Control ID 는프로그램에하드코딩되어있으며이는 resource.h 에서확인이가능하다. [ 7/34 ]

그림 2-2 대화상자의 Control ID 확인 ( 윈도우프로그램작성중에확인한화면 ) [ 8/34 ]

2.2. 메시지처리함수분석 WinMain 함수에서호출한 DialogBoxParam 함수의네번째인자는해당대화상자롤들어오는윈도우메시지를처리하기위한함수를지정하는것이다. 따라서, 프로그래머는별도의함수를지정하여여기서윈도우에서기본으로제공하는메시지처리루틴이동작하기이전에원하는동작을할수있도록처리할수있다. 여기서메시지처리함수의이름이 DialogProc라고정하였으므로메시지처리함수는 DialogProc로선언하면된다. 또한, 윈도우에서메시지처리함수는 BOOL CALLBACK 으로선언하므로해당형식에따라서전달되는인자를설정해주면된다. 즉, 다음과같이선언될것이다. BOOL CALLBACK DialogProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam) { 생략 } 위의그림에서 (1) 번사각형은함수의전처리부분으로함수에서사용되는자동변수들을스택에할당하기위해서사용된다. 여기서는 DialogProc 함수에서사용하는변수등 ( 변수외에별도의내용을저장하기위한공간도할당하기때문에변수등이라고하였음 ) 을위한스택공간할당을의미한다. 정확한스택의구조는역어셈블과정을통해서이후에설명하도록한다. (2) 번부분은메시지처리함수인 DialogProc함수로들어오는메시지가 WM_COMMAND인지를판단하는루틴이라고보면된다. [ 9/34 ]

Winuser.h 헤더파일에보면 0x111 의숫자를갖는메시지는 WM_COMMAND 이다. 해당코드와연관된부분을정리해보면아래와같이나누어볼수있다. 0040101F CMP DWORD PTR SS:[EBP+C],111 ; 윈도우메시지확인 00401026 JNZ SHORT MyCrackI.0040103B ; WM_COMMAND가아니면 0040103B번지로이동 생략 0040103B XOR EAX,EAX ; 반환값을만들기위해 EAX 초기화 0040103D JMP MyCrackI.004011A2 ; 004011A2로이동 생략 004011A2 LEAVE ; 함수후처리과정을지원 004011A3 RETN 10 ; 함수종료 이는메시지처리함수의특정인자를통해들어오는값을비교하여어떤처리과정을거치도록하고있 다. 우선메시지처리함수의프로토타입은아래와같다. BOOL CALLBACK DlgProc(HWND hdlg,uint imessage,wparam wparam,lparam lparam) 위의메시지처리함수에서 EBP는스택프레임포인터로 DlgProc함수에서사용하는스택의경계를가리킨다. 이지점부터낮은주소는함수내부에서사용하는변수들이저장되는공간이고높은주소는함수호출과관련하여저장된값들이다. 함수가호출되게되면스택에는다음과같은기본사항들이저장되게된다. [ 그림 2-3] 메시지처리함수의스택구조 ( 함수전처리과정직후 ) 따라서위의역어셈블코드중 SS:[EBP+C] 번지에위치한값은 imessage( 윈도우메시지코드 ) 이며, [ 10/34 ]

수신된윈도우메시지코드가 WM_COMMAND 인지를비교하는부분이첫줄이다. 여기서수신한윈도우메 시지코드가 0x111(WM_COMMAND) 일때와아닐때의처리방식이나뉘게된다. 우선 WM_COMMAND 가 아닐경우는다음의처리과정을갖는다. 주소번지 (offset) 0040101F 0040103B 004011A2 설명 MyCrackIt의 0040103B 번지로이동하라. 즉, WM_COMMAND가아닐경우의처 리부분으로이동하라는명령 EAX 를초기화하고 004011A2 번지로이동하라. 즉, 함수의반환값을저장하는 EAX 를 0 으로만들어반환값을 0 으로 1 타입이므로 0 값은 FALSE 를의미 설정하라. 여기서 DlgProc 함수는 BOOL LEAVE 명령을수행 ( 함수의후처리과정을지원 ) 하고호출한함수로돌아가라 두번째로입력된윈도우메시지가 WM_COMMAND 일경우는다음과같이처리한다. SS:[EBP+10] 번의위치에있는값을 EAX 레지스터로이동하는데 SS:[EBP+10] 번지의내용은함수 로전달되는 3 번째인자인 wparam 을의미한다. 2 이를전체적인구조의 C++ 형태로보면다음과같다. BOOL CALLBACK DlgProc(HWND hdlg,uint imessage,wparam wparam,lparam lparam) { switch(imessage) { case WM_COMMAND: 생략 } return FALSE; } 주소번지 00401028 부터는윈도우메시지를확인한결과값이 WM_COMMAND일경우를처리하는과정이다. WM_COMMAND 윈도우메시지 3 는일반적으로 wparam과 lparam 변수를같이쓰게되는데주로 wparam은어떤컨트롤이메시지를보냈는지를확인하는것이다. 다시말해서윈도우화면에서 확인 버튼을눌렀는지, 취소 버튼을눌렀는지를구분할수있다. lparam은메시지를보낸컨트롤의윈도우핸들이저장된다. lparam의경우 MyCrackIt 프로그램에서는사용하지않으므로설명은생략한다. 상세한설명은아래와같다. 1 DlgProc 함수의타입이 BOOL 이므로값 0 은 FALSE 를의미한다. 2 10 쪽의 [ 그림 2-3] 메시지처리함수의스택구조 ( 함수전처리과정직후 ) 를참고하라. 3 메뉴, 액셀러레이터를선택했을때이메시지가전달되며차일드컨트롤이부모윈도우로통지메시지를전달할때도이메시지형태로전달된다. 각종컨트롤로부터값이전달되며또한각컨트롤은다양한통지메시지를보내므로이메시지는일반적으로이중 switch 문으로작성된다. 즉, 윈도우화면에서사용자가버튼을누르는등의특정행위를했을때이를처리하기위한메시지로보면된다. [ 11/34 ]

00401028 MOVZX EAX,WORD PTR SS:[EBP+10] (1) 0040102C DEC EAX 0040102D DEC EAX (2) 0040102E JE MyCrackI.00401194 00401034 SUB EAX,3E9 (3) 00401039 JE SHORT MyCrackI.00401042 MyCrackIt 의 00401028 번지부터 00401039 번지까지는위와같이 3 부분으로나뉘어질수있다. 각부분에대한설명은다음과같다. A. (1) 번구간은 SS:[EBP+10] 번메모리주소에있는내용을 EAX레지스터로옮기라는명령이다. 단, MOV 명령과다른점은소스에서목적지로복사할때크기가다르면남는부분은 0으로채워넣으라는것이다르다. 4 명령에서복사할내용은 WORD 크기로 2바이트임을나타내고복사할곳의번지는 SS:[EBP+10] 으로 10쪽의 [ 그림 2-3] 을참조하면 wparam 을의미한다. 따라서, 이는 SS:[EBP+10] 번지에서 2바이트를 EAX로 4바이트로확장하여복사하면서 EAX의나머지상위 2바이트는 0으로초기화한다는것을의미한다. FF 3D FF 3D ㄱ 00 00 FF 3D 34 6C FF 3D < MOVZX 를통한복사 > < MOV 를통한복사 > 위의그림에서보듯이 MOVZX를사용하면상위 2바이트에 0 값을채워놓아확장이되더라도원하는값이그대로저장되지만, MOV를사용할경우하위 2바이트는원하는값이복사되지만상위 2바이트에는어떤값이들어갈지모른다. 다시말해서이전에있던값의상위 2 바이트값이남아있어전체적으로 4바이트값을보면원하는값이복사된것이아님을알수있다. 따라서, MOVZX는하위 2바이트를 4바이트로확장하여옮기는것을의미한다. B. (2) 번구간은위에서설명한바와같이이동한 wparam의값에서 2를뺀뒤이값이 0과같으면 (wparam 값이 2이면 ) 00401194 번지로이동하라는명령이다. 주목할것은여기서 wparam의값이 2 라는것이어떤의미인가하는것이다. 일반적으로 WM_COMMAND와함께들어오는 wparam의값은통지메시지를보낸항목의 ID 값을나타낸다. 즉, ID 가 2번이라는것인데여기서는좌측상단의종료메뉴를의미한다. 4 MOVZX 명령에대한자세한내용은어셈블리명령을참조하라. [ 12/34 ]

C. (3) 번구간은 EAX가 0x3E9(10진수 1001) 인지를비교하는데이는원칙적으로 EAX에원래할당된값, 다시말해 SS:[EBP+10] 번지에저장되었던값인 wparam이 0x3EB(10진수 1003) 인지를확인하는것이다.( 이미앞에서 DEC EAX를두번하였기때문에 2값을더해야한다.) 여기서 1003은마찬가지로 ID 번호 1003을의미하는데이는 Microsoft Visual Studio에서제공하는유틸리티인 Spy++ 를사용하여해당프로그램의 Control ID를알아낼수있다. 따라서, 위의 3 부분을각각분석한결과를합쳐서설명하면 wparam 값이 2인경우 ( 종료버튼이보낸메시지인경우 ) 에는 00401194 번지로이동하여명령을수행하고, 1003(0x3EB) 인경우 (Let s go 라고쓰인버튼인경우 ) 에는 00401042번지로이동하여명령을수행하라는의미이다. 이를좀더쉽게표현하자면종료버튼이눌렸을경우와 Let s go 라는버튼이눌렸을때의동작을의미한다. 다음역어셈블코드부분은아래와같이두줄을해석하면된다. [ 13/34 ]

0040101F CMP DWORD PTR SS:[EBP+C],111 00401026 JNZ SHORT MyCrackI.0040103B 생략 0040103B XOR EAX,EAX ; Default case of switch 0040102C 0040103D JMP MyCrackI.004011A2 생략 004011A2 LEAVE 004011A3 RETN 10 위의내용을보면 EAX를초기화하여 0으로만들고 004011A2 번지로이동하고해당번지를보면함수를종료하는것임을알수있다. (004011A2번지이하의내용은앞서설명하였다.) 여기서, 0040103B번지로어디서왔는지를위에서참고하여보면 00401026번지와연관지을수있다. 즉, 위의코드는수신한윈도우메시지가 WM_COMMAND가아닐경우반환값을 0으로초기화 (FALSE) 로만든후함수후처리과정을거쳐서종료하는것을의미한다. 여기서정리를한번해보면 00401042 번지부터는 WM_COMMAND 메시지를수신하고 Control ID 가 1003 일경우 ( 즉, Let s go 버튼을누른경우 ) 에수행되는코드를나타내고있다. 여기서 MyCrackIt 프로그램의각아이템의 Control ID 를 Spy++ 를통해확인해보면아래그림과같다. [ 그림 2-4] 아이템의 Control ID 확인 (ID = 2 는 Control ID 아님 ) 위 [ 그림 2-4] 에서설명의편의를위하여사용자입력을받아들이는두개의편집상자에 Edit1 과 Edit2 라는이름을주었다. 우선각아이템의 Control ID는그림에서보는바와같으며, 시스템메뉴의종료상자 (ID = 2) 는 Spy++ 를통해서확인되지않는다. 옵셋번지 00401042번부터 0040116D 번까지가두개의편집상자에모두맞는답을넣었을때처리되는과정이고 0040116F에서 00401192 번까지는답이틀렸을때메시지박스를나타내는코드이다. 우선이부분의설명을위하여역어셈블코드에서사용하는내부변수에대한정리를해둘필요가있다. 메시지처리함수의함수전처리과정에서 SUB ESP, 4C 라고하여 76바이트를내부지역변수를위하여할당한것은확인할수있으므로역어셈블코드에서 SS:[EBP-XX] 라고되어있는것들을정리하여분석과정에사용하는것이편리하다. 이를정리해보면다음과같다. [ 14/34 ]

코드에서사용 변수명 변수타입 비고 SS:[EBP+14] hdlg HWND 메시지처리함 SS:[EBP+10] imsg UINT 수로전달되는 SS:[EBP+C] wparam WPARAM 인자 SS:[EBP+8] lparam LPARAM 코드에서사용 임시로사용할변수명 예상되는변수타입 ( 크기 ) 비고 SS:[EBP-C] Var_1 문자열 (12 Bytes) SS:[EBP-18] Var_2 문자열 (12 Bytes) SS:[EBP-28] Var_3 문자열 (16 Bytes) SS:[EBP-3A] Var_4 문자열 (40 Bytes) 메시지처리함 수에서사용하 는지역변수 SS:[EBP-4C] Var_5 문자열 (58 Bytes) [ 표 2-1] 메시지처리함수에서사용하는스택과변수의연관 00401042 PUSH EBX ; EBX 레지스터를사용하기위해이전값을스택에저장 00401043 PUSH ESI ; ESI 레지스터를사용하기위해이전값을스택에저장 00401044 MOV ESI,DWORD PTR DS:[<&USER32.GetDlgItem>] 0040104A PUSH EDI 0040104B PUSH 3E8 00401050 PUSH DWORD PTR SS:[EBP+8] User32.dll 의 GetDlgItem 함수호출임을추정할수있 는부분 00401053 CALL ESI (1) 00401055 MOV EDI,DWORD PTR DS:[<&USER32.SendMessageA>] 0040105B LEA ECX,DWORD PTR SS:[EBP-C] 0040105E PUSH ECX 0040105F PUSH 0A (2) 00401061 PUSH 0D 00401063 PUSH EAX 00401064 CALL EDI 00401066 PUSH 3EA 0040106B PUSH DWORD PTR SS:[EBP+8] (3) 0040106E CALL ESI 00401070 MOV ESI,EAX 00401072 LEA EAX,DWORD PTR SS:[EBP-C] 00401075 PUSH EAX (4) 00401076 CALL DWORD PTR DS:[<&SHLWAPI.StrToIntA>] [ 15/34 ]

0040107C LEA ECX,DWORD PTR SS:[EBP-18] 0040107F PUSH ECX 00401080 PUSH 0C 00401082 SUB EAX,200E4 (5) 00401087 PUSH EAX 00401088 PUSH ESI 00401089 CALL EDI 위 (1) 번구간은 GetDlgItem 함수를실행시키는부분이다. 우선 PUSH와 CALL의조합은함수호출이라는것을유념하고분석을한다. 코드를보면 USER32.dll의 GetDlgItem함수를호출하는것을알수있는데이는 00401044번에서 User32.dll의 GetDlgItem함수에대한포인터를 ESI레지스터에넣고 00401053번에서 ESI 레지스터에대해 CALL 명령을수행한것으로알수있다. 분석을쉽게하기위해 GetDlgItem API를참조해보면다음과같은원형을확인할수있다. HWND GetDlgItem(HWND hdlg, int niddlgitem); 즉, 스택에저장될내용은우선대화상자의핸들인 hdlg, 대화상자에속한아이템의 control ID인 niddlgitem 이다. 실제 API함수호출을위해인자를넣은것은 CALL 바로앞서이루어지므로맨아래줄의 CALL ESI 가 User32.dll의 GetDlgItem함수를호출한것이므로 (3번째줄에 ESI에해당 API의주소번지를저장하였으므로 CALL ESI는함수호출동작임 ) 그바로위의두줄에걸친 PUSH가인자를넣는부분이된다. 따라서, 첫번째인자인 hdlg는 SS:[EBP+8] 이므로메시지처리함수로들어오는첫번째인자를가리키고, niddlgitem은 0x03E8 인십진수 1000번을의미한다. [ 그림 2-4] 에서 1000번은 Edit1 이므로아래의 3줄은 GetDlgItem함수를통해서대화상자의 Edit1 아이템에대한핸들을얻기위한것으로보면된다. 또한, CALL ESI를하게되면함수가호출되게되고함수가호출한이후의반환값은 EAX레지스터에저장된다. 따라서, CALL ESI 를수행하고나면 (GetDlgItem 수행 ) 이후에는 EAX에해당아이템의핸들이저장된다. 이를 C++ 코드로작성하면다음과같다. GetDlgItem(hDlg, IDC_EDIT_1); 이제 ESI 레지스터에 GetDlgItem 함수에대한포인터가저장되어있고, EAX 에는 Edit1 편집상자에 대한핸들이저장되어있음을숙지하고살펴보기로한다. (2) 번구간은결론적으로볼때 SendMessageA 함수를호출하기위한과정이다. 따라서, SendMessage 함수에대한원형을보면다음과같다. LRESULT SendMessage(HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam); [ 16/34 ]

마찬가지로 CALL EDI라고하는마지막줄이 SendMessage를호출하는것이므로함수에서사용하는인자 4개는 CALL명령이전에존재하게된다. - EDI 레지스터에 user32.dll의 SendMessageA API함수의주소를저장 - SS:[EBP-C] 즉지역변수인 Var_1 의주소를 ECX레지스터가가리키도록함 - ECX 레지스터값을스택에저장 (Var_1변수가할당받은메모리번지저장 )(lparam인자) - 0x0A( 십진수 10) 를스택에저장함.(wParam 인자 ) - 0x0D( 십진수 13) 를스택에저장함. 여기서 13은윈도우메시지코드의값으로 winuser.h를참조하면 WM_GETTEXT를말한다. WM_GETTEXT는대상아이템에서문자열을읽어오라는명령으로 wparam과연동되는데 wparam은읽어들일문자열의최대길이를말한다. 여기서는위에서 0x0A를저장했으므로최대 10개의문자를읽어들인다. (Msg인자) - EAX레지스터값을스택에저장 (EAX는 GetDlgItem 함수의반환값이저장 )(hwnd인자) 결국 (1) 번, (2) 번구간을묶어서살펴보면 Edit1 편집상자에대한핸들을얻고, 그핸들을이용하여 Edit1편집상자에 WM_GETTEXT 메시지를전송하여최대 10개의문자를읽어오도록하는것이다. (2) 번구간의마지막줄인 CALL EDI 를수행하면이제 EAX에는 SendMessage 함수를실행하고반환받은결과값이저장되었으므로더이상 Edit1 편집상자의핸들을갖지않는다. 그러나, ESI는여전히 GetDlgItem 함수에대한포인터를가지고있으며, (2) 번구간첫줄의명령에의해 EDI는 SendMessage 함수에대한포인터를가지고있음을확인할수있다. 위에서 (3) 번, (5) 번구간은각각 (1) 번, (2) 번구간과유사한코드를보여주고있다. 여기서 (3) 번구간은대상아이템의번호만 0x03E8에서 0x03EA로바뀌었을뿐이다. 이는 [ 그림 2-4] 를보면 Edit2 편집상자의 Control ID가할당되어 GetDlgItem을수행하게되므로결국 (3) 번구간의끝에서 EAX레지스터에는 Edit2 편집상자의핸들이저장되게된다. (4) 번구간을분석해보면 EAX의값을우선 ESI레지스터에넣는데이는반화값이넘어가는것을의미하며여기서는 Edit1 편집상자에서읽어들인문자열의길이가 ESI레지스터로저장됨을의미한다. 이후 3줄은 Var_1 (SS:[EBP-C]) 을 EAX레지스터에할당하여스택에넣고 StrToInt함수를호출한다. StrToInt 함수는 null 로끝나는문자열을인자로받아서이를정수로변환하여반환하는함수로원형은다음과같다. int StrToInt(LPCTSTR lpsrc); 따라서, (4) 번구간의의미는 (3) 번구간을통해서 Edit1 편집상자에서읽어들인값을정수로변환 하는것을의미하며여기서우리는 Edit1 편집상자는최대 10 자리까지의숫자를입력해야한다는것 을알수있다. 이후 (5) 번구간은 (2) 번구간과유사하나좀더자세히보면중간에 SendMessage 함수에서 Msg 에 대한부분을결정하는부분이무언가를계산하도록되어있는것을알수있다. [ 17/34 ]

00401082 SUB EAX,200E4 00401087 PUSH EAX 해당부분을보면위의코드와같이 EAX에서 0x0200E4 를빼고그값을저장하도록되어있다. 여기서 EAX는 StrToInt 함수의반환값으로이는 Edit1 편집상자에입력된문자열을정수로형변환한값에서 0x0200E4( 십진수 131300) 을뺀나머지값이스택에저장되는데이값이윈도우메시지코드로사용되는것을확인할수있다. 유형이 (2) 번구간과동일하므로여기서는결과값이 0x0D ( 십진수 13) 가나와야 Edit2 편집상자에서문자열을읽어올수있도록하는것임을유추할수있다. 따라서, Edit1 편집상자에들어가야할값은 131313 임을알아낼수있다. Edit1 편집상자에대한입력값 : 131313 [ 18/34 ]

이제 0040108B 부터의역어셈블코드에대한분석을하여야하는데그전에미리다음의사항을알아 두고넘어가도록한다. 해당부분에서부터는프로그램의 BSS 영역에사전에정의된문자열혹은데이터 값을넣어두고있으며, 올리디버거를통하여해당정보를파악해보면아래와같다. [ 그림 2-5] 사전에지정된변수의값및상수값 각메모리주소에는프로그래머가코딩시에선언한변수등에대한고정값이있을경우이를 PE 파일내에저장하게되며, 메모리에적재되었을경우에는스택이아닌힙혹은 bss 영역에저장된다. 위의화면덤프는해당부분을덤프한것으로프로그램분석과정에서쓰일각주소번지에저장되어있는값들을저장하면아래의표와같다. 메모리주소 16 진수값 아스키코드 00402030 57 72 6F 6E 67 21 00 W r o n g! 00402038 45 72 72 6F 72 21 00 E r r o r! 00402040 57 65 6C 6C 20 64 6F 6E W e l l d o n 65 2E 00 e. 0040204C 7F 52 45 41 58 46 5C 5E R E A X F \ ^ 5E 5F 48 51 55 52 45 00 ^ _ H Q U R E 0040205C 54 68 65 20 70 61 73 73 T h e p a s s 77 6F 72 64 20 69 73 3A 20 00 w o r d i s : 00402070 75 73 65 72 33 32 00 u s e r 3 2 00402078 24 0B 15 1C 13 0A 04 36 06 17 2F 64 64 원래 16진코드로할당되었을것으로분석되어아스키코드로변환하지않음 [ 표 2-2] 고정변수값정리표 [ 19/34 ]

0040108B MOV ESI,MyCrackI.00402078 00401090 LEA EDI,DWORD PTR SS:[EBP-28] 00401093 MOVSD ; ESI가가리키는주소에서 EDI가가리키는주소로 4바이트복사 00401094 MOVSD ; 복사후 ESI, EDI는각 4바이트뒤를가리킴 00401095 MOVSD 00401096 MOVSW ; ESI가가리키는주소에서 EDI가가리키는주소로 2바이트복사 ; 복사후 ESI, EDI는각 2바이트뒤를가리킴 00401098 XOR EBX,EBX 0040109A XOR ESI,ESI 0040109C CMP BYTE PTR SS:[EBP-28],BL 0040109F JE SHORT MyCrackI.004010A8 004010A1 INC ESI (1) 004010A2 CMP BYTE PTR SS:[EBP+ESI-28],BL 004010A6 JNZ SHORT MyCrackI.004010A1 004010A8 XOR ECX,ECX 004010AA MOV EAX,ECX 004010AC CDQ ; EAX의값을 EDX-EAX 조합으로확장 (32->64) 004010AD IDIV ESI ; EDX-EAX를 ESI로나누어몫을 EAX에나머지를 EDX에저장 004010AF MOV AL,BYTE PTR SS:[EBP+EDX-28] 004010B3 XOR BYTE PTR SS:[EBP+ECX-18],AL 004010B7 INC ECX 004010B8 CMP ECX,0B 004010BB JL SHORT MyCrackI.004010AA 004010BD PUSH MyCrackI.00402070 004010C2 CALL DWORD PTR DS:[<&KERNEL32.GetModuleHandleA>] 004010C8 CMP EAX,EBX 004010CA JE MyCrackI.0040116F (2) 004010D0 LEA ECX,DWORD PTR SS:[EBP-18] 004010D3 PUSH ECX 004010D4 PUSH EAX 004010D5 CALL DWORD PTR DS:[<&KERNEL32.GetProcAddress>] 004010DB CMP EAX,EBX ; 주소번지가 NULL인지비교 ( 오류검사 ) 004010DD MOV DWORD PTR SS:[EBP+10],EAX ; 함수의주소번지를 wparam에저장 004010E0 JE MyCrackI.0040116F ; 오류시오류처리부분인 0040116F로이동 위의 (1) 번구간의코드를분석하면 Var_3에메모리주소 00402078번에저장된값을할당하는작업 을한뒤이값과변수 Var_2에 Edit2 편집상자에서얻은값을 XOR 연산을하게된다. 이때총 11번 [ 20/34 ]

의작업을하게되는데결과값은다시 Var_2에저장이된다. 이과정이 0040108B ~ 004010B8 번까지이다. 004010BB번에서 Var_2에저장된값을살펴보면 Edit2 편집상자에넣은문자열과 Var_3 에들어있는문자열을 XOR 시켜생성된문자열이들어가있게된다. Edit2편집상자에 information 을넣었을경우 MessageBoxA라는문자열이저장된다. 이후 (2) 번구간은 00402070번메모리번지에저장된 user32 문자열을스택에넣고 GetModuleHandleA 함수를호출한다. 이는 user32.dll 의핸들을얻기위한것으로핸들은 EAX 레지스터에저장된다. 세번째, 네번째줄은핸들을제대로얻지못하였을때의오류처리루틴이다. 다섯번째줄에서마지막줄까지는 GetProcAddress 함수를호출하는것으로함수의인자로필요한모듈의핸들과함수의이름을넣는데모듈의핸들은 GetModuleHandleA 함수를실행하고난뒤에 EAX에저장되어있고, 함수명은 Var_2 (SS:[EBP-18]) 에 MessageBoxA 로저장되어있으므로이를스택에넣고나서 CALL 명령을통해 GetProcAddress 함수를호출한다. GetModuleHandle과 GetProcAddress 의함수원형은다음과간다. HMODULE WINAPI GetModuleHandle( in_opt LPCTSTR lpmodulename); FARPROC WINAPI GetProcAddress( in HMODULE hmodule, in LPCSTR lpprocname); 즉, 위의과정을모두거치고난뒤 EAX 레지스터에는 GetProcAddress 함수의반환값인 MessageBoxA 의주소번지를저장하고있다. 여기서우리는두번째편집상자인 Edit2에들어갈문자열을추측하는과정이있는데이를어떻게추론해냈는지확인하지않고넘어왔다. 문자열 information이들어가야한다는것은위의코드분석과정에서 Edit2 편집상자의문자열과조합하여나온문자열 (Var_2 에저장된문자열 ) 이 user32.dll의 export table에저장되어있어야함을추론할수있다. 또한, 변환과정에서 0x0B번반복하여문자열의크기가 11글자임을유추할수있다. 그리고, 이중에서함수를호출할때사용되는인자의개수가분석한자료와일치하는 API를찾으면된다. PE Explorer를통해서살펴본 user32.dll 의 export table에존재하는함수는총 779개임을확인할수있다. [ 그림 2-6] user32.dll 의 Export 함수목록 [ 21/34 ]

004010E6 004010EB 004010EE 004010EF 004010F0 004010F1 004010F2 004010F4 004010F6 004010F9 004010FC 004010FD 004010FE 004010FF MOV ESI,MyCrackI.0040205C LEA EDI,DWORD PTR SS:[EBP-4C] MOVSD MOVSD MOVSD MOVSD MOVSW XOR EAX,EAX CMP BYTE PTR SS:[EBP-C],BL LEA EDI,DWORD PTR SS:[EBP-3A] STOSD STOSD STOSD STOSW 00401101 STOSB 00401102 MOV ESI,MyCrackI.0040204C 00401107 LEA EDI,DWORD PTR SS:[EBP-28] 0040110A 0040110B 0040110C 0040110D 0040110E MOVSD MOVSD MOVSD MOVSD MOV DWORD PTR SS:[EBP+C],EBX 00401111 JE SHORT MyCrackI.0040111F 00401113 INC DWORD PTR SS:[EBP+C] 00401116 MOV EAX,DWORD PTR SS:[EBP+C] 00401119 CMP BYTE PTR SS:[EBP+EAX-C],BL 0040111D 0040111F JNZ SHORT MyCrackI.00401113 XOR ESI,ESI 00401121 CMP BYTE PTR SS:[EBP-18],BL 00401124 JE SHORT MyCrackI.0040112D 00401126 INC ESI 00401127 CMP BYTE PTR SS:[EBP+ESI-18],BL 0040112B 0040112D 0040112F JNZ SHORT MyCrackI.00401126 XOR ECX,ECX MOV EAX,ECX 00401131 CDQ 00401132 IDIV ESI 00401134 MOV EAX,ECX [ 22/34 ]

00401136 MOVSX EDI,BYTE PTR SS:[EBP+EDX-18] 0040113B 0040113C 0040113F CDQ IDIV DWORD PTR SS:[EBP+C] MOVSX EAX,BYTE PTR SS:[EBP+EDX-C] 00401144 CDQ 00401145 IDIV EDI 00401147 XOR BYTE PTR SS:[EBP+ECX-28],DL 0040114B 0040114C 0040114F INC ECX CMP ECX,0F JL SHORT MyCrackI.0040112F 00401151 LEA EAX,DWORD PTR SS:[EBP-28] 00401154 PUSH EAX 00401155 LEA EAX,DWORD PTR SS:[EBP-4C] 00401158 PUSH EAX 00401159 CALL DWORD PTR DS:[<&KERNEL32.lstrcatA>] 0040115F PUSH EBX 00401160 PUSH MyCrackI.00402040 00401165 LEA EAX,DWORD PTR SS:[EBP-4C] 00401168 PUSH EAX 00401169 PUSH EBX 0040116A 0040116D CALL DWORD PTR SS:[EBP+10] JMP SHORT MyCrackI.00401181 위의역어셈블코드는 Edit1, Edit2 편집상자에입력된값이맞을경우메시지박스에출력할패스워드를 만들어서메시지박스로넣는과정을표현한것이다. 분석자료는추가작성하여올릴예정이며시험범위는현재분석된자료까지로제한할것이니참고바람. [ 23/34 ]

[ 별첨 1] 윈도우메시지 /* * Window Messages */ #define WM_NULL #define WM_CREATE #define WM_DESTROY #define WM_MOVE #define WM_SIZE 0x0000 0x0001 0x0002 0x0003 0x0005 #define WM_ACTIVATE /* * WM_ACTIVATE state values */ #define WA_INACTIVE 0 #define WA_ACTIVE 1 #define WA_CLICKACTIVE 2 0x0006 #define WM_SETFOCUS #define WM_KILLFOCUS #define WM_ENABLE #define WM_SETREDRAW #define WM_SETTEXT #define WM_GETTEXT #define WM_GETTEXTLENGTH #define WM_PAINT #define WM_CLOSE #define WM_QUERYENDSESSION #define WM_QUIT #define WM_QUERYOPEN #define WM_ERASEBKGND #define WM_SYSCOLORCHANGE #define WM_ENDSESSION #define WM_SHOWWINDOW #define WM_WININICHANGE 0x0007 0x0008 0x000A 0x000B 0x000C 0x000D 0x000E 0x000F 0x0010 0x0011 0x0012 0x0013 0x0014 0x0015 0x0016 0x0018 0x001A [ 24/34 ]

#if(winver >= 0x0400) #define WM_SETTINGCHANGE #endif /* WINVER >= 0x0400 */ WM_WININICHANGE #define WM_DEVMODECHANGE #define WM_ACTIVATEAPP #define WM_FONTCHANGE #define WM_TIMECHANGE #define WM_CANCELMODE #define WM_SETCURSOR #define WM_MOUSEACTIVATE #define WM_CHILDACTIVATE #define WM_QUEUESYNC 0x001B 0x001C 0x001D 0x001E 0x001F 0x0020 0x0021 0x0022 0x0023 #define WM_GETMINMAXINFO 0x0024 // end_r_winuser /* * Struct pointed to by WM_GETMINMAXINFO lparam */ typedef struct tagminmaxinfo { POINT ptreserved; POINT ptmaxsize; POINT ptmaxposition; POINT ptmintracksize; POINT ptmaxtracksize; } MINMAXINFO, *PMINMAXINFO, *LPMINMAXINFO; // begin_r_winuser #define WM_PAINTICON #define WM_ICONERASEBKGND #define WM_NEXTDLGCTL #define WM_SPOOLERSTATUS #define WM_DRAWITEM #define WM_MEASUREITEM #define WM_DELETEITEM #define WM_VKEYTOITEM #define WM_CHARTOITEM 0x0026 0x0027 0x0028 0x002A 0x002B 0x002C 0x002D 0x002E 0x002F [ 25/34 ]

#define WM_SETFONT 0x0030 #define WM_GETFONT 0x0031 #define WM_SETHOTKEY 0x0032 #define WM_GETHOTKEY 0x0033 #define WM_QUERYDRAGICON 0x0037 #define WM_COMPAREITEM 0x0039 #if(winver >= 0x0500) #define WM_GETOBJECT 0x003D #endif /* WINVER >= 0x0500 */ #define WM_COMPACTING 0x0041 #define WM_COMMNOTIFY 0x0044 /* no longer suported */ #define WM_WINDOWPOSCHANGING 0x0046 #define WM_WINDOWPOSCHANGED 0x0047 #define WM_POWER 0x0048 /* * wparam for WM_POWER window message and DRV_POWER driver notification */ #define PWR_OK 1 #define PWR_FAIL (-1) #define PWR_SUSPENDREQUEST 1 #define PWR_SUSPENDRESUME 2 #define PWR_CRITICALRESUME 3 #define WM_COPYDATA #define WM_CANCELJOURNAL 0x004A 0x004B // end_r_winuser /* * lparam of WM_COPYDATA message points to... */ typedef struct tagcopydatastruct { DWORD dwdata; DWORD cbdata; PVOID lpdata; } COPYDATASTRUCT, *PCOPYDATASTRUCT; [ 26/34 ]

// begin_r_winuser #if(winver >= 0x0400) #define WM_NOTIFY #define WM_INPUTLANGCHANGEREQUEST #define WM_INPUTLANGCHANGE #define WM_TCARD #define WM_HELP #define WM_USERCHANGED #define WM_NOTIFYFORMAT 0x004E 0x0050 0x0051 0x0052 0x0053 0x0054 0x0055 #define NFR_ANSI 1 #define NFR_UNICODE 2 #define NF_QUERY 3 #define NF_REQUERY 4 #define WM_CONTEXTMENU #define WM_STYLECHANGING #define WM_STYLECHANGED #define WM_DISPLAYCHANGE #define WM_GETICON #define WM_SETICON #endif /* WINVER >= 0x0400 */ 0x007B 0x007C 0x007D 0x007E 0x007F 0x0080 #define WM_NCCREATE #define WM_NCDESTROY #define WM_NCCALCSIZE #define WM_NCHITTEST #define WM_NCPAINT #define WM_NCACTIVATE #define WM_GETDLGCODE #define WM_SYNCPAINT #define WM_NCMOUSEMOVE #define WM_NCLBUTTONDOWN #define WM_NCLBUTTONUP #define WM_NCLBUTTONDBLCLK #define WM_NCRBUTTONDOWN #define WM_NCRBUTTONUP 0x0081 0x0082 0x0083 0x0084 0x0085 0x0086 0x0087 0x0088 0x00A0 0x00A1 0x00A2 0x00A3 0x00A4 0x00A5 [ 27/34 ]

#define WM_NCRBUTTONDBLCLK #define WM_NCMBUTTONDOWN #define WM_NCMBUTTONUP #define WM_NCMBUTTONDBLCLK 0x00A6 0x00A7 0x00A8 0x00A9 #define WM_KEYFIRST #define WM_KEYDOWN #define WM_KEYUP #define WM_CHAR #define WM_DEADCHAR #define WM_SYSKEYDOWN #define WM_SYSKEYUP #define WM_SYSCHAR #define WM_SYSDEADCHAR #define WM_KEYLAST 0x0100 0x0100 0x0101 0x0102 0x0103 0x0104 0x0105 0x0106 0x0107 0x0108 #if(winver >= 0x0400) #define WM_IME_STARTCOMPOSITION #define WM_IME_ENDCOMPOSITION #define WM_IME_COMPOSITION #define WM_IME_KEYLAST #endif /* WINVER >= 0x0400 */ 0x010D 0x010E 0x010F 0x010F #define WM_INITDIALOG #define WM_COMMAND #define WM_SYSCOMMAND #define WM_TIMER #define WM_HSCROLL #define WM_VSCROLL #define WM_INITMENU #define WM_INITMENUPOPUP #define WM_MENUSELECT #define WM_MENUCHAR #define WM_ENTERIDLE #if(winver >= 0x0500) #define WM_MENURBUTTONUP #define WM_MENUDRAG #define WM_MENUGETOBJECT 0x0110 0x0111 0x0112 0x0113 0x0114 0x0115 0x0116 0x0117 0x011F 0x0120 0x0121 0x0122 0x0123 0x0124 [ 28/34 ]

#define WM_UNINITMENUPOPUP #define WM_MENUCOMMAND #endif /* WINVER >= 0x0500 */ 0x0125 0x0126 #define WM_CTLCOLORMSGBOX #define WM_CTLCOLOREDIT #define WM_CTLCOLORLISTBOX #define WM_CTLCOLORBTN #define WM_CTLCOLORDLG #define WM_CTLCOLORSCROLLBAR #define WM_CTLCOLORSTATIC 0x0132 0x0133 0x0134 0x0135 0x0136 0x0137 0x0138 #define WM_MOUSEFIRST #define WM_MOUSEMOVE #define WM_LBUTTONDOWN #define WM_LBUTTONUP #define WM_LBUTTONDBLCLK #define WM_RBUTTONDOWN #define WM_RBUTTONUP #define WM_RBUTTONDBLCLK #define WM_MBUTTONDOWN #define WM_MBUTTONUP #define WM_MBUTTONDBLCLK 0x0200 0x0200 0x0201 0x0202 0x0203 0x0204 0x0205 0x0206 0x0207 0x0208 0x0209 #if (_WIN32_WINNT >= 0x0400) (_WIN32_WINDOWS > 0x0400) #define WM_MOUSEWHEEL 0x020A #define WM_MOUSELAST 0x020A #else #define WM_MOUSELAST 0x0209 #endif /* if (_WIN32_WINNT < 0x0400) */ #if(_win32_winnt >= 0x0400) #define WHEEL_DELTA 120 /* Value for rolling one detent */ #endif /* _WIN32_WINNT >= 0x0400 */ #if(_win32_winnt >= 0x0400) #define WHEEL_PAGESCROLL (UINT_MAX) /* Scroll one page */ [ 29/34 ]

#endif /* _WIN32_WINNT >= 0x0400 */ #define WM_PARENTNOTIFY #define WM_ENTERMENULOOP #define WM_EXITMENULOOP 0x0210 0x0211 0x0212 #if(winver >= 0x0400) #define WM_NEXTMENU // end_r_winuser 0x0213 typedef struct tagmdinextmenu { HMENU hmenuin; HMENU hmenunext; HWND hwndnext; } MDINEXTMENU, * PMDINEXTMENU, FAR * LPMDINEXTMENU; // begin_r_winuser #define WM_SIZING 0x0214 #define WM_CAPTURECHANGED 0x0215 #define WM_MOVING 0x0216 // end_r_winuser #define WM_POWERBROADCAST 0x0218 // r_winuser pbt // begin_pbt #define PBT_APMQUERYSUSPEND #define PBT_APMQUERYSTANDBY 0x0000 0x0001 #define PBT_APMQUERYSUSPENDFAILED #define PBT_APMQUERYSTANDBYFAILED 0x0002 0x0003 #define PBT_APMSUSPEND #define PBT_APMSTANDBY 0x0004 0x0005 #define PBT_APMRESUMECRITICAL #define PBT_APMRESUMESUSPEND #define PBT_APMRESUMESTANDBY 0x0006 0x0007 0x0008 [ 30/34 ]

#define PBTF_APMRESUMEFROMFAILURE 0x00000001 #define PBT_APMBATTERYLOW #define PBT_APMPOWERSTATUSCHANGE 0x0009 0x000A #define PBT_APMOEMEVENT #define PBT_APMRESUMEAUTOMATIC // end_pbt 0x000B 0x0012 // begin_r_winuser #define WM_DEVICECHANGE 0x0219 #endif /* WINVER >= 0x0400 */ #define WM_MDICREATE #define WM_MDIDESTROY #define WM_MDIACTIVATE #define WM_MDIRESTORE #define WM_MDINEXT #define WM_MDIMAXIMIZE #define WM_MDITILE #define WM_MDICASCADE #define WM_MDIICONARRANGE #define WM_MDIGETACTIVE 0x0220 0x0221 0x0222 0x0223 0x0224 0x0225 0x0226 0x0227 0x0228 0x0229 #define WM_MDISETMENU #define WM_ENTERSIZEMOVE #define WM_EXITSIZEMOVE #define WM_DROPFILES #define WM_MDIREFRESHMENU 0x0230 0x0231 0x0232 0x0233 0x0234 #if(winver >= 0x0400) #define WM_IME_SETCONTEXT #define WM_IME_NOTIFY #define WM_IME_CONTROL #define WM_IME_COMPOSITIONFULL 0x0281 0x0282 0x0283 0x0284 [ 31/34 ]

#define WM_IME_SELECT #define WM_IME_CHAR #endif /* WINVER >= 0x0400 */ #if(winver >= 0x0500) #define WM_IME_REQUEST #endif /* WINVER >= 0x0500 */ #if(winver >= 0x0400) #define WM_IME_KEYDOWN #define WM_IME_KEYUP #endif /* WINVER >= 0x0400 */ 0x0285 0x0286 0x0288 0x0290 0x0291 #if(_win32_winnt >= 0x0400) #define WM_MOUSEHOVER #define WM_MOUSELEAVE #endif /* _WIN32_WINNT >= 0x0400 */ 0x02A1 0x02A3 #define WM_CUT #define WM_COPY #define WM_PASTE #define WM_CLEAR #define WM_UNDO #define WM_RENDERFORMAT #define WM_RENDERALLFORMATS #define WM_DESTROYCLIPBOARD #define WM_DRAWCLIPBOARD #define WM_PAINTCLIPBOARD #define WM_VSCROLLCLIPBOARD #define WM_SIZECLIPBOARD #define WM_ASKCBFORMATNAME #define WM_CHANGECBCHAIN #define WM_HSCROLLCLIPBOARD #define WM_QUERYNEWPALETTE #define WM_PALETTEISCHANGING #define WM_PALETTECHANGED #define WM_HOTKEY 0x0300 0x0301 0x0302 0x0303 0x0304 0x0305 0x0306 0x0307 0x0308 0x0309 0x030A 0x030B 0x030C 0x030D 0x030E 0x030F 0x0310 0x0311 0x0312 #if(winver >= 0x0400) #define WM_PRINT 0x0317 [ 32/34 ]

#define WM_PRINTCLIENT 0x0318 #define WM_HANDHELDFIRST #define WM_HANDHELDLAST 0x0358 0x035F #define WM_AFXFIRST #define WM_AFXLAST #endif /* WINVER >= 0x0400 */ 0x0360 0x037F #define WM_PENWINFIRST #define WM_PENWINLAST 0x0380 0x038F #if(winver >= 0x0400) #define WM_APP #endif /* WINVER >= 0x0400 */ 0x8000 /* * NOTE: All Message Numbers below 0x0400 are RESERVED. * * Private Window Messages Start Here: */ #define WM_USER 0x0400 #if(winver >= 0x0400) /* wparam for WM_SIZING message */ #define WMSZ_LEFT 1 #define WMSZ_RIGHT 2 #define WMSZ_TOP 3 #define WMSZ_TOPLEFT 4 #define WMSZ_TOPRIGHT 5 #define WMSZ_BOTTOM 6 #define WMSZ_BOTTOMLEFT 7 #define WMSZ_BOTTOMRIGHT 8 #endif /* WINVER >= 0x0400 */ #ifndef NONCMESSAGES [ 33/34 ]

[ 별첨 2] [ 34/34 ]