#include <stdio.h> // C++ 에서는 <cstdio>
int sprintf(char* str, const char* format, ...);
str에 데이터를 형식에 맞추어 쓴다. str 가 가리키는 배열에 형식 문자열에 지정한 방식 대로 C 문자열을 쓴다. 쉽게 설명하자면, printf에서 화면에 출력하는 대신에 화면에 출력할 문자열을 인자로 지정한 문자열에 쓴다는 것이다. 이때, 인자로 지정한 배열의 크기는 배열에 쓰일 문자열의 크기보다 커야만 한다. 주의할 점은 sprintf 함수는 자동적으로 str 맨 마지막에 NULL 문자를 붙이기 때문에 항상 한 칸의 여유가 있어야 한다.
[그림 1-1] 코드에서 argv[1] 으로 입력을 받고 입력한 값을 printf 하여 buffer 변수에 넣는다.
gdb로 분석하면 [그림 1-1]처럼 스택이 그려진다. 즉, buffer를 다 채우고 target에 "deadbeef" 문자열을 넣어야 한다.
#include <stdio.h>
int main()
{
int a = 230;
printf("%10d", a);
return 0;
}
위 출력값은 빈칸 7개와 230 이다. 즉, %Nd 이란 N개를 출력하는데 전달받은 값이 N개를 만족하지 못하면 만족할 때까지 앞에 패딩을 넣어준다.
성공
gdb를 이용해 분석해보자
[그림 1-3]처럼 인자값을 전달한 후 sprintf 하기 전 [그림 1-4] arg [0], arg [1]를 보면 buffer 변수 주소와 사용자가 입력한 argv [1] 주소가 들어가 있다.
printf("%64d\xef\xbe\xad\xde") 을해서 buffer에 넣는다.
sprintf 실행 후 buffer 변수 값을 확인해 보면 0x20이 많이 들어가 있다. 0x20 은 SP인데 space이다. -> 패딩
결국 64개를 채우고 target 위치에 문자열이 들어가게 되는 거다.
어떤 포맷 스트링이 와도 상관없다. 값을 채우기만 하면 되기 때문!