10.9(화) 이론-1

from Study/System 2007/10/14 14:55 view 18136
1. ReadProcessMemory

 - 프로세스간의 독립성은 보장되지만 디버깅을 위해 함수를 제공한다.
 - ReadProcessMemory, WriteProcessMemory

 - int 3( 브레이크 포인트 ), TF 레지스터 1 로 세팅하면 CPU가 한줄 단위로 읽게 된다.
 - 코드영역을 읽어와서 보여줄 수도 있다.( MinDbg, DebugActiveProcess ) 실행중인 프로세스와 연결!!
 - CreateProcess( option에 DEBUG_ONLY_PROCESS ) 를 준다.
 - WaitForDebugEvent 를 하면 DEBUG_EVENT에 정보가 들어가게 된다.

2. 컴파일 모드

  - Win32 Debug : 개발시, 실행오류체크와 관련된 메크로나 함수가 컴파일 대상에 포함된다.
  - Win32Release : 완성된 프로그램 일 경우 이 모드로 놓고 컴파일 해줌으로써 디버그 모드에서 수행되던 매크로나 함수는 컴파일 대상에서 제외되므로 보다 최적화된 코드가 탄생된다.

  - ASSERT 매크로
    1) Debug에서만 수헹, ASSET(조건식) 0 or 1
    2) 조건식이 거짓일 경우 ASSERT라는 이름의 Dialog박스를 출력하여 오류정보를 보여준다.

  - VERIFY 매크로
    1) Debug 모드에만 수행되며 ASSERT 와 동일한 매크로 이다.

  - TRACE 매크로
    1) Debug모드에서만 수행된다. 형식은 printf와 동일하며 Output 창에 출력된다.

  - OutputDebugString () == TRACE 괄호안의 문자열을 출력한다.

  - Dump()
    1) 디버그 모드에서만 수행한다.
    2) 특정개체에 저장된 데이타의 모든 항목을 Output 스크린상으로 전부 출력할 수 있는 코드를 추가가능.
Tag | ,

10.8(월) 이론-1

from Study/System 2007/10/14 14:03 view 20093
1. 세그먼트 레지스터와 GDT( global Descriptor Table )
  -
index address size access
0 1000 5k R/W
1 2000 3k R

  - Segment Register
    1) DS, CS 는 Table의 인덱스를 가리킨다.
    2) mov dword ptr DS[0x1000], 10  : DS레지스터리로부터 1000번지 이동 상대적주소.

2. Data Structure


사용자 삽입 이미지

  - TEB안에는 PEB를 가리키는 포인터가 있다. FS[ 주소 ] : TEB의 정보를 읽을 수 있는 레지스터!!
  - PEB(Process Enviroment Block) : 프로세스를 관리하기 위해 User Mode에 둔다.
  - 직접 접근이 가능하므로 조사하면 많은 정보를 볼 수 있다. ex) dt nt!_PEB ( WinDbg 를 활용하자! )

2. Kernel 상속을 활용한 리다이렉션( 표준출력을 Console창에서 다른곳으로 바꾸는 작업 )

  - STARTUPINFO를 활용한다. 잘 알아보면 하는일이 너무많다...

more..


  - Handle의 공유 문제 : Duplicate 는 떠있는 상태에서 복사해준다.
  - 상속은 이제 만들어진 것에서 유용하다. 부모에게 그대로 상속받는다면 똑같은 Handle이 생성..

  - Kernel Object는 기본적으로 비상속 모드이다 이를 SetHandleInfomation 으로 바꿔준다.
            HANDLE hRead, hWrite;
            CreatePipe( &hRead, &hWrite, 0, 1024 );
            SetHandleInformation( hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );

3. 프로세스 열거

  - User : Kernel32.dll ( ToolhelpAPI ) , ntdll.dll ( ZwQuerySystemInformation )
  - Kernel : EPROCESS - EPROCESS - EPROCESS -.. // 링크드리스트로 열거 되어 동기화 되고 있다.
 
  - kernel32.dll 은 NT4.0에서는 지원이 안된다. 대신에 PSAPI.dll 이 있다.

  - 프로세스 열거시 목록을 SnapShot 해둔다. ( 프로세스가 사라질 경우를 대비.. )
    // 프로세스의 목록을 메모리 어딘가에 보관(snapshot)해 둔다.
    HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );

