이번에 풀어볼 문제는 bof문제이다 bof는 buffer over flow공격 기법으로 많이 알려진 공격기법의 명칭이다.
우선 들어가기 전에 이전문제들과는 다른 화면을 볼 수 있다.
본래라면 연결할 주소만 줄 터인데 실행파일을 다운로드할 수 있는 링크와 과 소스코드를 볼 수 있는 주소, 그리고 연결하면 뭔가 입력할 수 있는 프로그램(?)을 연결 해주는 nc명령어가 덩그라니 있다.
우선 우리가 해야할 일은 언제나 소스코드인 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;
}
이 코드는 아무래도 nc로 연결하면 실행되는 프로그램이 아닌가 싶다. 따라서 이 코드를 해석하면 문제를 쉽게 풀 수 있을 것이다.
main함수에서는 func함수에 0xdeadbeef라는 값을 key에 넘겨주면서 실행시킨다. 그렇다면 func함수만 해석하면 될 것 같다.
코드를 보니 대놓고 자기를 공격해달라는 문자열을 볼 수 있다. 이건 제처두고 이 문제를 풀려면 key에 있는 값과 cafebabe라는 값이 같으면 쉘을 실행해주는 듯 하다.
smash me!가 있는 부분이 가장 수상하니 한번 보자 gets라는 명령어로 입력을 받아 overflowme라는 변수에 저장한다.
bof문제 답게 overflowme라는 변수의 값을 넘어서서 key라는 변수가 있는 곳을 변조해주어야 하는 것 같다.
변조해 주려면 deadbeef라는 값이 어느 주소의 위치에 있는지를 우선 알아야 하기 떄문에 gdb로 해석해봐야 할 것 같다.
조건 : key = cafebabe
필요한 것 : key와 overflow 사이의 거리
우리가 key값을 원하는 값으로 바꿔주기 위해서는 입력이 가능한 overflowme와의 거리를 알 필요가 있다.
# overflowme에서 key값 전까지 dummy값을 넣어주고 key값을 변조한다.
그러기 위해서는 메모리의 구조를 알아야 한다.
메모리 구조는 알았으니 이제 overflow부터 key가 있는 주소까지 몇 byte 떨어져있는지만 알면 된다.
# linux환경인 kali 내에 있는 gdb라는 해석툴로 디버깅 해볼 것이다. 다운로드를 kali 내에서 주소를 입력해 bof 실행 파일을 다운받을 수도 있지만, 나는 vmware를 사용하기 때문에 vm tool을 사용해서 파일을 옮겨주어 사용했다.
다운로드받은 파일의 위치로 이동해서 gdb -q bof명령어를 입력해보자 그러면 gdb를 이용해서 bof파일을 디버깅할 수 있게 된다.
gdb로 들어온 뒤 disas명령어를 이용해서 func과 main을 열어보면 어셈블리된 코드들이 나오는데, 그 중에서 cafebabe와 key값을 비교하는 부분에 break포인트를 걸어서 한번 실행시키면 스택에 0xdeadbeef라는 값이 쌓이게 될 텐데 이 값이 있는 위치가 key변수의 주소가 될 것이다.
이제 b *func+40으로 break포인트를 건뒤 r명령으로 한번 실행시켜 아무 값이나 입력해주고, x/30x $esp명령어로 esp로부터 30개의 값들의 정보를 보면 deadbeef를 찾을 수 있다.
이제 저 것들을 읽으면 몇byte만큼 key값이 떨어져있는지 알 수 있다. aaa를 여러번 입력했으니 같은 수가 많이 나올텐데 마침 0x61616161이라는 값들이 많이 있었다. ( 아스키코드에서 61 = a )
그리고 마침 deadbeef도 보였다. a값이 들어간 주소를 보니 0xffffd26c에서 시작했고 0xdeadbeef는 0xffffd2a0에서 시작했다. 그러니 0xffffd2a0 - 0xffffd26c를 하면 0x38이 나오는데 이는 10진수로 52byte이다.
우리가 필요한 걸 얻었으니 페이로드를 짜면 다음과 같다.
payload = (python -c 'print "A" * 52 + "\xbe\xba\xfe\xca"';cat ) | nc pwnable.kr 9000
#key변수 전까지를 A로 채운뒤 값을 리틀 엔디안 방식으로 넣어준 뒤 출력하는 payload와 파이프 ( | )를 이용해서 연결해주면 다음과 같이 쉘이 따진다.
flag : daddy, I just pwned a buFFer :)
'Hacking > Pwnable' 카테고리의 다른 글
[ pwnable.kr ] random 문제 풀이 (0) | 2019.09.04 |
---|---|
[ pwnable.kr ] passcode 문제풀이 (0) | 2019.08.30 |
[ pwnable.kr ] flag 문제풀이 (0) | 2019.08.30 |
[ pwnable.kr ] collision 문제 풀이 (0) | 2019.08.27 |
[ pwnable.kr ] fd 문제풀이 (0) | 2019.08.23 |