Pointer Redirecting

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

문자열 포인터

함수 호출이 stack에 위치한 문자열의 주소를 사용할 경우, buffer overflow를 악용해 이 주소를 덮어쓰고 바이너리 내의 다른 문자열의 주소를 넣는 것이 가능합니다.

예를 들어 어떤 system 호출이 커맨드를 실행하기 위해 스택에 있는 문자열의 주소를 사용할 예정이라면, 공격자는 스택에 다른 문자열의 주소를 넣고 export PATH=.:$PATH 같은 문자열을 배치한 뒤 현재 디렉터리에 새 문자열의 첫 글자와 같은 이름의 스크립트를 만들어 바이너리가 그 스크립트를 실행하게 할 수 있습니다.

실제 타깃에서는 단순히 출력되는 텍스트를 바꾸는 것보다 stack 문자열 포인터를 재지정하는 것이 보통 더 유용합니다:

  • 나중에 호출되는 **system/popen/execl***의 인자를 이미 메모리에 존재하는 "/bin/sh" 또는 공격자가 제어하는 명령 문자열로 리다이렉트.
  • 나중에 발생하는 read sink(예: puts("%s", ptr) 또는 write(fd, ptr, len))를 리다이렉트하여 stack, heap 또는 binary 데이터를 leak.
  • 나중에 발생하는 write sink(예: strcpy(dst, ...), memcpy(dst, src, len) 또는 ptr->field = value 같은 구조체 필드 할당)를 리다이렉트하여 스택 오버플로우를 2단계 임의 쓰기로 전환.

검토할 때는 함수가 반환되기 전이지만 오버플로우 이후에 사용되는 char *cmd, char *path, char *buf, FILE *fp 같은 stack 로컬 변수들이나 임시 요청/응답 구조체 내부의 포인터들을 우선적으로 확인하세요. 이는 canary 때문에 저장된 return address에 안전하게 도달할 수 없거나, 인접한 포인터를 손상시키는 것만으로 충분한 경우 특히 유용합니다.

손상이 부분 덮어쓰기로 제한되는 경우(예: 버그가 0x00을 붙이는 경우), 포인터를 다음으로 리다이렉트해 보세요:

  • 같은 stack frame에 있는 근처 문자열
  • 같은 모듈 / non-PIE 이미지에 있는 다른 객체
  • 상위 바이트(high bytes)가 변경되지 않는 제어 가능한 영역

후행 NUL이 전용 로컬 변수가 아닌 기존 stack 포인터를 변경하는 ASLR 관련 사례는 Ret2ret & Reo2pop를 확인하세요.

예시는 다음에서 찾을 수 있습니다:

함수 포인터

string pointer와 동일한 개념이지만 함수에 적용되는 경우입니다. 만약 stack에 호출될 함수의 주소가 들어있다면, 이를 변경하는 것이 가능하며(예: system 호출하도록) 활용할 수 있습니다.

유용한 대상은 void (*fp)() 같은 명시적 콜백 변수뿐만 아니라 다음을 찾아보세요:

  • 이후 헬퍼 함수에 전달되는 로컬 구조체에 저장된 콜백
  • 에러 경로에서 호출되는 Destructor / cleanup handlers
  • 파서 디스패치 테이블 또는 상태기계 핸들러가 stack으로 복사된 경우
  • 이후 간접 호출로 디스패치하는 로컬 구조체/객체

현대 익스플로잇에서는 pointer redirection이 canary를 건드리기 전에 남아 있는 마지막 프리미티브인 경우가 많습니다. CVE-2024-20017에 대한 2024년 익스플로잇 분석은 전형적인 패턴을 보여줍니다: 오버플로우가 stack의 여러 로컬 변수를 건드리지만 stack canary에는 도달하지 못하고, 공격자는 stack 포인터와 관련된 길이/값을 손상시켜 그 포인터를 통한 이후 할당이 임의 쓰기로 이어지게 합니다(복귀할 필요 없이).

포인터 손상을 통한 2단계 프리미티브

근처 포인터가 이후에 store를 위해 역참조되는 경우, 목표는 보통 처음 오버플로우로 바로 점프하지 않고 프리미티브를 업그레이드하는 것입니다:

  1. 로컬 버퍼를 오버플로우시키고 포인터와 연관된 길이/정수/인덱스를 손상시킨다.
  2. 함수가 ptr->len = x, memcpy(ptr, src, n) 또는 *ptr = value 같은 오버플로우 이후 역참조를 수행하기를 기다린다.
  3. 그 결과 생긴 write-what-where를 사용해 GOT 슬롯, 콜백, 설정 포인터 또는 다른 간접 호출 지점을 덮어쓴다.

이 방법은 다음과 같은 경우에 좋습니다:

  • 버그가 canary에서 멈출 때
  • 함수 포인터 자체에 직접 도달할 수 없을 때
  • 즉시 제어 흐름 탈취보다 4바이트 또는 8바이트 데이터 쓰기가 얻기 쉬울 때

손상된 포인터가 이후 로깅, 출력 또는 네트워크 전송 헬퍼로 전달되는 경우 동일한 아이디어가 read 프리미티브에도 적용됩니다.

Modern AArch64 note: PAC / BTI

현재 AArch64 타깃에서는 전형적인 saved return address overwrite가 epilogue에서 x30을 PAC로 인증하기 때문에 실패할 수 있습니다. 이런 경우, 오버플로우로 인한 로컬 함수 포인터나 콜백 포인터 같은 non-return hijacks가 더 매력적입니다.

다만 BTI가 활성화되어 있다면, 덮어쓴 간접 호출 대상은 여전히 유효한 landing pad에 도달해야 합니다(보통 **bti c**가 있는 함수 엔트리, 또는 PAC가 사용되는 코드에서는 **paciasp/pacibsp**로 시작하는 프로로그). 따라서 AArch64에서 stack 함수 포인터를 리다이렉트할 때는 다음을 선호하세요:

  • 미드-함수 가젯 대신 실제 함수 엔트리
  • 이미 BTI 요건을 만족하는 프로로그를 가진 대상
  • 간접 호출 포인터가 사용 전에 추가로 인증되지 않는 대상

AArch64 stack-overflow 관련 예시는 ret2win-arm64를 확인하세요.

예시는 다음에서 찾을 수 있습니다:

References

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기