4. 특권얻기

사용자 삽입 이미지

  - MSGINA.dll : 로그인창의 다이얼로그가 들어있다.
  - 사용자가 지나dll을 다시 만들어서 로그인 과정을 바꾸는 것도 가능하다.

  - Access Token에는 사용자의 권한이 기록되어 있다.
BOOL EnablePrimary( HANDLE    hProcess, // 권한을 부여할 프로세스
                    char*    pri,      // 권한을 나타내는 문자열
                    BOOL    bEnable   // 가능/불가능 여부
                    )
{

    HANDLE hToken;
    OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );

    // 문자열로 되어 있는 권한ID( LUID, 64비트 정수 )로 변경한다.
    LUID luid;
    LookupPrivilegeValue(
        ".", // PC이름
        pri, // 권한이름
        &luid ); // luid를 담을 변수

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;    // 갯수
    tp.Privileges[0].Luid = luid;    // 권한 ID
    tp.Privileges[0].Attributes= bEnable ? SE_PRIVILEGE_ENABLED : 0;

    return AdjustTokenPrivileges( hToken, 0, &tp, sizeof(tp), 0, 0 );
}
Tag | ,

10.5(금) 이론-Debuger,KO,TKO

from Study/System 2007/10/13 19:07 view 19124
1. Debuger

  - User 모드 디버거 -> VC 디버거
  - Kernel 모드 디버거 -> SoftIce, WinDbg

  - WinDbg 초간단 사용법
    1) Symbol path 에  SRV*C:\symbol*http://msdl.microsoft.com/download/symbols 추가!!
    2) Kernel Debugging 눌러서 Local 로 선택
    3) dt nt!_구조체명   : KMUTANT, EPROCESS, KSEMAPHORE 등등 // 구조체의 내용을 본다.

2. Kernel Object( KO )
 
  - OS가 동작하는 3가지 Object ( 내부적으로 구조체를 갖는다는 의미 )

CreateWindow
CreatePen
CreateFile
User Object GDI Object Kernel Object (KO)
윈도우 객체
핸들이 전역
Public of Process
다른 프로세스에서 접근하여 움직일 수 있다.
펜객체
핸들이 지역
내부에서만 사용가능~
파일 객체
상대적 핸들
Private to Process
다른 프로세스에서 쓰게 하지 못한다.

  - KO의 특징 : 40여가지의 구조체를 가지고 있다. 상대적(한정적)핸들을 가진다.
    1) 공통속성 : 보안, signal, 참조계수, 이름, LIST_ENTRY

  - 상대적 핸들의 개념

사용자 삽입 이미지

사용자 삽입 이미지

  - 모든 커널 Object 소유자는 OS 이다. 파일의 생성후 프로세스가 종료된다면 파일은 누가 관리해줘야 할까?
  - Table의 Index가 곧 핸들값이므로 KO는 복사 되었을때 인덱스값이 달라진다. 이를 상대적 핸들이라 한다.


 

Tag | ,

10.2(화) 이론-1

from Study/API 2007/10/13 15:36 view 27502
1. 메뉴바 => 팝업 메뉴 => 메뉴 아이템
 
  - 메뉴바도 하나의 윈도우기 때문에 구조체를 갖는다. ( MENUINFO )
  - 마찬가지로 팝업메뉴도 하나의 윈도우이기 때문에 구조체를 갖는다. ( MENUITEMINFO )
 
2. 적재 방법

  - 윈도우 클래스에 바로 등록한다. wc.lpszMenuName
  - CreateWindowEx 10번쨰 인자에 준다. HMENU( 핸들을 등록해준다. )
  - 윈도우 생성 후 SetMenu() GetMenu() 로 등록해준다.
  - 임의로 메뉴바를 추가 했을 때는 rc에서 아이디추가, 다음 가르킬 ID를 변경 해줘야 한다.

