Win32 스레드 정보 블록
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
Win32 스레드 정보 블록(TIB)은 윈도우 운영체제에서 각 스레드에 대한 정보를 담는 자료 구조이다. TIB는 32비트(x86) 시스템에서는 FS 세그먼트 레지스터, 64비트(x64) 시스템에서는 GS 세그먼트 레지스터를 통해 접근하며, 스레드별 예외 처리 체인, 스레드 로컬 스토리지(TLS) 등에 대한 포인터를 포함한다. TIB는 스택 정보, GDI 정보, Wow64 관련 정보, 예외 코드 등 다양한 정보를 저장하며, 스택 베이스, 스택 제한 등의 필드를 통해 스택 관리에 필요한 정보를 제공한다. TIB는 인라인 어셈블리 또는 내장 함수를 사용하여 접근할 수 있으며, 윈도우 SDK를 통해 NtCurrentTeb 함수를 사용하여 현재 스레드 정보 블록의 주소를 얻을 수 있다.
더 읽어볼만한 페이지
- 스레드 - 멀티스레딩
멀티스레딩은 프로세스 내에서 여러 스레드를 동시 실행하여 처리 능력을 향상시키는 기술로, 응답성 향상과 자원 공유 등의 장점이 있지만, 자원 간섭과 소프트웨어 복잡성 증가 등의 단점도 존재하며, 다양한 모델과 구현 방식, 스레드 스케줄러, 가상 머신 활성화 가능성 등을 고려해야 한다. - 스레드 - 동시 멀티스레딩
동시 멀티스레딩(SMT)은 슈퍼스칼라 구조 기반으로 한 클럭 사이클 내에 여러 스레드의 명령어를 동시에 실행하여 CPU 자원 활용률을 높이는 기술이지만, 자원 경합, 성능 저하, 보안 취약점 등의 단점도 있으며, 인텔 하이퍼 스레딩이 대표적이다. - 마이크로소프트 API - 윈도우 API
윈도우 API는 마이크로소프트 윈도우 운영 체제에서 응용 프로그램이 시스템 기능에 접근하도록 돕는 인터페이스 집합이며, 다양한 버전으로 발전해 왔고, 현재 Win32가 널리 사용되며, 유연성을 제공하지만 복잡하다는 단점을 보완하기 위해 다양한 래퍼 라이브러리가 개발되었다. - 마이크로소프트 API - WinFS
WinFS는 마이크로소프트가 개발한 파일 시스템으로, 검색 기능 내장 및 메타데이터 관리를 통해 데이터 관리 효율성을 높이는 것을 목표로 했으나 별도 제품으로 출시되지는 못하고 핵심 기능들이 윈도우 비스타 이후 기술에 통합되었다.
Win32 스레드 정보 블록 | |
---|---|
개요 | |
유형 | 데이터 구조 |
운영체제 | 마이크로소프트 윈도우 |
설명 | 스레드 관련 정보를 저장하는 데이터 블록 |
구조체 정보 | |
정의 위치 | winternl.h |
관련 문서 | Thread Information Block Thread Information Block (Windows Drivers) |
상세 정보 | |
역할 | 마이크로소프트 윈도우 운영체제에서 스레드 관련 정보를 저장하는 데 사용되는 데이터 구조체이다. |
접근 방식 | x86 아키텍처에서는 `FS` 세그먼트 레지스터를 통해 접근할 수 있다. |
포함 정보 | 스레드 ID, 스택 주소, 프로세스 환경 블록(PEB)에 대한 포인터 등 스레드 실행에 필요한 다양한 정보를 포함한다. |
주요 사용 목적 | 스레드의 상태 관리, 디버깅, 성능 모니터링 등 다양한 시스템 수준 작업에 활용된다. |
기타 정보 | TEB는 커널 모드와 사용자 모드 모두에서 접근 가능하다. |
2. TIB의 구조
TIB는 운영체제 및 아키텍처에 따라 구조가 달라진다.[1] Wine의 마이크로소프트 윈도우 내부 작업에 기반하여 TIB의 구조를 나타내면 아래 표와 같다.
바이트/ 타입 | 오프셋 (32비트, FS) | 오프셋 (64비트, GS) | 윈도우 버전 | 설명 |
---|---|---|---|---|
포인터 | FS:[0x00] | GS:[0x00] | Win9x 및 NT | 현재 구조적 예외 처리(SEH) 프레임 |
포인터 | FS:[0x04] | GS:[0x08] | Win9x 및 NT | 스택 베이스 / 스택 하단 (높은 주소) |
포인터 | FS:[0x08] | GS:[0x10] | Win9x 및 NT | 스택 제한 / 스택 상단 (낮은 주소) |
포인터 | FS:[0x0C] | GS:[0x18] | NT | `SubSystemTib` |
포인터 | FS:[0x10] | GS:[0x20] | NT | 파이버 데이터 |
포인터 | FS:[0x14] | GS:[0x28] | Win9x 및 NT | 임의 데이터 슬롯 |
포인터 | FS:[0x18] | GS:[0x30] | Win9x 및 NT | TEB의 선형 주소 |
NT 서브시스템 독립 부분의 끝; 아래는 Win32에 종속적임 | ||||
포인터 | FS:[0x1C] | GS:[0x38] | NT | 환경 포인터 |
포인터 | FS:[0x20] | GS:[0x40] | NT | 프로세스 ID (일부 윈도우 배포판에서는 이 필드가 `DebugContext`로 사용됨) |
포인터 | FS:[0x24] | GS:[0x48] | NT | 현재 스레드 ID |
포인터 | FS:[0x28] | GS:[0x50] | NT | 활성 RPC 핸들 |
포인터 | FS:[0x2C] | GS:[0x58] | Win9x 및 NT | 스레드 로컬 스토리지 배열의 선형 주소 |
포인터 | FS:[0x30] | GS:[0x60] | NT | 프로세스 환경 블록 (PEB)의 선형 주소 |
4 | FS:[0x34] | GS:[0x68] | NT | 마지막 오류 번호 |
4 | FS:[0x38] | GS:[0x6C] | NT | 소유된 중요 섹션 수 |
포인터 | FS:[0x3C] | GS:[0x70] | NT | CSR 클라이언트 스레드의 주소 |
포인터 | FS:[0x40] | GS:[0x78] | NT | Win32 스레드 정보 |
124 | FS:[0x44] | GS:[0x80] | NT, Wine | Win32 클라이언트 정보 (NT), user32 개인 데이터 (Wine), 0x60 = LastError (Win95&98), 0x74 = LastError (WinME) |
포인터 | FS:[0xC0] | GS:[0x100] | NT | Wow64를 위해 예약됨. Wow64의 `FastSysCall`에 대한 포인터를 포함한다. |
4 | FS:[0xC4] | GS:[0x108] | NT | 현재 로케일 |
4 | FS:[0xC8] | GS:[0x10C] | NT | FP 소프트웨어 상태 레지스터 |
216 | FS:[0xCC] | GS:[0x110] | NT, Wine | OS용으로 예약됨 (NT), kernel32 개인 데이터 (Wine). 여기서: FS:[0x124] 4 NT 포인터 to `KTHREAD` (ETHREAD영어) 구조체 |
4 | FS:[0x1A4] | GS:[0x2C0] | NT | 예외 코드 |
18 | FS:[0x1A8] | GS:[0x2C8] | NT | 활성화 컨텍스트 스택 |
24 | FS:[0x1BC] | GS:[0x2E8] | NT, Wine | 여유 바이트 (NT), ntdll 개인 데이터 (Wine) |
40 | FS:[0x1D4] | GS:[0x300] | NT, Wine | OS용으로 예약됨 (NT), ntdll 개인 데이터 (Wine) |
1248 | FS:[0x1FC] | GS:[0x350] | NT, Wine | GDI TEB 배치 (OS), vm86 개인 데이터 (Wine) |
4 | FS:[0x6DC] | GS:[0x838] | NT | GDI 영역 |
4 | FS:[0x6E0] | GS:[0x840] | NT | GDI 펜 |
4 | FS:[0x6E4] | GS:[0x848] | NT | GDI 브러시 |
4 | FS:[0x6E8] | GS:[0x850] | NT | 실제 프로세스 ID |
4 | FS:[0x6EC] | GS:[0x858] | NT | 실제 스레드 ID |
4 | FS:[0x6F0] | GS:[0x860] | NT | GDI 캐시된 프로세스 핸들 |
4 | FS:[0x6F4] | GS:[0x868] | NT | GDI 클라이언트 프로세스 ID (PID) |
4 | FS:[0x6F8] | GS:[0x86C] | NT | GDI 클라이언트 스레드 ID (TID) |
4 | FS:[0x6FC] | GS:[0x870] | NT | GDI 스레드 로케일 정보 |
20 | FS:[0x700] | GS:[0x878] | NT | 사용자 응용 프로그램을 위해 예약됨 |
1248 | FS:[0x714] | GS:[0x890] | NT | GL용으로 예약됨 (내부 정보는 와인 참조)[1] |
4 | FS:[0xBF4] | GS:[0x1250] | NT | 마지막 상태 값 |
532 | FS:[0xBF8] | GS:[0x1258] | NT | 정적 `UNICODE_STRING` 버퍼 |
포인터 | FS:[0xE0C] | GS:[0x1478] | NT | `DeallocationStack`이라고도 알려져 있으며, 스택 버퍼의 실제 시작 주소를 설정하므로 실제 스택 제한을 설정한다. 이는 스택 제한 필드보다 몇 페이지 적다 (스택 오버플로를 감지하는 데 사용되는 가드 페이지를 숨긴다). |
포인터[] | FS:[0xE10] | GS:[0x1480] | NT | TLS 슬롯, 슬롯당 4/8 바이트, 64 슬롯 |
8 | FS:[0xF10] | GS:[0x1680] | NT | TLS 링크 (`LIST_ENTRY` 구조체) |
4 | FS:[0xF18] | GS:[0x1690] | NT | VDM |
4 | FS:[0xF1C] | GS:[0x1698] | NT | RPC용으로 예약됨 |
4 | FS:[0xF28] | GS:[0x16B0] | NT | 스레드 오류 모드 (`RtlSetThreadErrorMode`) |
4 | FS:[0xF78] | GS:[0x1748] | NT | 보장된 스택 바이트 |
이것은 전체 표가 아니다. FS:[0xfb4] / GS:[17c8]까지의 모든 필드는 Wine 참조를 참조.[1] 최신 윈도우 버전은 TIB 크기를 윈도우 10에서 0x1000/0x1838까지 확장한다. 추가된 일부 필드는 제거되어 정의가 충돌한다.[2] |
FS (32비트의 경우) 또는 GS (64비트의 경우)는 TDB (스레드 데이터베이스)로 알려진 데이터 블록에 포함된 TIB에 매핑된다. TIB에는 스레드별 예외 처리 체인과 TLS (스레드 로컬 스토리지)에 대한 포인터가 포함되어 있으며, 스레드 로컬 스토리지는 C 로컬 스토리지와는 다르다.
2. 1. 32비트 윈도우 (x86)
32비트 윈도우(x86)에서 TIB는 FS 세그먼트 레지스터를 통해 접근한다. 주요 필드는 다음과 같다:[1]위치 | 길이 | 윈도우 버전 | 설명 |
---|---|---|---|
FS:[0x00] | 4 | Win9x 및 NT | 현재 구조적 예외 처리(SEH) 프레임 |
FS:[0x04] | 4 | Win9x 및 NT | 스택 베이스 / 스택의 바닥 (높은 주소) |
FS:[0x08] | 4 | Win9x 및 NT | 스택 한계 / 스택의 천장 (낮은 주소) |
FS:[0x0C] | 4 | NT | SubSystemTib |
FS:[0x10] | 4 | NT | Fiber data |
FS:[0x14] | 4 | Win9x 및 NT | 임의 데이터 슬롯 |
FS:[0x18] | 4 | Win9x 및 NT | Thread Environment Block |
---- NT subsystem 독립적인 부분 끝 ---- | |||
FS:[0x1C] | 4 | NT | Environment Pointer |
FS:[0x20] | 4 | NT | 프로세스 ID (몇몇 윈도우 버전에서 이 필드는 DebugContext로 쓰인다.) |
FS:[0x24] | 4 | NT | 현재 스레드 ID |
FS:[0x28] | 4 | NT | 활동중인 RPC 핸들 |
FS:[0x2C] | 4 | Win9x 및 NT | 스레드 로컬 스토리지 배열의 선형 주소 |
FS:[0x30] | 4 | NT | 프로세스 환경 블록(PEB)의 선형 주소 |
FS:[0x34] | 4 | NT | 마지막 오류 번호 |
FS:[0x38] | 4 | NT | 소유된 중요 섹션 수 |
FS:[0x3C] | 4 | NT | CSR 클라이언트 스레드의 주소 |
FS:[0x40] | 4 | NT | Win32 스레드 정보 |
FS:[0x44] | 124 | NT, Wine | Win32 클라이언트 정보 (NT), user32 private data (Wine), 0x60 = LastError (Win95), 0x74 = LastError (WinME) |
FS:[0xC0] | 4 | NT | Wow64를 위해 예약됨. Wow64에서 FastSysCall에 대한 포인터를 포함한다. |
FS:[0xC4] | 4 | NT | Current Locale |
FS:[0xC8] | 4 | NT | FP Software Status Register |
FS:[0xCC] | 216 | NT, Wine | OS용으로 예약됨 (NT), kernel32 private data (Wine). herein: FS:[0x124] 4 NT Pointer to KTHREAD (ETHREAD) structure |
FS:[0x1A4] | 4 | NT | 예외 코드 |
FS:[0x1A8] | 18 | NT | Activation context stack |
FS:[0x1BC] | 24 | NT, Wine | Spare bytes (NT), ntdll private data (Wine) |
FS:[0x1D4] | 40 | NT, Wine | OS용으로 예약됨 (NT), ntdll private data (Wine) |
FS:[0x1FC] | 1248 | NT, Wine | GDI TEB Batch (OS), vm86 private data (Wine) |
FS:[0x6DC] | 4 | NT | GDI Region |
FS:[0x6E0] | 4 | NT | GDI 펜 |
FS:[0x6E4] | 4 | NT | GDI 브러시 |
FS:[0x6E8] | 4 | NT | Real Process ID |
FS:[0x6EC] | 4 | NT | Real Thread ID |
FS:[0x6F0] | 4 | NT | GDI cached process handle |
FS:[0x6F4] | 4 | NT | GDI 클라이언트 프로세스 ID (PID) |
FS:[0x6F8] | 4 | NT | GDI 클라이언트 스레드 ID (TID) |
FS:[0x6FC] | 4 | NT | GDI thread locale information |
FS:[0x700] | 20 | NT | 사용자 응용 프로그램을 위해 예약됨 |
FS:[0x714] | 1248 | NT | GL용으로 예약됨 |
FS:[0xBF4] | 4 | NT | 마지막 상태 값 |
FS:[0xBF8] | 532 | NT | Static UNICODE_STRING buffer |
FS:[0xE0C] | 4 | NT | deallocation stack에 대한 포인터 |
FS:[0xE10] | 256 | NT | TLS 슬롯, 슬롯 당 4 byte |
FS:[0xF10] | 8 | NT | TLS 링크 (LIST_ENTRY structure) |
FS:[0xF18] | 4 | NT | VDM |
FS:[0xF1C] | 4 | NT | RPC용으로 예약됨 |
FS:[0xF28] | 4 | NT | 스레드 에러 모드(RtlSetThreadErrorMode) |
2. 2. 64비트 윈도우 (x64)
64비트 윈도우에서 TIB는 GS 세그먼트 레지스터를 통해 접근한다.[1] 32비트 구조와 유사하지만, 필드의 크기와 오프셋이 다르다. 다음은 Wine의 마이크로소프트 윈도우 내부 작업에 기반한 64비트 TIB 구조이다.[1]바이트/타입 | 오프셋 (64비트, GS) | 윈도우 버전 | 설명 |
---|---|---|---|
포인터 | GS:[0x00] | Win9x 및 NT | 현재 구조적 예외 처리(SEH) 프레임 |
포인터 | GS:[0x08] | Win9x 및 NT | 스택 베이스 / 스택 하단 (높은 주소) |
포인터 | GS:[0x10] | Win9x 및 NT | 스택 제한 / 스택 상단 (낮은 주소) |
포인터 | GS:[0x18] | NT | SubSystemTib |
포인터 | GS:[0x20] | NT | 파이버 데이터 |
포인터 | GS:[0x28] | Win9x 및 NT | 임의 데이터 슬롯 |
포인터 | GS:[0x30] | Win9x 및 NT | TEB의 선형 주소 |
NT 서브시스템 독립 부분의 끝; 아래는 Win32에 종속적임 | |||
포인터 | GS:[0x38] | NT | 환경 포인터 |
포인터 | GS:[0x40] | NT | 프로세스 ID (일부 윈도우 배포판에서는 이 필드가 DebugContext 로 사용됨) |
포인터 | GS:[0x48] | NT | 현재 스레드 ID |
포인터 | GS:[0x50] | NT | 활성 RPC 핸들 |
포인터 | GS:[0x58] | Win9x 및 NT | 스레드 로컬 스토리지 배열의 선형 주소 |
포인터 | GS:[0x60] | NT | 프로세스 환경 블록 (PEB)의 선형 주소 |
4 | GS:[0x68] | NT | 마지막 오류 번호 |
4 | GS:[0x6C] | NT | 소유된 중요 섹션 수 |
포인터 | GS:[0x70] | NT | CSR 클라이언트 스레드의 주소 |
포인터 | GS:[0x78] | NT | Win32 스레드 정보 |
124 | GS:[0x80] | NT, Wine | Win32 클라이언트 정보 (NT), user32 개인 데이터 (Wine), 0x60 = LastError (Win95&98), 0x74 = LastError (WinME) |
포인터 | GS:[0x100] | NT | Wow64를 위해 예약됨. Wow64의 FastSysCall 에 대한 포인터를 포함한다. |
4 | GS:[0x108] | NT | 현재 로케일 |
4 | GS:[0x10C] | NT | FP 소프트웨어 상태 레지스터 |
216 | GS:[0x110] | NT, Wine | OS용으로 예약됨 (NT), kernel32 개인 데이터 (Wine) 여기서: 4 NT 포인터 to KTHREAD (ETHREAD ) 구조체 |
4 | GS:[0x2C0] | NT | 예외 코드 |
18 | GS:[0x2C8] | NT | 활성화 컨텍스트 스택 |
24 | GS:[0x2E8] | NT, Wine | 여유 바이트 (NT), ntdll 개인 데이터 (Wine) |
40 | GS:[0x300] | NT, Wine | OS용으로 예약됨 (NT), ntdll 개인 데이터 (Wine) |
1248 | GS:[0x350] | NT, Wine | GDI TEB 배치 (OS), vm86 개인 데이터 (Wine) |
4 | GS:[0x838] | NT | GDI 영역 |
4 | GS:[0x840] | NT | GDI 펜 |
4 | GS:[0x848] | NT | GDI 브러시 |
4 | GS:[0x850] | NT | 실제 프로세스 ID |
4 | GS:[0x858] | NT | 실제 스레드 ID |
4 | GS:[0x860] | NT | GDI 캐시된 프로세스 핸들 |
4 | GS:[0x868] | NT | GDI 클라이언트 프로세스 ID (PID) |
4 | GS:[0x86C] | NT | GDI 클라이언트 스레드 ID (TID) |
4 | GS:[0x870] | NT | GDI 스레드 로케일 정보 |
20 | GS:[0x878] | NT | 사용자 응용 프로그램을 위해 예약됨 |
1248 | GS:[0x890] | NT | GL용으로 예약됨 (내부 정보는 와인 참조)[1] |
4 | GS:[0x1250] | NT | 마지막 상태 값 |
532 | GS:[0x1258] | NT | 정적 UNICODE_STRING 버퍼 |
포인터 | GS:[0x1478] | NT | DeallocationStack 이라고도 알려져 있으며, 스택 버퍼의 실제 시작 주소를 설정하므로 실제 스택 제한을 설정한다. 이는 스택 제한 필드보다 몇 페이지 적다 (스택 오버플로를 감지하는 데 사용되는 가드 페이지를 숨긴다). |
포인터[] | GS:[0x1480] | NT | TLS 슬롯, 슬롯당 4/8 바이트, 64 슬롯 |
8 | GS:[0x1680] | NT | TLS 링크 (LIST_ENTRY 구조체) |
4 | GS:[0x1690] | NT | VDM |
4 | GS:[0x1698] | NT | RPC용으로 예약됨 |
4 | GS:[0x16B0] | NT | 스레드 오류 모드 (RtlSetThreadErrorMode ) |
4 | GS:[0x1748] | NT | 보장된 스택 바이트 |
이것은 전체 표가 아니다. GS:[0x17c8]까지의 모든 필드는 Wine 참조를 참조.[1] 최신 윈도우 버전은 TIB 크기를 윈도우 10에서 0x1838까지 확장한다. 추가된 일부 필드는 제거되어 정의가 충돌한다.[2] |
2. 3. 추가 정보
TIB에는 다음과 같은 다양한 정보들이 포함되어 있다.[1]- GDI 정보
- Wow64 관련 정보
- 예외 코드
- 활성화 컨텍스트 스택
32비트 (FS) | 64비트 (GS) | 설명 |
---|---|---|
0x1A4 | 0x2C0 | 예외 코드 |
0x1A8 | 0x2C8 | 활성화 컨텍스트 스택 |
0x1FC | 0x350 | GDI TEB 배치 |
0x6DC | 0x838 | GDI 영역 |
0x6E0 | 0x840 | GDI 펜 |
0x6E4 | 0x848 | GDI 브러시 |
0x6E8 | 0x850 | 실제 프로세스 ID |
0x6EC | 0x858 | 실제 스레드 ID |
0x6F0 | 0x860 | GDI 캐시된 프로세스 핸들 |
0x6F4 | 0x868 | GDI 클라이언트 프로세스 ID (PID) |
0x6F8 | 0x86C | GDI 클라이언트 스레드 ID (TID) |
0x6FC | 0x870 | GDI 스레드 로케일 정보 |
0xC0 | 0x100 | Wow64를 위해 예약됨. Wow64의 FastSysCall 에 대한 포인터를 포함. |
0x714 | 0x890 | GL용으로 예약됨 (내부 정보는 와인 참조)[1] |
현재 스레드의 TIB는 세그먼트 레지스터 FS (x86) 또는 GS (x64)의 오프셋으로 접근할 수 있다.[3]
3. TIB 접근 방법
일반적으로 `FS:[0x18]`(32비트) 또는 `GS:[0x30]`(64비트)에 있는 선형 자기 참조 포인터를 사용하여 TIB에 접근한다. 이 포인터를 포인터 연산에 사용하거나 구조체 포인터로 캐스팅할 수 있다.
마이크로소프트 윈도우 SDK를 사용하는 경우, `winnt.h`에 정의된 인라인 함수 `NtCurrentTeb`를 사용하여 현재 스레드 정보 블록의 주소를 `NT_TIB *` 형태로 얻을 수 있다.[3]
C/C++ 코드에서는 인라인 어셈블리 또는 내장 함수를 사용하여 TIB에 접근할 수 있다. (자세한 내용은 하위 섹션 "코드 예제 (C/C++)" 참고)
3. 1. 코드 예제 (C/C++)
cpp
// gcc (AT&T 스타일 인라인 어셈블리).
void *getTIB(void) {
register void *pTIB;
#if defined(__x86_64__) || defined(__amd64__)
__asm__("movq %%gs:0x30, %0" : "=r" (pTIB));
#elif defined(__i386__)
__asm__("movl %%fs:0x18, %0" : "=r" (pTIB));
#else
#error unsupported architecture
#endif
return pTIB;
}
```
```cpp
// gcc (이름 지정된 주소 공간, -O1 또는 -ftree-ter에서 인라인 어셈블리 버전과 동일).
void *getTIB(void) {
#if defined(__x86_64__) || defined(__amd64__)
#ifndef __SEG_GS
#error unsupported GCC version
#endif
return *(void *__seg_gs *) 0x30;
#elif defined(__i386__)
#ifndef __SEG_FS
#error unsupported GCC version
#endif
return *(void *__seg_fs *) 0x18;
#else
#error unsupported architecture
#endif
}
```
```cpp
// Microsoft C
__declspec(naked)
void *getTIB() {
__asm mov EAX, FS:[18h]
__asm ret
}
```
```cpp
// 인라인 어셈블리 대신 Microsoft의 내장 함수 사용 (X86 및 X64 아키텍처 모두에서 작동).
void *getTIB() {
#ifdef _M_IX86
return (void *)__readfsdword(0x18);
#elif _M_AMD64
return (void *)__readgsqword(0x30);
#else
#error unsupported architecture
#endif
}
4. 스택 정보
프로세스는 TIB에 저장된 정보를 적절하게 업데이트하는 한, 스레드의 스택을 자유롭게 이동할 수 있어야 한다. 이와 관련하여 몇 가지 중요한 필드가 있는데, 이는 스택 베이스, 스택 제한, 할당 해제 스택 및 보장된 스택 바이트이며, 각각 64비트에서 오프셋 `0x8`, `0x10`, `0x1478` 및 `0x1748`에 저장된다.[1] 다양한 Windows 커널 함수는 이러한 값을 읽고 쓰는데, 특히 스택 오버플로를 다른 읽기/쓰기 페이지 폴트와 구별하기 위해 사용된다 (보장된 스택 바이트 내에서 스택 제한에 의해 보호되는 페이지에 대한 읽기 또는 쓰기는 액세스 위반 대신 스택 오버플로 예외를 발생시킨다).[1] 할당 해제 스택은 Windows API가 보호된 페이지의 양을 변경할 수 있기 때문에 중요하다.[1] `SetThreadStackGuarantee` 함수는 현재 공간을 읽고 이를 늘릴 수 있게 해준다.[1] 읽으려면 `GuaranteedStackBytes` 필드를 읽고, 늘리려면 스택 페이지를 언커밋해야 한다.[1] `DeallocationStack`을 설정하지 않고 스택 제한을 설정하면 `SetThreadStackGuarantee`에서 이상한 동작이 발생할 수 있다.[1] 예를 들어, 스택 제한이 잘못된 값으로 덮어쓰여질 수 있다.[1] 다양한 라이브러리에서 `SetThreadStackGuarantee`를 호출하는데, 예를 들어 .NET CLR은 스레드의 스택을 설정하는 데 사용한다.[1]
참조
[1]
웹사이트
wine winternl.h: typedef struct _TEB
https://github.com/w[...]
wine-mirror
2019-10-29
[2]
웹사이트
TEB
https://www.geoffcha[...]
[3]
웹사이트
NtCurrentTeb function
https://docs.microso[...]
2019-11-20
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com