mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/basic-stack-binary-exploitation-met
This commit is contained in:
parent
85a2a3b86e
commit
88d329ce67
@ -47,12 +47,14 @@ Segment Sections...
|
||||
|
||||
바이너리를 메모리에 로드하는 데 사용할 로더의 경로를 나타냅니다.
|
||||
|
||||
> 팁: 정적으로 링크된 또는 정적-PIE 바이너리는 `INTERP` 항목이 없습니다. 이러한 경우에는 동적 로더가 관여하지 않으므로 이를 기반으로 하는 기술(예: `ret2dlresolve`)이 비활성화됩니다.
|
||||
|
||||
### LOAD
|
||||
|
||||
이 헤더는 **바이너리를 메모리에 로드하는 방법**을 나타내는 데 사용됩니다.\
|
||||
각 **LOAD** 헤더는 **메모리**의 영역(크기, 권한 및 정렬)을 나타내고, 그곳에 복사할 ELF **바이너리의 바이트**를 나타냅니다.
|
||||
각 **LOAD** 헤더는 **메모리**의 영역(크기, 권한 및 정렬)을 나타내고 ELF **바이너리에서 복사할 바이트**를 나타냅니다.
|
||||
|
||||
예를 들어, 두 번째 헤더는 크기가 0x1190이며, 0x1fc48에 위치해야 하고, 읽기 및 쓰기 권한을 가지며, 오프셋 0xfc48에서 0x528로 채워집니다(모든 예약된 공간을 채우지 않습니다). 이 메모리에는 섹션 `.init_array .fini_array .dynamic .got .data .bss`가 포함됩니다.
|
||||
예를 들어, 두 번째 헤더는 크기가 0x1190이며, 0x1fc48에 위치해야 하고 읽기 및 쓰기 권한을 가지며 오프셋 0xfc48에서 0x528로 채워집니다(모든 예약된 공간을 채우지 않음). 이 메모리에는 섹션 `.init_array .fini_array .dynamic .got .data .bss`가 포함됩니다.
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
@ -62,6 +64,12 @@ Segment Sections...
|
||||
|
||||
이것은 바이너리에 대한 공급업체 메타데이터 정보를 저장합니다.
|
||||
|
||||
- x86-64에서 `readelf -n`은 `.note.gnu.property` 내에 `GNU_PROPERTY_X86_FEATURE_1_*` 플래그를 표시합니다. `IBT` 및/또는 `SHSTK`가 보이면, 바이너리는 CET(간접 분기 추적 및/또는 섀도 스택)으로 빌드되었습니다. 이는 ROP/JOP에 영향을 미치며, 간접 분기 대상은 `ENDBR64` 명령어로 시작해야 하고 반환은 섀도 스택에 대해 확인됩니다. 자세한 내용과 우회 노트는 CET 페이지를 참조하세요.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
디버거와 C++ 예외 처리 런타임 함수에서 사용하는 스택 언와인드 테이블의 위치를 정의합니다.
|
||||
@ -70,13 +78,21 @@ Segment Sections...
|
||||
|
||||
스택 실행 방지 방어의 구성을 포함합니다. 활성화되면 바이너리는 스택에서 코드를 실행할 수 없습니다.
|
||||
|
||||
- `readelf -l ./bin | grep GNU_STACK`로 확인하세요. 테스트 중에 강제로 전환하려면 `execstack -s|-c ./bin`을 사용할 수 있습니다.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
바이너리의 RELRO(재배치 읽기 전용) 구성을 나타냅니다. 이 보호는 프로그램이 로드된 후 실행되기 전에 메모리의 특정 섹션(예: `GOT` 또는 `init` 및 `fini` 테이블)을 읽기 전용으로 표시합니다.
|
||||
|
||||
이전 예제에서는 0x3b8 바이트를 0x1fc48에 읽기 전용으로 복사하여 섹션 `.init_array .fini_array .dynamic .got .data .bss`에 영향을 미칩니다.
|
||||
이전 예제에서는 0x3b8 바이트를 0x1fc48로 읽기 전용으로 복사하여 섹션 `.init_array .fini_array .dynamic .got .data .bss`에 영향을 미칩니다.
|
||||
|
||||
RELRO는 부분적이거나 전체적일 수 있으며, 부분 버전은 **`.plt.got`** 섹션을 보호하지 않으며, 이는 **지연 바인딩**에 사용되며 라이브러리의 주소를 처음 검색할 때 이 메모리 공간에 **쓰기 권한**이 필요합니다.
|
||||
RELRO는 부분적 또는 전체적일 수 있으며, 부분 버전은 **`.plt.got`** 섹션을 보호하지 않으며, 이는 **지연 바인딩**에 사용되며 라이브러리의 주소를 처음 검색할 때 이 메모리 공간에 **쓰기 권한**이 필요합니다.
|
||||
|
||||
> 익스플로잇 기술 및 최신 우회 노트에 대한 정보는 전용 페이지를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
### TLS
|
||||
|
||||
@ -145,11 +161,11 @@ CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
```
|
||||
그것은 위치, 오프셋, 권한뿐만 아니라 섹션의 **데이터 유형**도 나타냅니다.
|
||||
It also indicates the location, offset, permissions but also the **데이터 유형** it section has.
|
||||
|
||||
### 메타 섹션
|
||||
|
||||
- **문자열 테이블**: ELF 파일에 필요한 모든 문자열을 포함하고 있습니다(하지만 프로그램에서 실제로 사용되는 문자열은 아닙니다). 예를 들어, `.text` 또는 `.data`와 같은 섹션 이름을 포함합니다. 그리고 문자열 테이블에서 `.text`가 오프셋 45에 있다면 **이름** 필드에 숫자 **45**를 사용합니다.
|
||||
- **문자열 테이블**: ELF 파일에 필요한 모든 문자열을 포함하고 있습니다(하지만 프로그램에서 실제로 사용되는 문자열은 아닙니다). 예를 들어, `.text` 또는 `.data`와 같은 섹션 이름을 포함합니다. 그리고 문자열 테이블에서 `.text`가 45의 오프셋에 있다면 **이름** 필드에 숫자 **45**를 사용합니다.
|
||||
- 문자열 테이블이 어디에 있는지 찾기 위해 ELF는 문자열 테이블에 대한 포인터를 포함합니다.
|
||||
- **심볼 테이블**: 이름(문자열 테이블의 오프셋), 주소, 크기 및 심볼에 대한 추가 메타데이터와 같은 심볼에 대한 정보를 포함합니다.
|
||||
|
||||
@ -188,12 +204,16 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
각 심볼 항목은 다음을 포함합니다:
|
||||
|
||||
- **이름**
|
||||
- **바인딩 속성** (약한, 로컬 또는 전역): 로컬 심볼은 프로그램 자체에서만 접근할 수 있으며, 전역 심볼은 프로그램 외부에서 공유됩니다. 약한 객체는 예를 들어 다른 함수에 의해 재정의될 수 있는 함수입니다.
|
||||
- **유형**: NOTYPE (유형 지정되지 않음), OBJECT (전역 데이터 변수), FUNC (함수), SECTION (섹션), FILE (디버거용 소스 코드 파일), TLS (스레드 로컬 변수), GNU_IFUNC (재배치를 위한 간접 함수)
|
||||
- **바인딩 속성** (약한, 로컬 또는 글로벌): 로컬 심볼은 프로그램 자체에서만 접근할 수 있으며, 글로벌 심볼은 프로그램 외부에서 공유됩니다. 약한 객체는 예를 들어 다른 함수로 재정의될 수 있는 함수입니다.
|
||||
- **유형**: NOTYPE (유형 지정되지 않음), OBJECT (글로벌 데이터 변수), FUNC (함수), SECTION (섹션), FILE (디버거용 소스 코드 파일), TLS (스레드 로컬 변수), GNU_IFUNC (재배치를 위한 간접 함수)
|
||||
- **섹션** 인덱스 (위치)
|
||||
- **값** (메모리 내 주소)
|
||||
- **크기**
|
||||
|
||||
#### GNU 심볼 버전 관리 (dynsym/dynstr/gnu.version)
|
||||
|
||||
현대 glibc는 심볼 버전을 사용합니다. `.gnu.version` 및 `.gnu.version_r`에서 항목을 볼 수 있으며, `strlen@GLIBC_2.17`와 같은 심볼 이름이 있습니다. 동적 링커는 심볼을 해결할 때 특정 버전을 요구할 수 있습니다. 수동 재배치를 만들 때 (예: ret2dlresolve) 올바른 버전 인덱스를 제공해야 하며, 그렇지 않으면 해결이 실패합니다.
|
||||
|
||||
## 동적 섹션
|
||||
```
|
||||
readelf -d lnstat
|
||||
@ -229,11 +249,28 @@ Tag Type Name/Value
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
```
|
||||
NEEDED 디렉토리는 프로그램이 계속 진행하기 위해 **언급된 라이브러리를 로드해야 함**을 나타냅니다. NEEDED 디렉토리는 공유 **라이브러리가 완전히 작동하고 사용 준비가 되었을 때** 완료됩니다.
|
||||
The NEEDED directory indicates that the program **필요한 라이브러리를 로드해야 함**을 나타냅니다. NEEDED 디렉토리는 공유 **라이브러리가 완전히 작동하고 준비되었을 때** 완료됩니다.
|
||||
|
||||
## Relocations
|
||||
### 동적 로더 검색 순서 (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
로더는 또한 로드한 후 종속성을 재배치해야 합니다. 이러한 재배치는 REL 또는 RELA 형식의 재배치 테이블에 표시되며, 재배치 수는 동적 섹션 RELSZ 또는 RELASZ에 제공됩니다.
|
||||
항목 `DT_RPATH` (사용 중단) 및/또는 `DT_RUNPATH`는 동적 로더가 종속성을 검색하는 위치에 영향을 미칩니다. 대략적인 순서:
|
||||
|
||||
- `LD_LIBRARY_PATH` (setuid/sgid 또는 기타 "보안 실행" 프로그램에 대해 무시됨)
|
||||
- `DT_RPATH` (단, `DT_RUNPATH`가 없을 경우)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- 기본 디렉토리 예: `/lib64`, `/usr/lib64` 등.
|
||||
|
||||
`$ORIGIN`은 RPATH/RUNPATH 내에서 주요 객체의 디렉토리를 참조하는 데 사용될 수 있습니다. 공격자의 관점에서 이는 파일 시스템 레이아웃이나 환경을 제어할 때 중요합니다. 강화된 바이너리(AT_SECURE)의 경우 대부분의 환경 변수는 로더에 의해 무시됩니다.
|
||||
|
||||
- 검사 방법: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- 빠른 테스트: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (검색 경로 결정 표시)
|
||||
|
||||
> Priv-esc 팁: 귀하가 소유한 쓰기 가능한 RUNPATH 또는 잘못 구성된 `$ORIGIN` 상대 경로를 악용하는 것을 선호하십시오. LD_PRELOAD/LD_AUDIT는 보안 실행(setuid) 컨텍스트에서 무시됩니다.
|
||||
|
||||
## 재배치
|
||||
|
||||
로더는 종속성을 로드한 후에도 재배치해야 합니다. 이러한 재배치는 REL 또는 RELA 형식의 재배치 테이블에 표시되며, 재배치 수는 동적 섹션 RELSZ 또는 RELASZ에 제공됩니다.
|
||||
```
|
||||
readelf -r lnstat
|
||||
|
||||
@ -274,7 +311,6 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0
|
||||
00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
|
||||
00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0
|
||||
00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0
|
||||
00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0
|
||||
00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0
|
||||
00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0
|
||||
@ -308,23 +344,41 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
```
|
||||
### 정적 재배치
|
||||
|
||||
프로그램이 **선호하는 주소**(보통 0x400000)와 다른 위치에 로드되면(주소가 이미 사용 중이거나 **ASLR** 또는 기타 이유로), 정적 재배치가 **포인터를 수정**하여 이진 파일이 선호하는 주소에 로드될 것으로 예상했던 값을 수정합니다.
|
||||
프로그램이 **선호하는 주소**(보통 0x400000)와 다른 위치에 로드되면(주소가 이미 사용 중이거나 **ASLR** 또는 기타 이유로), 정적 재배치는 선호하는 주소에 바이너리가 로드될 것으로 예상했던 값을 가진 포인터를 **수정**합니다.
|
||||
|
||||
예를 들어, `R_AARCH64_RELATIV` 유형의 섹션은 재배치 편향에 추가 값(addend value)을 더한 주소를 수정해야 합니다.
|
||||
예를 들어, `R_AARCH64_RELATIV` 유형의 섹션은 재배치 편향에 주소를 수정하고 추가 값(addend value)을 더해야 합니다.
|
||||
|
||||
### 동적 재배치 및 GOT
|
||||
|
||||
재배치는 외부 기호(종속성의 함수와 같은)를 참조할 수도 있습니다. 예를 들어, libC의 malloc 함수입니다. 그런 다음 로더는 libC를 로드할 때 malloc 함수가 로드된 주소를 확인하고, 이 주소를 GOT(전역 오프셋 테이블) 테이블(재배치 테이블에 표시됨)에 기록합니다. 여기서 malloc의 주소가 지정되어야 합니다.
|
||||
재배치는 외부 기호(종속성의 함수와 같은)를 참조할 수도 있습니다. 예를 들어, libC의 malloc 함수입니다. 그런 다음 로더는 libC를 로드할 때 malloc 함수가 로드된 주소를 확인하고, 이 주소를 GOT(전역 오프셋 테이블) 테이블에 기록합니다(재배치 테이블에 표시된 대로) 여기서 malloc의 주소가 지정되어야 합니다.
|
||||
|
||||
### 프로시저 링크 테이블
|
||||
|
||||
PLT 섹션은 지연 바인딩을 수행할 수 있게 해주며, 이는 함수의 위치 해석이 처음 접근할 때 수행된다는 것을 의미합니다.
|
||||
PLT 섹션은 지연 바인딩(lazy binding)을 수행할 수 있게 해주며, 이는 함수의 위치 해석이 처음 접근할 때 수행된다는 것을 의미합니다.
|
||||
|
||||
따라서 프로그램이 malloc을 호출할 때, 실제로는 PLT의 `malloc`에 해당하는 위치(`malloc@plt`)를 호출합니다. 처음 호출될 때 `malloc`의 주소를 해석하고 저장하므로 다음에 `malloc`이 호출될 때는 PLT 코드 대신 그 주소가 사용됩니다.
|
||||
따라서 프로그램이 malloc을 호출할 때, 실제로는 PLT의 `malloc`에 해당하는 위치(`malloc@plt`)를 호출합니다. 처음 호출할 때 `malloc`의 주소를 해석하고 저장하므로 다음에 `malloc`이 호출될 때는 PLT 코드 대신 그 주소가 사용됩니다.
|
||||
|
||||
#### 익스플로잇에 영향을 미치는 현대 링크 동작
|
||||
|
||||
- `-z now` (전체 RELRO)는 지연 바인딩을 비활성화합니다; PLT 항목은 여전히 존재하지만 GOT/PLT는 읽기 전용으로 매핑되므로 **GOT 덮어쓰기** 및 **ret2dlresolve**와 같은 기술은 주요 바이너리에 대해 작동하지 않습니다(라이브러리는 여전히 부분적으로 RELRO일 수 있습니다). 참조:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt`는 컴파일러가 PLT 스텁을 거치지 않고 **GOT 항목을 직접** 통해 외부 함수를 호출하게 만듭니다. `call func@plt` 대신 `mov reg, [got]; call reg`와 같은 호출 시퀀스를 보게 될 것입니다. 이는 추측 실행 남용을 줄이고 PLT 스텁 주위의 ROP 가젯 탐색을 약간 변경합니다.
|
||||
|
||||
- PIE vs static-PIE: PIE(ET_DYN 및 `INTERP` 포함)는 동적 로더가 필요하며 일반적인 PLT/GOT 기계 장치를 지원합니다. Static-PIE(ET_DYN 및 `INTERP` 없음)는 커널 로더에 의해 재배치가 적용되며 `ld.so`가 없습니다; 런타임에서 PLT 해석이 없을 것으로 예상됩니다.
|
||||
|
||||
> GOT/PLT가 옵션이 아닌 경우, 다른 쓰기 가능한 코드 포인터로 전환하거나 libc로 고전적인 ROP/SROP를 사용하십시오.
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
{{#endref}}
|
||||
|
||||
## 프로그램 초기화
|
||||
|
||||
프로그램이 로드된 후 실행할 시간입니다. 그러나 실행되는 첫 번째 코드는 **항상 `main`** 함수가 아닙니다. 예를 들어 C++에서 **전역 변수가 클래스의 객체인 경우**, 이 객체는 main이 실행되기 **전에** **초기화**되어야 합니다.
|
||||
프로그램이 로드된 후 실행할 시간입니다. 그러나 실행되는 첫 번째 코드는 항상 `main` 함수가 아닙니다. 예를 들어 C++에서 **전역 변수가 클래스의 객체**인 경우, 이 객체는 main이 실행되기 **전에** **초기화**되어야 합니다, 예를 들어:
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
@ -345,38 +399,75 @@ printf("Main\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
이러한 전역 변수는 `.data` 또는 `.bss`에 위치하지만, `__CTOR_LIST__` 및 `__DTOR_LIST__` 목록에는 초기화 및 소멸할 객체가 저장되어 이들을 추적할 수 있습니다.
|
||||
이 전역 변수들은 `.data` 또는 `.bss`에 위치하지만, `__CTOR_LIST__`와 `__DTOR_LIST__` 목록에는 초기화 및 소멸할 객체들이 저장되어 이들을 추적할 수 있습니다.
|
||||
|
||||
C 코드에서는 GNU 확장을 사용하여 동일한 결과를 얻을 수 있습니다:
|
||||
```c
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
컴파일러 관점에서, `main` 함수가 실행되기 전과 후에 이러한 작업을 실행하기 위해 `init` 함수와 `fini` 함수를 생성할 수 있으며, 이는 동적 섹션에서 **`INIT`** 및 **`FIN`**으로 참조됩니다. 그리고 ELF의 `init` 및 `fini` 섹션에 배치됩니다.
|
||||
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
|
||||
|
||||
언급된 다른 옵션은 동적 섹션의 **`INIT_ARRAY`** 및 **`FINI_ARRAY`** 항목에서 **`__CTOR_LIST__`** 및 **`__DTOR_LIST__`** 목록을 참조하는 것이며, 이들의 길이는 **`INIT_ARRAYSZ`** 및 **`FINI_ARRAYSZ`**로 표시됩니다. 각 항목은 인수 없이 호출될 함수 포인터입니다.
|
||||
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
|
||||
|
||||
또한 **`PREINIT_ARRAY`**를 가질 수 있으며, 이는 **`INIT_ARRAY`** 포인터가 실행되기 **전**에 실행될 **포인터**를 포함합니다.
|
||||
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
|
||||
|
||||
### 초기화 순서
|
||||
#### Exploitation note
|
||||
|
||||
1. 프로그램이 메모리에 로드되고, 정적 전역 변수가 **`.data`**에서 초기화되며, 초기화되지 않은 변수는 **`.bss`**에서 0으로 설정됩니다.
|
||||
2. 프로그램 또는 라이브러리에 대한 모든 **종속성**이 **초기화**되고 **동적 링크**가 실행됩니다.
|
||||
- Under Partial RELRO these arrays live in pages that are still writable before `ld.so` flips `PT_GNU_RELRO` to read-only. If you get an arbitrary write early enough or you can target a library’s writable arrays, you can hijack control flow by overwriting an entry with a function of your choice. Under Full RELRO they are read-only at runtime.
|
||||
|
||||
- For lazy binding abuse of the dynamic linker to resolve arbitrary symbols at runtime, see the dedicated page:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Initialization Order
|
||||
|
||||
1. 프로그램이 메모리에 로드되고, 정적 전역 변수가 **`.data`**에서 초기화되며 초기화되지 않은 변수는 **`.bss`**에서 0으로 설정됩니다.
|
||||
2. 프로그램 또는 라이브러리의 모든 **종속성**이 **초기화**되고 **동적 링크**가 실행됩니다.
|
||||
3. **`PREINIT_ARRAY`** 함수가 실행됩니다.
|
||||
4. **`INIT_ARRAY`** 함수가 실행됩니다.
|
||||
5. **`INIT`** 항목이 있으면 호출됩니다.
|
||||
6. 라이브러리인 경우, dlopen이 여기서 끝나고, 프로그램인 경우 **실제 진입점**(`main` 함수)을 호출할 시간입니다.
|
||||
|
||||
## 스레드 로컬 저장소 (TLS)
|
||||
## Thread-Local Storage (TLS)
|
||||
|
||||
C++에서 **`__thread_local`** 키워드를 사용하거나 GNU 확장 **`__thread`**를 사용하여 정의됩니다.
|
||||
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
|
||||
|
||||
각 스레드는 이 변수에 대해 고유한 위치를 유지하므로 오직 해당 스레드만 자신의 변수를 접근할 수 있습니다.
|
||||
Each thread will maintain a unique location for this variable so only the thread can access its variable.
|
||||
|
||||
이것이 사용될 때 ELF에서 **`.tdata`** 및 **`.tbss`** 섹션이 사용됩니다. 이는 TLS를 위한 `.data` (초기화됨) 및 `.bss` (초기화되지 않음)와 유사합니다.
|
||||
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
|
||||
|
||||
각 변수는 TLS 헤더에 크기와 TLS 오프셋을 지정하는 항목을 가지며, 이는 스레드의 로컬 데이터 영역에서 사용할 오프셋입니다.
|
||||
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
|
||||
|
||||
`__TLS_MODULE_BASE`는 스레드 로컬 저장소의 기본 주소를 참조하는 데 사용되는 기호이며, 모듈의 모든 스레드 로컬 데이터를 포함하는 메모리 영역을 가리킵니다.
|
||||
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
|
||||
|
||||
## Auxiliary Vector (auxv) and vDSO
|
||||
|
||||
The Linux kernel passes an auxiliary vector to processes containing useful addresses and flags for the runtime:
|
||||
|
||||
- `AT_RANDOM`: points to 16 random bytes used by glibc for the stack canary and other PRNG seeds.
|
||||
- `AT_SYSINFO_EHDR`: base address of the vDSO mapping (handy to find `__kernel_*` syscalls and gadgets).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, etc.
|
||||
|
||||
As an attacker, if you can read memory or files under `/proc`, you can often leak these without an infoleak in the target process:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
|
||||
# From your own process (helper snippet)
|
||||
#include <sys/auxv.h>
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
|
||||
printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
|
||||
}
|
||||
```
|
||||
`AT_RANDOM`를 누출하면 해당 포인터를 역참조할 수 있다면 카나리 값을 얻을 수 있습니다; `AT_SYSINFO_EHDR`는 가젯을 찾거나 빠른 시스템 호출을 직접 호출하기 위한 vDSO 기반을 제공합니다.
|
||||
|
||||
## References
|
||||
|
||||
- ld.so(8) – 동적 로더 검색 순서, RPATH/RUNPATH, 보안 실행 규칙 (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
|
||||
- getauxval(3) – 보조 벡터 및 AT_* 상수: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user