3. 메뉴윈도우가 부모에게 보내주는 메시지.

  - WM_INITMENU
  - WM_INITPOPUPMENU : 'v' 메뉴항목의 체크작업 해줄 수 있다.
  - WM_MENUSELECT : 메뉴설명을 상태방에 추가 할 수 있다.
  - WM_COMMAND : 메뉴를 선택 했을 때 메뉴의 메시지 처리함수에서 부모에게 메세지를 보내준다.

4. ModifyMenu

  - 최근 사용한 파일을 표현할 수도 있다.(추후구현) : AppendMenu, DrawMenuBar (레지스터리 참조)
  - 윈도우즈는 모든 구성요소를 구조체로 만든 Object-Based 이므로 구조체만 수정해주면 된다.

5. 메뉴 OWNERDRAW

  - 색변경
    1) WM_CTLCOLOR 에서 처리한다.
    2) OWERDRAW : 메뉴, 기본컨트롤 - 결국 UI만 대신 그려주는 역할. 동작은 클래스내부에서 처리한다.
    3) CustomDraw : 공용 컨트롤에 적용

  - MF_OWNERDRAW : 속성으로 변경을 한다. ( ModifyMenu )
  - WM_MEASUREITEM : 그릴 항목의 크기를 지정해달라는 MSG를 OS가 보낸다. 열릴때 최초 1회발생
  - WM_DRAWITEM : 사용자가 그려 주라는 메시지로 HDC(lParam) 와 기타 모든 정보가 넘어온다.
  - LPDRAWITEMSTRUCT 현재 state를 조사할 수 있다.

6. Context Menu

  - WM_RBUTTONUP 생성 => 처리 하지 않는 메시지는 DefProc로 보내줘야 한다.
  - WM_CONTEXTMENU
    1) Context메뉴 리소스 제작시 _MENU로 이름을 주어 구분한다. OWNERDRAW를 적용받지 못한다.

  - 스크린 좌표로 넘어온다.( 클라이언트좌표로 변환 )
  - WM_COMMAND에서 명령을 처리하면 된다.


7. Dialog 공용 컨트롤 ( #32770 에 등록 )

  - DialogBox() => CreateWindow를 내부적으로 호출한다. 자기만의 메시지 루프를 가진다.
  - DlgProc() 사용자정의 함수로 메시지를 전달 해주게 된다.
  - 전달해 주는 메시지는 정해 져있다.( WndProc 과 엇비슷 )
  - WM_INITDIALOG : WM_CREATE를 수행한 후에 초기상태를 정하라는 메시지!!!
  - 특정키를 막거나 메시지를 가로 채려면 여기서 하는게 아니라 서브클래싱 해줘야 한다.!!

사용자 삽입 이미지

DlgProc()
    EndDialog() // 내부적으로 미리 약속되어 있는
                      // 탈출작업을 한다.

WndProc()
  : DialogBox : Blocking 된다.

DialogBox()
1) CreateWindowEx() 다이얼로그 생성
2) EnableWindow( 부모, FALSE ) 부모 블럭
3) WM_INITDIALOG 발생
4) 메시지 루프 Dispatch로 메시지 받아옴
5) 부모 Enable 후 다이얼로그 파괴

4)부가설명 - 메시지 박스가 내부적으로 메시지 루프를 갖는것과 같다. 이때 Dispatch 에서 Message를 DlgProc으로 보내준다.

- DialogBox는 내부적으로 DialogBoxParam을 호출 한다 lParam을 0L로 주는것에 불과한 매크로이다!! 호환성위해..





8. Dialog값 꺼내오기

  - 핸들을 알아야 윈도우의 값을 얻어오므로 ID로부터 핸들을 얻어야 한다. GetDlgItem( ID ) 로 얻어온다!!
  - GetDlgItem + GetWindowLong = GetDlgItemText  해당 컨트롤로부터 int값을 buf로 읽어 올수 있다.

  - DialogBoxParam() : lParam으로 특정데이터를 넘길 수 있다. 전역변수 대신에 포인터로 접근하는것!!
  - 이를 사용하면 Dialog에서 사용한 컨트롤의 값들을 lParam에 저장해두면 부모가 값을 읽어오는것이다.

