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