'System'에 해당되는 글 27건

  1. 2007/10/14 10.8(월) 이론-1
  2. 2007/10/14 10.8(월) 실습-2
  3. 2007/10/14 10.8(월) 실습-1
  4. 2007/10/13 10.5(금) 이론-CreateProcess
  5. 2007/10/13 10.5(금) 이론-Debuger,KO,TKO
  6. 2007/10/13 10.5(금) 이론-함수호출 과정
  7. 2007/10/09 System - Object Table

10.8(월) 이론-1

from Study/System 2007/10/14 14:03 view 19977
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.8(월) 실습-2

from Study/System 2007/10/14 12:55 view 20021
1. nativeAPI.h 와 ntdll.lib 사용 ( 각 프로세스의 핸들카운트와 스레드시작주소 출력~ )

more..


Tag | ,

10.8(월) 실습-1

from Study/System 2007/10/14 12:18 view 19177
1. TEB에서 값 얻어오기

more..


2. 커널 상속( 콘솔 창에 출력을 edit박스로 받기 )

more..


3. Pipe를 사용한 콘솔창 출력을 에디트 박스로~( 한줄 씩 읽어보기 )

more..


3. 실행중인 프로세스 열거해보기

more..


4. pid 를 사용한 모듈 열거

more..


5. PC끄는 권한 얻어 와서 종료시키기

more..

Tag | ,

10.5(금) 이론-CreateProcess

from Study/System 2007/10/13 20:17 view 22929
1. CreateProcess ~ ko상태

사용자 삽입 이미지
 
  - A.exe에서 CreateProcess로 계산기를 생성함.
    1) &si로 STRARTUPINFO정보를 넘기고 &pi 로 PROCESS_INFORMATION를 얻어온다.
    2) pi에는 &pko(0x8100,000) 와 &tko(0x8200,0000) 를 얻어 올수 있다.(id도 얻어옴)
    3) 생성된 계산기의 참조계수는 부모와 자신이 참조하게 되므로 2가 된다.
    4) 이 때 calc.exe를 닫는다면 참조계수는 1이 되면서 메모리 Leak이 발생한다.
    5) 관리하는 구조체가 남아있는 상태가 되는 것이다.(좀비상태) CloseHandle을 사용하여 죽여야 한다.
    6) 그래서 프로세스의 생성에 성공했다면 참조계수를 꼭 1로 만들어 줘야 한다.(메모리 Leak방지)

  - 다른 프로세스의 종료코드 확인 ; GetExitCodeProcess()
  - PKO 내부에 ExitStatus 에서 이값을 저장하고 있다.
    1) Main_CRT_STARTUP -> 어떤한것 -> main -> return 하면 ExitStatus에 저장.
    2) STILL_ACTIVE (0x103) : 계산기가 살아있다면 가지고 있는값이다!!!

  - 프로세스 강제 종료 : TerminateProcess()
    1) 비동기 함수. 바로 종료되었는지를 확신 하지 못한다.
    2) Process 는 KO의 signal에 상태를 저장하고 있는데 non-signal은 살아있다. signal은 죽었을때 발생.
    3) WaitForSingleObject 로 KO가 signal 이 될때까지 대기 해주면 동기화 할 수 있다.




2. HWND VS ID

  - GetWindowProcessThreadId로 hwnd로 부터 pid를 얻어 낼 수 있다.
  - hwnd로는 대상윈도우에 접근 할려고 한다면 이는 상대적이므로 에러가 발생한다.
  - 하지만 pid는 시스템 전체에서 유니크하기 때문에 접근이 가능하다.
  - pid로 대상윈도우의 HANDLE을 얻기 위해선 OpenProcess를 사용하여 PKO->ObjectTable에 등록해준다.
  - 윈도우의 핸들 => 프로세스ID => 프로세스핸들 얻어서 제어 일종의 공식??

3. 프로세스의 핸들을 얻을 때는 필요한 권한만 요구해야 한다.( 제한된 권한까지 열려고 할땐 에러남 )
  // ALL은 너무 많은 권한
  HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, 0, pid );
  // 최소 요구의 원칙 - 필요한 권한만 요구하자.****꼭 필요한것만 요구하자.
            HANDLE hProcess = OpenProcess(
                PROCESS_TERMINATE | SYNCHRONIZE,    // 죽이고 | wait 할수 있는 권한
                0,
                pid
                );

Tag |

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

from Study/System 2007/10/13 19:07 view 19013
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.5(금) 이론-함수호출 과정