9 모달리스
 
  - 생성과정 : DialogBox 를 CreateDialog 로 생성 해줘야 한다.
  - 파괴는 EndDialog =>  DestroyWindow() 취소버튼을 눌렀을때 파괴~
  - 이방식은 DlgProc() 에서 사용자정의 메시지를 WndProc() 로 보내 작업을 수행하도록 할 수 있다.
  - 메시지 루프가 없으므로 부모윈도우가 같은 메시지 루프를 사용한다.
  - 그러므로 Dialog에서 특정키등을 가로채서 모달리스에 전달 하고자 할 떄는 메시지루프를 수정한다.
        if ( !IsWindow( g_hDlg ) || !IsDialogMessage( g_hDlg, &msg ))
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
Tag | ,

10.1(월) 이론-2

from Study/API 2007/10/13 14:08 view 28943
1. WndProc 에서 hInstancs를 얻어내는 법

  - 전역 변수에 저장해놓고 사용하기.
  - 결국 실행파일의 주소이므로 GetModuleHandle( 0 ) 으로 얻기
  - 윈도우 Object에서 얻기. GetWindowLong( HWND, GWL_HINSTANCE )
  - WM_CREATE의 lParam에서 얻기

2. 커서 메세지
  - WM_SETCURSOR에서 모양을 바꾸자.

3. 메뉴

  - API는 HANDLE을 가지고 있다면 모두 변경 가능하다.
  - 메뉴의 HANDLE을 구할 수 있다. ( GetMenu, GetSystemMenu )
  - GetSystemMenu : FALSE는 얻어온다 HANDLE, TRUE는 초기상태로 메뉴를 되돌린다.
  - 시스템 메뉴 ID등록 : 0xF000 ->이하는 시스템메뉴 ID.
  - 메뉴 ID가 있는 하위 4비트를 0으로 하자.

4. 트래이로 숨기기
  - SC_CLOSE 가 발생했을때 트래이로 숨기면 된다.
  - TASKBAR윈도우에서는 사용자가 지정한 CALLBACKMESSAGE로 발생한 이벤트를 보내준다.
  - WM_USER+100 으로 지정했다면, wParam = Id, lParam = Message 가 들어온다.

Tag | ,

10.1(월) 이론-1

from Study/API 2007/10/13 13:49 view 25914
1. 데이타 Drag : 다른 프로세스간의 데이타를 서로 드래그 하기 __ OLE,COM 사용
  - 어렵다. -_-..차후에 공부함.

2. 파일 Drag    : 파일을 Drag해서 열기
  - WS_EX_ACCEPTFILES __ 확장 스타일로 주거나
  - shellapi.h 의 DragAcceptFiles 함수를 사용한다.

3. WM_DROPFILES
  - 윈도우창에 파일이 드래그 되었을 떄 발생한다.
  - SetCaputre, DragQueryFile, DragFinish 를 이용하여 메모리에 올라온 이름을 얻는다.

4. 리소스 원리

  - 리소스 ID를 알기 위해선 #include "resource.h" 를 해야 한다.
  - 완성된 프로그램의 PE헤더 .rsrc 에는 리소스가 있는데 이를 꺼내올 수 있다.
  - Loadxxx(모듈의주소)

5. ICON 여러가지

  - LoadIcon() 기본크기 32x32를 읽어온다. LoadImage() 로 다양한 크기를 로드 할 수 있다.
  - DrawIcon 으로 기본크기 32x32를 그린다. DrawIconEx 로 크기를 지정해서 그릴 수 있다.
 
  - SetClassLong으로 클래스 자체를 바꾼다. 이후 바뀐 클래스에 로드된 윈도우는 아이콘이 바뀐다.
  - SendMessage 현재 윈도우의 스타일만 바꾸고자 할 떄 쓰인다.




Tag | ,

9.19(수) 이론-1

from Study/API 2007/10/10 19:20 view 19003
1. 무효화 영역과 WM_PAINT

  1) 무효환 영역 ? 윈도우가 다른 윈도우에 가려 있다가 앞으로 나올 때 다시 그려야 하는 영역
  2) size 조절시 윈도우 전체가 무효화 : 윈도우 클래스에 CS_HREDRAW | CS_VREDRAW style을 줘야함.
  3) InvalidateRect() : 사용자가 윈도우의 특정영역을 무효화 한다. TRUE or FALSE(강추!!)

