1. 포맷 스트링 공격(Format String Attack)
- 프로그램에 입력된 문자열 데이터가 명령으로 해석될 때 발생
- 공격자는 코드를 실행하거나 메모리 일부를 읽거나 실행중인 프로그램에 Segmentation Fault를 발생시켜 시스템에 의도되지 않은 동작을 유발
1.1 포멧 스트링 3가지 개념
① 포맷 함수(Format Function)
- printf, fprintf와 같은 ANSI C 함수
- ex) printf(), scanf() ...
② 포맷 스트링(Format String)
- 포맷 함수의 인자이며 다음과 같은 텍스트 및 포맷 인자를 포함하는 ASCII 문자열
- ex) printf("number : %d\n", 1);
③ 포맷스트링 인자(Format String Parameter)
- %x %s 등으로 포맷 함수의 변환 형태를 정의
- 프로그램이 전달된 스트링 입력의 유효성을 제대로 확인하지 않으면 취약점이 노출됨.
인자 | 입력 타입 | 출력 |
%d | 값 | 10진수 |
%s | 포인터 | 포인터에 위치하는 문자열 |
%x | 값 | 16진수 |
%u | 값 | 부호없는 10진수 |
%p | 포인터 | 포인터가 가르키는 주소 |
%n | 포인터 | 지금까지 출력한 바이트수를 포인터가 가르키는 주소에 넣어줌 |
1.2 예시
- 포맷 스트링 공격에 안전한 경우(위)와 취약한 경우(아래)를 비교하여 확인
1.3 포맷 스트링 공격 대응방안
① 서식문자열을 함수의 입력 파라미터로 직접 사용하지 않음 즉, 정확한 포맷스트링의 지정이 필요
ex) printf(argv[1]) -> printf("%s", argv[1])
② 포맷 스트링에 취약한 함수를 사용하지 않음
ex) fprintf(), sprintf(), snprintf() ...
2. 풀이
- 80byte 배열 bleh를 선언한 후 setruid 실행 및 fgets로 79byte까지 입력값을 받아 버퍼오버플로우는 불가능함
- main 심볼이 없어 gdb를 사용할 수 없음
- hint 파일의 내용 중 print(bleh); 구문에서 포맷 스트링 공격이 가능함
- attackme 실행 후 %08x의 개수를 증가시킬 경우 12byte 이후 삽입한 문자열이 출력되는 것을 확인할 수 있으므로 스택의 구조를 예상해 볼 수 있음
- level20에서는 쉘코드를 환경변수에 등록하여 환경변수의 주소를 등록한 후 해당 환경변수의 주소를 RET에 덮어쓰는 기존의 방식은 사용하지 못함
- bleh와 SFP 사이에 존재하는 dummy의 크기를 모르기 때문이며, 따라서 다른 값에 환경변수의 주소를 덮어써야함
- 따라서 main()이 종료되고 .dtors가 실행되기전에 .dtors값을 쉘코드로 덮어써야함
- objdump 명령으로 .dtors의 세그먼트 주소는 0x08049594이며, .dtros의 시작 주소는 0x08049598
- +4를 해주는 이유는 다수의 .dtors 영역에서 실행이 되게 하기 위해서는 +4를 해줘야 한다고 함(정확한 이유는 확인 중)
- .dtros의 시작 주소 0x08049598에 환경변수 주소 0xbfffff2d를 덮어써주면 됨
- 쉘코드 주소 0xbfffff2d는 10진수로 3,221,225,261로 int형 범위를 넘어서게 되므로 소멸자를 2바이트씩 나누어 넣어줘야하며, 이때 %n 지정자 사용
- 소멸자를 낮은 주소와 높은 주소로 나누어보면 0x08049598이 낮은 주소, 0x08049598+2=0x0804959a가 높은 주소
- 쉘코드 환경변수의 낮은 주소는 ff2d(65,325), 높은 주소는 bfff(49,151)
- 따라서, 페이로드 형식은 다음과 같음
AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%낮은 셸 코드주소c%n%높은 셸 코드주소c%n
- %[숫자]c의 경우 [숫자] 만큼의 공백을 의미하며, %n은 이전 입력 값까지 더하여 저장하게됨
- 따라서 %낮은 셸 코드주소c%n의 경우 65,325-(4 + 4 + 4 + 4 + 8 + 8 + 8)=65,285
- %높은 셸 코드주소c%n의 경우 49,151-65,325=-16,174, 음수가 발생하므로 bfff의 2의보수에 65,325를 빼주어 높은 쉘코드를 구함=114687-65,325=49,362
- 즉 완성된 페이로드는 다음과 같음
AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%65285c%n%49362c%n
'문제풀이 > FTZ' 카테고리의 다른 글
FTZ Level19 풀이 (0) | 2022.11.08 |
---|---|
FTZ Level18 풀이 (0) | 2022.11.07 |
FTZ Level17 풀이 (0) | 2022.11.07 |
FTZ Level16 풀이 (0) | 2022.11.05 |
FTZ Level15 풀이 (0) | 2022.11.05 |