Libc Protections
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Malloc는 8바이트(32비트) 또는 16바이트(64비트) 그룹으로 메모리를 할당합니다. 이는 32비트 시스템에서 청크의 끝이 0x8에 정렬되어야 하고, 64비트 시스템에서는 0x0에 정렬되어야 함을 의미합니다. 이 보안 기능은 각 청크가 사용하기 전에 이러한 특정 위치에서 올바르게 정렬되었는지 확인합니다.
64비트 시스템에서 청크 정렬의 시행은 Malloc의 보안을 크게 향상시켜 가짜 청크의 배치를 16개 주소 중 1개로 제한합니다. 이는 사용자가 입력 값에 대한 제어가 제한된 시나리오에서 공격을 더 복잡하고 성공적으로 실행하기 어렵게 만듭니다.
Fastbin Attack on __malloc_hook
Malloc의 새로운 정렬 규칙은 __malloc_hook
과 관련된 고전적인 공격을 저지합니다. 이전에는 공격자가 청크 크기를 조작하여 이 함수 포인터를 덮어쓰고 코드 실행을 얻을 수 있었습니다. 이제 엄격한 정렬 요구 사항은 이러한 조작이 더 이상 유효하지 않도록 하여 일반적인 공격 경로를 차단하고 전반적인 보안을 강화합니다.
Pointer Mangling은 메모리 관리 작업에서 fastbin 및 tcache Fd 포인터를 보호하기 위해 사용되는 보안 강화 기술입니다. 이 기술은 누출된 메모리 정보가 필요하지 않거나 알려진 위치에 상대적으로 메모리 위치를 직접 조작하는 특정 유형의 메모리 공격 전술을 방지하는 데 도움을 줍니다(상대적 덮어쓰기).
이 기술의 핵심은 난독화 공식입니다:
New_Ptr = (L >> 12) XOR P
L은 포인터의 저장 위치입니다.
P는 실제 fastbin/tcache Fd 포인터입니다.
저장 위치(L)를 오른쪽으로 12비트 비트 이동한 후 XOR 연산을 수행하는 이유는 중요합니다. 이 조작은 메모리 주소의 가장 낮은 12비트의 결정론적 특성에 내재된 취약점을 해결합니다. 이러한 비트는 일반적으로 시스템 아키텍처 제약으로 인해 예측 가능하기 때문입니다. 비트를 이동함으로써 예측 가능한 부분이 방정식에서 제거되어 새로운, 변형된 포인터의 무작위성이 향상되고, 이러한 비트의 예측 가능성에 의존하는 공격으로부터 보호됩니다.
이 변형된 포인터는 프로그램에서 사용하는 주소를 무작위화하여 공격자가 프로세스의 메모리 레이아웃을 예측하기 어렵게 만드는 **주소 공간 레이아웃 무작위화(ASLR)**에서 제공하는 기존의 무작위성을 활용합니다.
Demangling 포인터는 원래 주소를 검색하기 위해 동일한 XOR 연산을 사용합니다. 여기서 변형된 포인터는 공식에서 P로 처리되며, 변경되지 않은 저장 위치(L)와 XOR 연산을 수행하면 원래 포인터가 드러납니다. 변형 및 복원 과정의 대칭성은 시스템이 상당한 오버헤드 없이 포인터를 효율적으로 인코딩하고 디코딩할 수 있도록 하며, 메모리 포인터를 조작하는 공격에 대한 보안을 크게 강화합니다.
포인터 변형은 힙 관리에서 부분 및 전체 포인터 덮어쓰기를 방지하는 것을 목표로 하며, 이는 보안에서 중요한 향상입니다. 이 기능은 여러 방식으로 공격 기술에 영향을 미칩니다:
바이트 상대 덮어쓰기 방지: 이전에는 공격자가 포인터의 일부를 변경하여 정확한 주소를 알지 못한 채 힙 청크를 다른 위치로 리디렉션할 수 있었습니다. 이는 누출 없는 House of Roman 공격에서 분명히 나타나는 기술입니다. 포인터 변형을 통해 이러한 상대적 덮어쓰기는 힙 누출 없이 이제는 무차별 대입을 요구하므로 성공 가능성이 크게 줄어듭니다.
Tcache Bin/Fastbin 공격의 난이도 증가: 함수 포인터(예: __malloc_hook
)를 덮어쓰는 일반적인 공격은 fastbin 또는 tcache 항목을 조작하여 방해받습니다. 예를 들어, 공격은 LibC 주소를 누출하고, 청크를 tcache bin에 해제한 다음, Fd 포인터를 덮어써서 __malloc_hook
로 리디렉션하여 임의의 코드 실행을 시도할 수 있습니다. 포인터 변형을 통해 이러한 포인터는 올바르게 변형되어야 하므로, 정확한 조작을 위해 힙 누출이 필요하게 되어 공격 장벽이 높아집니다.
비힙 위치에서 힙 누출 요구: 비힙 영역(스택, .bss 섹션 또는 PLT/GOT)에서 가짜 청크를 생성하는 것도 이제 포인터 변형으로 인해 힙 누출이 필요합니다. 이는 이러한 영역을 악용하는 복잡성을 확장하며, LibC 주소 조작 요구와 유사합니다.
힙 주소 누출이 더 어려워짐: 포인터 변형은 fastbin 및 tcache bin에서 Fd 포인터의 유용성을 제한하여 힙 주소 누출의 출처로서의 역할을 감소시킵니다. 그러나 정렬되지 않은, 작은 및 큰 bin의 포인터는 여전히 변형되지 않으므로 주소 누출에 여전히 사용될 수 있습니다. 이러한 변화는 공격자가 이러한 bin에서 악용 가능한 정보를 탐색하도록 유도하지만, 일부 기술은 여전히 누출 전에 포인터를 복원할 수 있도록 허용할 수 있습니다.
For a better explanation of the process check the original post from here.
포인터를 변형하고 복원하는 데 사용되는 공식은:
New_Ptr = (L >> 12) XOR P
여기서 L은 저장 위치이고 P는 Fd 포인터입니다. L이 12비트 오른쪽으로 이동하면 P의 가장 중요한 비트가 노출됩니다. 이는 XOR의 특성으로, 비트가 자신과 XOR될 때 0을 출력합니다.
Algorithm의 주요 단계:
가장 중요한 비트의 초기 누출: 이동된 L과 P를 XOR하여 P의 상위 12비트를 효과적으로 얻습니다. 이동된 L의 부분은 0이 되어 P의 해당 비트는 변경되지 않습니다.
포인터 비트 복구: XOR는 가역적이므로 결과와 한 개의 피연산자를 알면 다른 피연산자를 계산할 수 있습니다. 이 속성을 사용하여 변형된 포인터의 부분과 알려진 비트 집합을 순차적으로 XOR하여 P의 전체 비트 집합을 유추합니다.
반복적 복원: 이 과정은 반복되며, 매번 이전 단계에서 발견된 P의 새 비트를 사용하여 변형된 포인터의 다음 세그먼트를 디코딩합니다. 모든 비트가 복구될 때까지 진행됩니다.
결정론적 비트 처리: L의 마지막 12비트는 이동으로 인해 손실되지만, 이들은 결정론적이므로 후처리 후 재구성할 수 있습니다.
이 알고리즘의 구현을 여기에서 찾을 수 있습니다: https://github.com/mdulin2/mangle
Pointer guard는 glibc에서 저장된 함수 포인터를 보호하기 위해 사용되는 공격 완화 기술로, 특히 atexit()
와 같은 라이브러리 호출에 의해 등록된 포인터를 보호합니다. 이 보호는 포인터를 스크램블하여 스레드 데이터(fs:0x30
)에 저장된 비밀과 XOR하고 비트 회전을 적용하는 방식으로 이루어집니다. 이 메커니즘은 공격자가 함수 포인터를 덮어써서 제어 흐름을 탈취하는 것을 방지하는 것을 목표로 합니다.
Pointer Guard 작업 이해: 포인터의 스크램블(변형)은 64비트 비밀과 XOR한 후 0x11 비트 왼쪽으로 회전하는 PTR_MANGLE
매크로를 사용하여 수행됩니다. 원래 포인터를 복구하기 위한 역작업은 PTR_DEMANGLE
에 의해 처리됩니다.
공격 전략: 공격은 알려진 평문 접근 방식에 기반하며, 공격자는 비밀을 유추하기 위해 원래 포인터와 변형된 포인터를 모두 알아야 합니다.
알려진 평문 악용:
고정 함수 포인터 식별: glibc 소스 코드나 초기화된 함수 포인터 테이블(예: __libc_pthread_functions
)을 조사하여 공격자는 예측 가능한 함수 포인터를 찾을 수 있습니다.
비밀 계산: __pthread_attr_destroy
와 같은 알려진 함수 포인터와 함수 포인터 테이블에서의 변형된 버전을 사용하여, 변형된 포인터를 역회전(오른쪽 회전)한 후 함수의 주소와 XOR하여 비밀을 계산할 수 있습니다.
대체 평문: 공격자는 0 또는 -1과 같은 알려진 값으로 포인터를 변형하여 메모리에서 식별 가능한 패턴을 생성하는지 실험할 수 있으며, 이러한 패턴이 메모리 덤프에서 발견될 경우 비밀을 드러낼 수 있습니다.
실용적 응용: 비밀을 계산한 후 공격자는 제어된 방식으로 포인터를 조작하여, libc 기본 주소에 대한 지식과 임의의 메모리 위치를 읽을 수 있는 능력을 통해 Pointer Guard 보호를 우회할 수 있습니다.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)