2. 무효화 영역 발생시 OS가 하는일

  1) WM_PAINT 메시지를 전달한다.( OS가 Application에 전달, App는 무효화영역을 기억해야 한다. )
  2) 메시지 Q에  QS_PAINT 형태로 flag가  1일때 GetMessage 로 꺼내온다.
  3) ValidateRect 나 BeginPaint 로 유효화영역으로 바뀌게 되면 flag 는 0 이된다.
  4) BeginPaint : Caret 숨김, 유효화 영역.. 기본적으로 해야 하는것들을 해준다.
 
3. 화면떨림방지( Flicker 방지 )
 
  1) RECT rc = ps.rcPaint;  // 무효화 영역의 크기를 받아서 꼭 필요한 곳만 그릴 수 있다.
  2) 더블 버퍼링 ( 좌표 대신에 비트맵으로 보관해 놓는다. ) ***해결책**
  3) 무효화 영역을 꼭 지워야 할까 ?
    - wc.hbackground = 0; // 윈도우 클래스의 백그라운드색을 0으로 해놓는다.
    - 배경을 지우라는 메시지를 가로채서 WM_ERASEBKGND 아무일도 못한게 한다.

4. 알아 둘 것.

  1) 항상 윈도우에 보여주고 싶다면 WM_PAINT 내에서 호출한다.
  2) 출력을 Update 하고 싶다면 무효화 영역을 만들어야 한다. InvalidateRect
  3) 화면에 즉시 뿌리고 싶다면
    - UpdateWindow() => if( msgQ has WM_PAINT ) WndProc( HWND, WM_PAINT )


1. GDI Object
 
  1) 생성 => 선택 => 선택해지 => 파괴 의 순서를 지켜야 한다.
  2) SelectObject( Createxxx() )
  3) DeleteObject( SelectObject() )
  4) StockObject 는 OS가 미리 만들어 놓은 Object 이므로 GetStockObject로 얻은 것은 파괴하면 안된다!!!
 
2. Region

  1) 영역 생성             CreatexxxRgn()   // 다양한 모양이 생성가능
  2) 영역 합치기          CombineRgn()     // RGN_AND,RGN_COPY 등 다양한 모드 지원
  3) 적용 하기             SetWindowRgn()
  4) 영역 해지             DeleteObject()

3. 그리기 모드

  1) 선의 색은 배경색과 DC의 PEN의 색을 비트연산하여 나오는 것이다.( | , & )
  2) a | 흰색(1111)  => 흰색 , a & 흰색(1111) => a  // 어떤 연산을 할 것인지를 정하는게 그리기모드의 핵심!!
  3) R2_NOT 은 bending 효과를 구현 할 수 있다. 선잡고 움직이기.

2007/10/10 - [Study/API] - 9.19(수) 실습-1
2007/10/10 - [Study/API] - 9.19(수) 실습-2

Tag | ,

9.18(화) 이론-1

from Study/API 2007/10/10 17:54 view 20789
1. Mouse, 키보드에 대한 이야기

- RIT는 항상 자기와 연결된 Thread의 ID를 보관하고 있는데 이를 Foreground Thread 라고 한다.(하나존재)
- 마우스 : WindowFromPoint , 키보드 : Foreground Thread로 전달한다.( PostThreadMessage(ID) )
- RIT는 쓰레드 ID만 보고 ID에 해당하는 메시지 Q에 전달하면 GetMessage 로 메시지를 꺼내 DispatchMessage 를 사용해서 해당 WndProc에 메시지를 보낸다. 현재 포커스에 입력되게 된다.

- Activate(활성창)은 최상위 윈도우가 관리하고, Focus는 Top-leve 윈도우단위로(스레드) 관리하게 된다.

- 키보드 => Scan Code:Hardware => 드라이버에서 가상키코드로 변환(대소문자x) => WM_KEYDOWN  => TranslateMessage 가상키코드를 분석하여 대소문자를 구분시켜준다.=> Focus에 입력

