본문으로 바로가기

[pwnable.kr] bof 풀이, write-up

category Wargame/pwnable.kr 2018. 11. 1. 22:40

pwnable.kr --- bof




cmd에 nc pwnable.kr 9000을 입력하면 접속할 수 있다.


이번 문제는 nc를 이용해 문제를 푼다. 따라서 ssh 접속과 다르게 cat으로 값을 넘겨 주어야 한다.


우분투에서 wget을 통해서 문제와 파일을 다운받았다.






bof elf 파일이 있고, bof.c의 내용은 아래와 같다.


buffer overflow의 가장 기초적인 모습이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;
}
cs



main 함수부터 차례차례 bof.c를 이해해보자


func 함수를 호출하는데 인자로 "0xdeadbeef"를 전달해준다.



1
func(0xdeadbeef);                                                                    
cs



fucn 함수 내에서 지역변수 char overflowme[32]를 선언한다.

"overflowme : "를 출력한다.



1
2
char overflowme[32];
printf("overflow me : ");                                                            
cs



사용자로부터 overflowme buffer에 입력을 받는다.



1
gets(overflowme);                                                                    
cs


만일 key == 0xcafebabe 이면 쉘을 실행하고 다르면 "Nah..\n"를 출력한다.



1
2
3
4
if(key == 0xcafebabe
    system("/bin/sh");
else
    printf("Nah..\n");                                                                
cs



bof.c의 메모리 구조를 나타내면 간단히 아래와 같이 나타낼 수 있다.





예상해 본 메모리 구조는 위와 같지만 compiler가 최적화를 위해 중간 중간에 dummy를 삽입할 수 있다.


따라서 gdb를 통해 정확히 overflowme와 0xdeadbeef 사이의 byte 공간을 알아야 한다.


set disassembly-flavor intel을 통해 intel 문법으로 assembly를 바꿀 수 있다.





func 함수에 변수가 총 72(0x48) byte 만큼 할당되어 있는 것을 알 수 있다.


func 함수의 disassembly 코드를 보면 총 4번의 call이 보인다.


각각 printf(), gets(), system(), printf() 인것을 알 수 있다.


gets의 인자로 overflowme가 들어가고 [ebp - 0x2c] 위치에 있는것을 확인할 수 있다.


key는 0xcafebabe와 compare하기 때문에, key는 [ebp + 0x08] 번지에 있는 것을 확인할 수 있다.


다시 메모리 구조를 그려보면 아래와 같이 그릴 수 있다.





52 byte의 패딩과 4 byte의 key 값으로 overflow 시키면 된다.