security/리버싱핵심원리

TEB & PEB 정리

민사민서 2023. 4. 5. 20:59

TEB (Thread Environment Block)

- 프로세스에서 실행되는 스레드에 대한 정보를 담고 있는 구조체

[offset 0x0: NtTib]

- _NT_TIB 구조체 존재

- 0x0 offset의 ExceptionList = SEH (윈도우 OS 예외처리 메커니즘)의 시작주소

- 0x18 offset의 Self = _NT_TIB 구조체의 셀프 포인터 = TEB 구조체의 포인터

typedef struct _NT_TIB {
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID SubSystemTib;
    union {
    	PVOID FiberData;
        DWORD Version;
    };
    PVOID ArbitraryUserPointer;
    struct _NT_TIB *Self;
} NT_TIB, *PNT_TIB;

[offset 0x30: ProcessEnvironmentBlock]

- PEB(Process Environment Block) 구조체의 포인터

FS 세그먼트 레지스터와의 관계

- FS 세그먼트 레지스터는 현재 스레드의 TEB를 지시하는데 사용

- FS 레지스터는 'Segment Descriptor Table'의 index 값을 가지고 있고, FS가 indexing하는 Segment Descriptor는 실제 TEB 주소를 가리킨다

- FS:0 = FS 레지스터가 Indexing하는 Segment Descriptor가 가리키는 메모리의 시작 주소 = TEB 주소

=> FS:[0x0] = TEB.NtTib.ExceptionList = addr of SEH

=> FS:[0x18] = TEB.NtTib.Self = addr of TEB

=> FS:[0x30] = TEB.ProcessEnvironmentBlock = addr of PEB

 

PEB (Process Environment Block)

- 프로세스 정보를 담고 있는 구조체

- 접근 방법

# Method 1
MOV EAX, DWORD PTR FS:[0x30]

# Method 2
MOV EAX, DWORD PTR FS:[0x18]
MOV EAX, DWORD PTR DS:[EAX+0x30]

[offset 0x2 : BeginDebugged]

- 디버깅 중이면 1, 아니면 0이 세팅된다

[offset 0x8 : ImageBaseAddress]

- 프로세스의 ImageBase를 표시한다

[offset 0xc : Ldr]

- _PEB_LDR_DATA  구조체의 포인터

- +0xc의 InLoadOrderModuleList0x14의 InMemoryOrderModuleList0x1C의 InInitializationOrderModuleList 이렇게 세 가지 종류의 LIST_ENTRY 타입 양방향 연결 리스트가 존재

- 연결 리스트에는 _LDR_DATA_TABLE_ENTRY 구조체 정보가 저장된다

typedef struct _LDR_DATA_TABLE_ENTRY {
    PVOID Reserved1[2];
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2[2];
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
    UNICODE_STRING FullDllName;
    BYTE Reserved4[8];
    PVOID Reserved5[3];
    union {
    	ULONG CheckSum;
        PVOID Reserved6;
    };
    ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

- 프로세스에 로딩된 DLL 모듈마다 _LDR_DATA_TABLE_ENTRY 구조체가 하나씩 생성되고, 이들은 _LIST_ENTRY 연결 리스트들을 통해 연결된다

[offset 0x18 : ProcessHeap]

- HEAP 구조체를 가리키는 포인터

- HEAP 구조체의 Flags 멤버(+0xC)와 ForceFlags 멤버(+0x10)는 정상 실행 중일 때 각각 2와 0이다.

- 디버깅 중일때 이 값을이 변경된다

[offset 0x68 : NtGlobalFlag]

- 프로세스가 디버깅 중이면 0x70으로 값이 세팅된다