from Study/System 2007/10/13 17:37 view 19335
1. 함수의 원리
  - USER 레벨
    1) exe 에서 CreateFile() 호출(kernel32.dll 에 있음 - 시스템함수)
    2) kernel32.dll 에서 내부적으로 NtCreateFile 호출( ntdll.dll 에 있음 )
    3) ntdll.dll 에서 기계어 코드를 수행한다.
mov    eax  서비스번호 5
mov    edx  스택주소
Int      2E        // 2E핸들러는 인터럽트를 사용하여 kernel 모드로 온다. eax를 확인하여 함수 호출

  - 보호모드 , 특권 레벨
    1) ZWCreateFile -> OS가 제공해주는 함수를 수행한다.
    2) SSDT ( System Service Dispatch Table )   정리 잘해 놓은 문서~
서비스 번호 함수 포인터
1  
2  
3  
4  
5 ZWCreateFile

  - Windows에서 파일을 열기 위해선 CreateFile을 호출해야 한다.
    1) SSDT Hooking 을 이용하여 이러한 함수의 호출을 막게 된다면 파일을 생성을 막을 수 있다.
    2) Native API는 도움말을 제공하지 않는다. !  포함헤더와 사용법은 다른 자료들을 참고!
    3) 디바이스 드라이버를 만들어야 SSDT를 후킹하여 접근할 수 있다.
    4) 프로세스 열거와 같은 기능은 Native까지 내려가야 한다.( 자세한 정보 표현 )

Tag |

System - Object Table

from Study/API 2007/10/09 17:09 view 18115
출처 : -_-..홈페이지가 폐쇠됨..
// 테이블 3개가 존재한다는 말은 2000 구조같은데... xp는 어떨지...

Win32 개발자들은 핸들이 뭔지는 알고 있을 것이다.

 그리고 이 핸들이 윈도우핸들(HWND)이 아님을 알고 있을것이다. 이 핸들이란건 특정 동작을 하기 위한 핸들링 용도로 쓰이고 있으며 대표적으로 파일을 다루는 WINAPI인 CreateFile(), ReadFile, WriteFile()함수들을 예로 들어 볼 수 있다.
 
 CreateFile()함수 성공시에 리턴값으로 핸들을 받게 되는데 이 핸들은 나중에 특정 파일을 핸들링 하기 위해 그 정보를 유지 해야 하는데 그 정보는 커널영역에 오브젝트 형태로 존재하게 되며 보통은 커널 오브젝트라고 부른다.

그럼 핸들값이 의미하는 숫자는 무엇일까?
이 핸들값은 커널오브젝트를 찾기 위한 일종의 인덱스 역활을 하는 값이다.
밑에 그림을 보도록 하자.



 위 그림은 유저영역에 존재하는 HANDLE을 통해 실제 객체를 나타내는 커널 오브젝트를 찾아가는 그림이다. 그림에선 중간에 HANDLE TALBLE이란게 존재하여 핸들값을 핸들테이블에서 인덱스로 사용하여 커널 오브젝트의 포인터를 찾는다.

자 이제 핸들테이블에 대해 알아보자.

핸들테이블이란?
 현 프로세스에서 생성된 핸들들에 대해서 커널 객체를 찾아가기 위한 인터페이스 역할을 하는 배열 형태로 된 테이블 영역이다. 이 핸들 테이블은 프로세스당 하나가 할당되며 프로세스간 독립적으로 핸들 테이블을 관리하게 되는데 우리가 CreateFile()로 생성된 핸들은 CloseHandle()를 사용하지 않고 프로세스를 죽였을때 운영체제는 이 핸들테이블에서 할당된 정보를 보고 모든 핸들을 반환하게 된다.

밑에 그림은 객체의 포인터를 찾기 위한 핸들테이블 구조를 보여준다.




 핸들테이블은 세개의 영역이 존재하는데 Top, Middle, entry가 존재함을 그림을 통해
알수가있다.
 그럼 위 테이블 구조를 어떤식으로 접근하여 실제 커널 오브젝트를 찾을 것인가? 아까 핸들값이 인덱스 역할을 하는 값이라고 설명하였다. 이 핸들값을 바이트 단위로 3등분 한후 핸들 테이블의 각 레벨의 배열을 인덱스로 사용하고 찾아간다.

