environ

oogu ㅣ 2023. 3. 6. 22:18

// Name: environ.c
// Compile: gcc -o environ environ.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

void sig_handle() {
  exit(0);
}

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  signal(SIGALRM, sig_handle);
  alarm(5);
}

void read_file() {
  char file_buf[4096];
  int fd = open("/etc/passwd", O_RDONLY);
  read(fd, file_buf, sizeof(file_buf) - 1);
  close(fd);
}

int main() {
 
  char buf[1024];
  long addr;
  int idx;
  init();

  read_file();

  printf("stdout: %p\n", stdout);

  while (1) {
    printf("> ");
    scanf("%d", &idx);
    switch (idx) {
      case 1:
        printf("Addr: ");
        scanf("%ld", &addr);
        printf("%s", (char *)addr);
        break;
      default:
        break;
    }
  }
  return 0;
}

[그림 1-1]

이 문제는 로컬에서 푸는 문제이다.

모든 보호 기법이 걸려있다...

stdout 라이브러리 주소를 출력해주니 libc base 주소를 구할 수 있고 case 1:을 통해 임의 주소의 값을 읽을 수 있는 취약점이 존재한다.

 

익스플로잇 시나리오

1. __environ 주소 계산

[그림 1-2]
[그림 1-3]

 

[그림 1-2]는 stdout 라이브러리 주소를 이용해 libc base 주소와 전역 변수 __environ 주소를 얻어온다.

[그림 1-3] 주소 확인가능

 

2. 스택 주소 계산

__environ 주소를 알아냈다면, 임의 주소 읽기 취약점을 통해 스택 주소를 알아내고, "/etc/passwd" 파일의 내용이 저장된 스택 버퍼의 주소를 계산합니다. 해당 주소는 환경 변수와 상대적인 거리가 매번 같으므로, 디버깅을 통해 간격을 알아냅니다.

[그림 1-4]

read_file+77에서 rsi 값이 파일 내용이 들어가는 스택 주소이다.

[그림 1-5]
[그림 1-6]

[그림 1-5] rsi 값을 [그림 1-6] 처럼 확인해보면 "/etc/passwd" 파일 내용이 들어가 있다.

[그림 1-7]

노란색 주소 : 전역변수 __environ 위치

빨간색 주소: 스택 위치

[그림 1-8]

빨간색 주소와 파일 내용("/etc/passwd")이 존재하는 스택 주소를 빼면 [그림 1-8]이 나온다.

앞서 말했드시 환경 변수와 거리가 상대적으로 같아 __environ 값에서 0x1538을 빼면 파일 내용 스택 주소가 나온다.

 

3. 파일 내용 읽기

[그림 2-1]

[그림 2-1]은 최종 payload이다.
libc_env는 전역 변수 주소이고 값으로는 스택 주소를 가지고 있다. 따라서 임의 주소 읽기 취약점을 이용해 스택 주소(env)를 알아오고 그 값을 0x1538로 빼면 파일 내용이 존재하는 스택 주소가 된다.

[그림 2-2]

익스를 하면 [그림 2-2] 처럼 "/etc/passwd" 파일 내용이 출력된다.

 

 

 

알게 된점

1. 프로세스에는 환경 변수 정보를 항상 가지고 있고 필요할 때마다 가져와서 사용한다.

2. 환경 변수에 대한 정보는 스택 영역에 존재한다.

3. __environ 라이브러리 주소를 알고 있고, 임의의 주소를 읽을 수 있는 취약점이 있다면 스택 주소를 알아낼 수 있다.

'Dreamhack - pwnable' 카테고리의 다른 글

Sigreturn-Oriented Progamming  (0) 2023.03.14
rtld  (0) 2023.03.12
master_canary  (1) 2023.02.15
seccomp  (0) 2023.02.13
cmd_center  (0) 2023.02.03