- 키보드 메시지 종류 ( wparam : 가상키코드, lparam : 스캔+a )
  1) WM_KEYDOWN
  2) WM_KEYUP
  3) WM_SYSKEYDOWN  (ALT
  4) WM_SYSKEYUP
  5) WM_SYSCHAR
- CTRL+ALT+DEL, ALT+TAB.. RIT가 시스템으로 넘겨주게 된다.

- TranslateMessage : 가져온 메시지가 키보드 메시지이고 wParam의 키가 문자키라면 WM_CHAR메세지를 Q에 넣는다.!!
- 문자키 : WM_CHAR,      기능키 : WM_KEYDOWN

- 키보드 상태조사 ( 상위 8비트 : 일반키 상태 , 하위 8비트 : 상태키 )
  1) GetKeyState( VK_SHIFT ) & 0xFF00 ) // 시프트와 왼쪽 마우스클릭조사
      : 마우스, 키보드 메시지 처리를 한다. 현재 키보드상태를 조사한다.
  2) GetAsyncKeyState( 가상키코드 )

- 캐럿은 개별 스레드자원이므로 Focus를 얻을 때 생성, 잃을 때 파괴 해줘야 한다.
   : 감추고 파괴해야 Caret 내부에 있는 문자가 깨질 우려가 없다.
- 커서는 시스템 자원이므로 관여 할 필요 없다.

2007/10/10 - [Study/API] - 9.18(화) 실습-1
Tag | ,

9.17(월) 이론-4( 종료과정이해 )

from Study/API 2007/10/10 16:15 view 17009
1. 종료과정 이해하기


- 윈도우가 종료 하기 바로 전에 해야 할일은 주로 WM_CLOSE 메시지 에서 처리한다.!!
Tag | ,
1. 마우스 캡쳐

- 일반적으로 마우스 메시지는, 메시지가 발생할 당시 커서의 아래 있는 윈도우에게 전달된다. 하지만 SetCapture()함수를 사용하므로서 이런 행동을 변경 할 수 있다.
- 특정 윈도우가 SetCapture() 함수를 사용해서 마우스를 캡쳐할 경우, 모든 마우스 메시지는 마우스를 캡쳐한 윈도우에게로 전달된다.

2. 마우스 캡쳐하기
- 마우스 캡쳐는 아래의 3가지 경우에 해지된다.
  1) RealeaseCapture() 를 호출 한 경우
  2) 다른 윈도우가 마우스를 캡쳐한 경우
  3) 사용자가 다른 스레드가 만든 윈도우를 클릭 한 경우
- 마우스 캡쳐가 해지될 경우, 캡쳐를 잃은 윈도우에 WM_CAPTURECHANGED 메시지가 전달된다.
이 때 lParam에는 새롭게 마우스를 캡쳐 한 윈도우의 핸들이 들어 있다.

3. 마우스가 캡쳐 되어 있을 경우 WM_NCHITTEST, WM_SETCURSOR 메시지는 발생되지 않는다.
4. 예제 코드( 다른 윈도우 캡쳐하기 )

more..




1. 마우스 좌표
- 어디를  기준으로 보냐에 따라서 스크린 좌표계, 윈도우 좌표계, 클라이언트 좌표계로 나눌수 있다.

- ClinetToScreen | ScreenToClient ( 두개 외에 나머지 함수 만들기 )
void
WindowToScreen(HWND hwnd, POINT* Point)
{
      RECT Rect;
      GetWindowRect( hwnd, &Rect );
      Point->x = Point->x + Rect.left;
      Point->y = Point->y + Rect.top;
}
void ScreenToWindow(HWND hwnd, POINT* Point)
{
      RECT Rect;
      GetWindowRect( hwnd, &Rect );
      Point->x = Point->x - Rect.left;
      Point->y = Point->y - Rect.top;
}
void WindowToClient(HWND hwnd, POINT* Point)
{
      WindowToScreen( hwnd, Point );
      ScreenToClient( hwnd, Point );
}
void ClientToWindow(HWND hwnd, POINT* Point)
{
      ClientToScreen( hwnd, Point );
      ScreenToWindow( hwnd, Point );
}
Tag | ,