본문 바로가기

Security/System Hacking

No.3 Format 스트링

(1) Format 스트링기법 

 

포맷 스트링은 발신자 즉, 보내는 사람을 속여서 받는 사람으로 하여금 받는 파일의 신뢰를 가게 하는 방법입니다.

 

예를 들어 봅시다.

abc.c

 

#include <stdio.h>

 

main() { 

char *buffer = "heeman";

printf ("%s\n", buffer);

}

 

위에서 %s 와 같은 문자열이 바로 포맷 스트링입니다.

이러한 포맷 스트링 문자를 이용하여 작성하면 취약점이 발생되지 않지만.

포맷 스트링 문자를 이용하지않고 printf와 같은 함수를 이용하면 문제가 발생됩니다.

 

abcd.c

 

#include <stdio.h>

 

main() {

char *buffer = " heeman\n";

printf(buffer);

}

 

위와 같이 짜게되면 보안상 매우 위험하게 됩니다. 위의 예제를 조금 변형해보겠습니다.

 

abcde.c

 

#include <stdio.h>

main () {

char *buffer = "heeman\n%x\n";

printf(buffer);

}

 

이때 %x(16진수로표현) 입니다.

 

결과 : [root@heemanhost ~]# ./a.out
heeman
804822c
이런 식으로 나옵니다

이때 8024822c는 heeman이라는 문자열이 저장된 다음의 메모리에 존재하는 값을 나타냅니다.

자 이렇게 되면 메모리의 내용을 보는것과 마찬가지입니다.

그럼 메모리의 내용을 변조 해보겠습니다

 

abcded.c

 

#include <stdio.h>

 

void main(int argc, char *argv[]) {

int i = 5;

pirntf("최초 i의 값 : %d\n", i);

printf("%s%n\n", argv[1], &i);

printf("변경된 i의 값 : %d\n", i);

}

 

결과 :

[root@heemanhost ~]# ./a.out aaaaa
before i result : 10
aaaaa
after i result : 5

위와 같이 나오는 이유는?

문제는 printf("%s%n\n", argv[1], &i) 입니다.

먼저 이 명령은 argv[1] 즉 aaaaa를 문자열(%s)로 바꾼 뒤 , 해당 문자열의 개수를 세어 그 값을 i의 주소값에 입력합니다.

즉 컴파일후 실행해서 보면 입력된 a의 개수로 i의 값이 변경된 것을 확인 할수 있습니다.

%s 뒤의 %n이 개수를 세는 역할을 한것입니다.

 

결론 : 포맷 스트링공격은 포맷 스트링을 이용하며 버퍼 오버플로우와 같이 메모리에 셸을 띄워놓고, ret값을 변조하여 관리자 권한을 얻는 것입니다. 방식은 같으나 방법만 다를뿐입니다.

 

[출처] No.3 Format 스트링|작성자 Securely