imnyang's workspace

뒤로

포맷 스트링#

printf는 포맷 스트링을 사용하여 값을 원하는 형식으로 출력해요.

printf("%d\n", 123);
printf("%s\n", "Hello");
printf("%p\n", address);
c

대표적인 형식 지정자는 다음과 같아요.

형식 지정자설명
%d정수 출력
%x16진수 출력
%s주소가 가리키는 문자열 출력
%p주소 출력
%n지금까지 출력한 문자 수를 메모리에 저장

인자의 위치를 직접 지정할 수도 있어요.

%7$p
text

위 포맷 스트링은 일곱 번째 인자를 주소 형태로 출력해요.

FSB#

포맷 스트링 버그(Format String Bug, FSB)는 사용자 입력을 printf의 포맷 스트링으로 직접 사용했을 때 발생해요.

char format[0x100];

scanf("%255s", format);
printf(format);
c

사용자가 %p, %s, %n 등을 입력하면 printf가 레지스터와 스택의 값을 인자로 해석해요.

%p → 레지스터 또는 스택 값 출력
%s → 해당 값을 주소로 사용하여 메모리 읽기
%n → 해당 값을 주소로 사용하여 메모리 쓰기
text

따라서 포맷 스트링 버그를 이용하면 주소를 유출하거나 메모리의 값을 읽고 쓸 수 있어요.

임의 주소 읽기#

%s는 인자를 문자열이 저장된 주소로 사용해요.

%7$s
text

일곱 번째 인자 위치에 읽고 싶은 주소가 있다면 해당 주소의 데이터를 문자열로 출력해요.

페이로드 뒤에 주소를 직접 넣는 방식도 사용할 수 있어요.

payload = b"%7$s"
payload = payload.ljust(8, b"a")
payload += p64(target_address)
py

정확한 인자 번호는 실행 환경과 스택 구조에 따라 달라져요. 일반적으로 %p를 반복하여 입력값이 나타나는 위치를 찾아요.

AAAA.%1$p.%2$p.%3$p...
text

임의 주소 쓰기#

%n은 현재까지 출력된 문자 수를 인자로 받은 주소에 저장해요.

int num;

printf("AAAA%n", &num);
c

AAAA는 네 글자이므로 num에는 4가 저장돼요.

Width를 사용하면 원하는 수만큼 문자를 출력할 수 있어요.

%31337c%8$n
text

위 포맷 스트링은 31337개의 문자를 출력한 뒤 여덟 번째 인자가 가리키는 주소에 31337을 기록해요.

기록하는 크기는 길이 지정자로 조절할 수 있어요.

%hhn → 1바이트
%hn  → 2바이트
%n   → 4바이트
text

큰 값을 기록할 때는 %hhn을 사용하여 한 바이트씩 나누어 쓰는 방법을 사용할 수 있어요.

예를 들어 0xdeadbeef는 리틀 엔디언 환경에서 다음 순서로 저장돼요.

낮은 주소
ef be ad de
높은 주소
text

따라서 각각의 바이트를 target, target + 1, target + 2, target + 3에 기록하면 돼요.

방지 방법#

그냥 포맷 스트링을 쓰면 해결돼요.

printf(user_input);       // 취약
printf("%s", user_input); // 안전
c

문자열만 출력한다면 putsfputs를 사용할 수도 있어요.

puts(user_input);
fputs(user_input, stdout);
c

포맷 스트링을 고정하고 사용자 입력은 별도의 인자로 전달하는 것이 가장 중요해요.

-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg4c/dn4BitGH1/xNjKoKEp97I2b
eU57QXvkDBEdNNrEMAAAATYmxvZy5pbW55YS5uZy9wb3N0cwAAAAAAAAAGc2hhNTEyAAAA
UwAAAAtzc2gtZWQyNTUxOQAAAECyhgad3dpzvi/czJk5py52oUHvnQfugEbZbIV1mwzJEW
33sOR4mW89euaiPldAzE/zELf2jZXQJdIG7a8ys5oP
-----END SSH SIGNATURE-----
[Layer7] 2026년 8월 3일 시스템 해킹 5차시 과제
http://blog.imnya.ng/layer7/17
저자 imnyang
게시일 2026년 08월 04일