워게임/root-me

ELF x86 - Format string bug basic 2

zz! 2025. 8. 26. 21:31
728x90
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main( int argc, char ** argv )

{

	int var;
	int check  = 0x04030201;

	char fmt[128];

	if (argc <2)
		exit(0);

	memset( fmt, 0, sizeof(fmt) );

	printf( "check at 0x%x\n", &check );
	printf( "argv[1] = [%s]\n", argv[1] );

	snprintf( fmt, sizeof(fmt), argv[1] );

	if ((check != 0x04030201) && (check != 0xdeadbeef))	
		printf ("\nYou are on the right way !\n");

	printf( "fmt=[%s]\n", fmt );
	printf( "check=0x%x\n", check );

	if (check==0xdeadbeef)
   	{
		printf("Yeah dude ! You win !\n");
     		setreuid(geteuid(), geteuid());
     		system("/bin/bash");
   	}
}

snprintf 에서 argv[1] 을 통해 포맷 문자열이 그대로 들어간다. 그래서 %x 나 %n 이나 %hn 이나 등등 포맷 문자를 넣으면 

포맷 스트링 취약점이 발생한다.

check 변수 메모리 주소에 0xdeadbeef를 쓰면 되는 문제이다.

 

먼저 %x %x %x를 넣어서 스택의 값을 확인을 한다. 그리고 %hn 을 통해 2바이트 단위로 값을 덮어 쓴다.

ex) 임의 주소 쓰기가 되는 이유

%1234x%n -> 1234 글자 출력 -> 1234 = 길이가 지정한 주소에 기록된다. 

어떤 주소든 원하는 값 (길이 조절로) 덮어쓸 수 있다.  (아마 fsb에서 가장 이해하기 어려운 부분이 아닐까 싶다 ㅋㅋ)

cccc 로 넣은 것이 9번째에 적혀있다.

 

[check 주소] 첫 번째 %n이 이 주소를 참조해서 값을 씀 

[AAAA] alignment 맞추려고

check + 2 주소 두 번째 %n이 이 주소를 참조해서 값을 씀

%8x * 7 스택에서 값을 꺼내서 출력 스택 offset 맞추기

%48811c$n 총 출력 길이를 48879로 맞추고 %n을 실행함 첫 번째 주소에 0xbeef를 기록하는것

%8126c%n 추가로 8126 글자를 더 출력하고 총 출력 길이가 0xdead가 된다.

%n은 4바이트

 

fsb는 숨쉬듯이 풀려면 비슷한 유형에 문제 10문제는 더 풀어야할듯

728x90