밑에 그림은 핸들값이 0x4일때 이걸 세등분 한 후 핸들 테이블을 인덱스 삼아
실제 오브젝트를 찾아가는 그림이다.




 핸들값은 상위 6비트와 하위 2비트는 핸들테이블을 인덱싱하는 부분에선 해당되지 않는 비트이며 중간에 있는 총 3개의 8비트가 우리가 커널 오브젝트를 찾기 위한 핸들테이블을 접근하는 인덱스 번호가 되겠다.

 Table ptr은 Top레벨의 주소를 가리킨다.여기서부터 핸들값의 인덱스가 적용된다. 우리가 보고자 하는 0x4값은 각각 Top:0, Mid:0, Entry:1값을 가진다. 핸들 테이블에 이 값들을 적용하면 Top[0], Mid[0], Entry[1]이 되며. 처음 Top[0]에는 Mid의 첫번째 배열 주소를 가지키며 Mid[0]은 Entry의 주소를 가리키고 있다. 마지막 Entry는 실제 커널 오브젝트를 가리키는 주소를 가지고 있게된다.

코드로 함 살펴보기로 하자.

lkd> dt nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS

   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE

 커널에서 프로세스를 표현하는 EPROCESS에 보면 _HANDLE_TABLE ObjectTable가 존재한다.이 필드는 HANDLE_TABLE이란 구조체의 포인터를 가리키며 이 필드가 실제 핸들 테이블의 정보를 가지고 있는 셈이다. 윈도우 XP에서 ObjectTable의 위치는 0x0c4로 되어있다.

자 이제 HANDLE_TABLE의 구조를 살펴 봐야 한다.

lkd> dt nt!_HANDLE_TABLE
   +0x000 TableCode        : Uint4B
   +0x004 QuotaProcess     : Ptr32 _EPROCESS
   +0x008 UniqueProcessId  : Ptr32 Void
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO
   +0x02c ExtraInfoPages   : Int4B
   +0x030 FirstFree        : Uint4B
   +0x034 LastFree         : Uint4B
   +0x038 NextHandleNeedingPool : Uint4B
   +0x03c HandleCount      : Int4B
   +0x040 Flags            : Uint4B
   +0x040 StrictFIFO       : Pos 0, 1 Bit

 대충 보면 몇몇 필드는 변수명으로 그 의미를 파악할 수 있다. 여기서 HandleCount는 현재 프로세스에 할당된 핸들 총갯수 즉 핸들 테이블에 기록된 핸들의 정보수를 나타낸다.

UniqueProcessId는 이 핸들 테이블을 소유한 프로세스의 ID를 뜻하며 실제적인 핸들 테이블을 나타내는 Table 필드가 우리가 알고자 하는 핸들 테이블을 가리키는 필드이다.

lkd> dt nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : Ptr32 Void
   +0x000 ObAttributes     : Uint4B
   +0x000 InfoTable        : Ptr32 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Value            : Uint4B
   +0x004 GrantedAccess    : Uint4B
   +0x004 GrantedAccessIndex : Uint2B
   +0x006 CreatorBackTraceIndex : Uint2B
   +0x004 NextFreeTableEntry : Int4B

HANDLE_TABLE_ENTRY 구조체는 커널 오브젝트를 가리키는 Object필드와 핸들테이블 액세스 관련 필드인 GrantedAccess로 구성되어 있으며 Object가 OBJECT_HEADER를 가리키며 OBJECT_HEADER + OBJECT BODY 형태로 되어있다. 구조는 밑에와 같이 생겼으며 Body로 된 부분은 커널 객체마다 다른 구조로 되어 있다.

lkd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Type             : Ptr32 _OBJECT_TYPE
   +0x00c NameInfoOffset   : UChar
   +0x00d HandleInfoOffset : UChar
   +0x00e QuotaInfoOffset  : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void
   +0x018 Body             : _QUAD

 이 Body부분은 운영체제에 지시한 특정 명령에 동작을 나타내는 정보를 가지고 있는 실제 커널 오브젝트를 뜻한다.
 이 객체는 CreateFile()과 같은 커널에서 수행되어야 될 명령을 오브젝트 형태로 커널에서 관리하기 위해서 만들어진 구조체이며 유저영역에선 핸들을 사용하여 커널 오브젝트에 접근하게 된다.
 커널오브젝트는 스스로 제거될 수 있도록 참조 개수를 유지 하게 되는데. HandleCount, PointerCount란 필드를 통해서 관리된다. HandleCount는 우리가 CreateFile()로 생성되었을때 리턴된 핸들의 갯수를 뜻하며 PointerCount는 핸들이 아닌 직접 객체의 포인터를 얻어왔을때 증가하게된다. 커널에선 ReferenceObjectByPointer(), ObDereferenceObject() 사용시에 PointerCount가 증감된다.



Tag |