Format String Bug
개발자의 실수로 printf(buf) 이렇게 사용했을 때 입력 값을 포맷 스트링으로 넣으면 입력값을 문자로 취급하는게 아닌, 서식문자로 취급하여 취약점이 일어난다.
#include<stdio.h>
int main(){
char str[0x10];
scanf("%s", str);
printf("올바른 출력: %s\n", str);
printf(str);
return 0;
}
printf(str)
에서 포멧스트링 버그가 일어난다.
str에 hello%x
를 입력하면printf(str) = printf("Hello%x")
와 같은 동작을 한다.
printf 함수는 가변 함수로 인자의 개수는 포맷 문자 개수로 결정된다.
포멧 스트링을 사용하는 대표적인 함수는 다음과 같은데
printf, sprintf, snprintf, fprintf, vprintf, vfprintf, vsprintf, vsnprintf, scanf 등이 있다.
Format String
$[parameter][flags][width][.precision][length]type
- specifier
- width
포멧 스트링 종류
인자 | 입력타입 | 출력 |
%d | 값 | 10진수 |
%s | 포인터 | 포인터에 위치하는 문자열 |
%x | 값 | 16진수 |
%u | 값 | 부호없는10진수 |
%p | 포인터 | 포인터가 가르키는 주소 32bit에서 4바이트 64bit에서 8바이트 |
%n | 포인터 | 지금까지 사용된 문자열의 길이를 포인터가 가르키는 주소에 넣어줌 |
이런식으로 된다.
기본적으로 $n 같은 경우는 4바이트 인데 더 많은 바이트 또는 적은 바이트를 쓰고 싶으면 아래와 같이 쓸 수 있다.
바이트ln 6바이트
바이트hn 2바이트
$hhn 1바이트
x64의 경우
x64의 경우에는 함수호출 규약에 따라 레지스터를 사용하기 때문에
%p 로 릭을 할 경우 6혹은 7번째 부터 스택의 값이 릭된다.
FSB 로 exploit
$(달러플래그) 를 이용하면 된다.
%2$p 를 하면 2칸 아래 영역을 가르키게 된다.
이걸 응용하면 스택이 7번째 라고 치면 %7$n 으로 하면 7번째에 적힌 주소를 포인터로 해서 지금까지 쓴 문자열을 그 주소에 쓰게 되는 것이다.
* (asterisk)
- width
* 는 너비를 정해주는 너비 지정자 인데 이걸 이용하면 libc leak 없이도 libc를 사용할 수 있는 트릭이된다.
이 글은 옵시디언을 이용해서 작성되었습니다.
'TOOR' 카테고리의 다른 글
[TOOR] 17. Race Condition (0) | 2023.10.02 |
---|---|
[TOOR] 16.1 OOB (Out of Bound) (0) | 2023.10.02 |
[TOOR] 14. RELRO (0) | 2023.09.29 |
[TOOR] 13.1. PIE (0) | 2023.09.29 |
[TOOR] 12.3. SROP (0) | 2023.09.24 |