티스토리 뷰
4학년 1학기 정보보호 수업으로 수행했던 포맷 스트링 해킹 실습 과제 정리
1. printf()
함수의 취약점
- printf()
함수 처럼 format string을 사용하는 함수는 포맷 인자 (형식 인자)를 함수에 인자로 넘겨 특정 동작을 수행한다.
- 마지막으로 입력된 포맷 스트링 다음에 포맷 스트링 인자가 없다면, 스택의 입장에서, printf 함수가 호출된다
- printf()
는스택의 위에서부터 printf()
의 인자를 위치시킨다.
2. %n
, %hn
포맷 스트링
* 표준 입출력 함수들의 포맷 인자
인자 | 입력 타입 | 출력 타입 |
%d | 값 | 10진수 |
%u | 값 | 부호 없는 10진수 |
%x | 값 | 16진수 |
%s | 포인터 | 문자열 |
%n | 포인터 | 지금까지 출력한 바이트 수 |
%hn | 포인터 | 지금까지 출력한 바이트 수 |
%n
, %hn
: printf()
가 출력하는 바이트 수를 pointer에 저장한다
%n
는 4bytes로 저장%hn
는 2bytes로 저장
-> %n
의 앞에 적절한 값을 주어, %n
이 값을 주소로 여겨서 해당하는 메모리 주소에 출력되는 바이트 수를 저장시킨다
- printf 함수는
%n
포맷 인자를 만나면 이 포맷 인자의 순서에 해당하는 내용을 스택에 pop 하고, pop된 내용을 주소로 이용하여, 해당 주소에 지금까지 출력된 문자의 갯수를 저장하게 될 것이다. - 이때 만약 이 주소가 어떤 함수의 복귀 주소가 저장되어 있는 곳이라면 프로그램의 흐름을 바꿀 수 있다
3. main 함수의 ret (return address)를 알아내서 코드를 짜야 했다. -> gdb 이용
* GDB : GNU 디버거, GNU 소프트 웨어 시스템을 위한 기본 디버거
- 유닉스 기반 시스템에서 동작하는 이식성 있는 디버거
- C, C++, 포트란 등 지원
- GDB같은 디버거의 목적은, 다른 프로그램 수행 중 그 프로그램 '내부'에서 무슨 일이 일어나고 있는지 보여주거나, 프로그램이 잘못 실행되었을 때 무슨 일이 일어나는지 보여주는 것
* GCC : GNU 컴파일러
# 스택 프레임 : 함수가 호출됨에 따라서 데이터를 저장하는 스택 영역
- 프로그램 안에서 function 함수라 불리는 다양한 서브 루틴이 실행 되면서 프레임은 스택 상에 차곡차곡 쌓이게 된다
- 나중에 실행할 때도 반대로 스택에서 하나씩 명령어를 꺼내게 된다