gets 로 인 한 혈액 사건

다음으로 이동:http://hi.baidu.com/david_jlu/blog/item/3f742b1b74284a1a8618bf80.html
   /* DO NOT USE THIS FUNCTION!! There is no limit on how much it will read. * / 다음은 gets 의 소스 코드 를 살 펴 보 겠 습 니 다.
 1 char *
 2 gets(char *str){
 3         char *cp;
 4         int c;
 5         if ((stdin->flags & __SRD) == 0)
 6                 return NULL;
 7         for (c = 0, cp = str; c != '
'
; cp++) { 8                 if ((c = getchar()) == EOF) { 9                         stdin->flags |= __SERR; 10                         return NULL; 11                  } 12                  *cp = (char)c; 13          } 14          *--cp = '\0'; 15         return str; 16 }

’ , , str , str ? , fget : 1 char * 2 fgets(char *as, int n, FILE *f){ 3         int c; 4         char *s=as; 5          c = EOF; 6         while(n>1 && (c=getc(f))!=EOF){ 7                  *s++=c; 8                  --n; 9                 if(c=='
'
) break; 10          } 11         if(c==EOF && s==as 12                          || ferror(f)) return NULL; 13         if(n) *s='\0'; 14         return as; 15 }
── (Buffer Overflow)。 1988 11 , “Morris ” Internet ,“Morris ” Internet 10% 。2001 7 , “Code Red” IIS Web Server 300000 。2003 1 ,“Slammer” Microsoft SQL Server 2000 , Internet , , 、 。 。 ? : 1 void print_input(int a,int b) { 2         char str[3]; 3          gets(str); 4          puts(str); 5 } 6 int main(int argc, char * argv[]) { 7          print_input(1,2); 8         return 0; 9 }

컴 파일 후 (gcc 플러스 - g) gdb 로 디 버 깅 하고 정지점 을 gets 후 정지점 으로 직접 continue 하여 현재 상 태 를 봅 니 다.
(gdb) bt
#0 print_input (a=1, b=2) at study.c:5
#1 0x080483e7 in main () at study.c:9
(gdb) p &a
$3 = (int *) 0xbfed95c0
(gdb) p &b
$4 = (int *) 0xbfed95c4
(gdb) p &str
$5 = (char (*)[3]) 0xbfed95b5
(gdb) x/3b 0xbfed95b5
0xbfed95b5:     0x41    0x42    0x00      #여기 '1' 과 '2' 는 제 가 실행 할 때 입력 한 str 입 니 다.
여기 서 스 택 구역 은 높 은 주소 에서 낮은 주소 로 연장 되 었 음 을 알 수 있 습 니 다. 즉, 높 은 주 소 는 스 택 밑 의 낮은 주 소 는 스 택 꼭대기 이 고 현재 메모리 상태 입 니 다.
0xbfed95b5 0xbfed95b6 0xbfed95b7 ………… 0xbfed95c0 0xbfed95c4
      str[0]            str[1]             str[3]                             a                b
중간 에 8 개의 바이트 가 있 는데 뭐 죠?컴 파일 을 배 웠 다 면 주 소 를 되 돌려 주 는 것 이 있 을 것 이다. 그렇지 않 으 면 실행 할 것 이다.
완 printinput 어떻게 main 으로 돌아 가 죠?!안 믿 어 봐.
(gdb) x/4b 0xbfed95bc
0xbfed95bc:     0xe7    0x83    0x04    0x08        #이게 바로 귀환 주소 0x080483e 7 입 니 다.
(gdb) x/4b 0xbfed95b8
0xbfed95b8:     0xd8    0x95    0xed    0xbf
(gdb) disassemble main                                    #main 함수 에 대한 어 셈 블 리
Dump of assembler code for function main:
0x080483c2 :    lea    0x4(%esp),%ecx
0x080483c6 :    and    $0xfffffff0,%esp
0x080483c9 :    pushl 0xfffffffc(%ecx)
0x080483cc :   push   %ebp
0x080483cd :   mov    %esp,%ebp
0x080483cf :   push   %ecx
0x080483d0 :   sub    $0x14,%esp
0x080483d3 :   movl   $0x2,0x4(%esp)
0x080483db :   movl   $0x1,(%esp)
0x080483e2 :   call   0x80483a4
0x080483e7 :   mov    $0x0,%eax                            #함수 가 실행 되면 여기 로 돌아 가 야 합 니 다.
0x080483ec :   add    $0x14,%esp
0x080483ef :   pop    %ecx
0x080483f0 :   pop    %ebp
0x080483f1 :   lea    0xfffffffc(%ecx),%esp
0x080483f4 :   ret    
End of assembler dump.
위 에서 볼 수 있 듯 이 a 변수 왼쪽 에 있 는 것 이 바로 주 소 를 되 돌려 주 는 것 입 니 다. 즉, call 0x80483a 4 < print 입 니 다.input>
의 다음 지령, 그럼 또 하나의 빈 자 리 는 무엇 입 니까?0xbfed 95b 8 대응 은 스 택 포인터 sp 입 니 다. 이것 은 있 으 나 마 나 합 니 다.
현재 메모리 상태 그림:
0xbfed95b5 0xbfed95b6 0xbfed95b7 0xbfed95b8 0xbfed95bc 0xbfed95c0 0xbfed95c4
      str[0]            str[1]             str[3]          %sp          ret 주소            a                 b
현재 문 제 는 gets 에서 경 계 를 검사 하지 않 습 니 다. 긴 문자열 을 입력 하면% sp 와 주 소 를 덮어 씁 니 다.
이것 은 cracker 가 주 소 를 되 돌려 쓸 수 있 음 을 의미 합 니 다. printinput 가 완료 되면 되 돌아 갑 니 다. 되 돌아 오 는 것 은 아 닙 니 다.main
 ,cracker 가 실행 하고 자 하 는 악성 코드 로 돌아 가 는 것 입 니 다.
첨부: C 언어의 위험 함수
함수.
심각 성
해결 방안
gets
가장 위험 하 다
fgets (buf, size, stdin) 를 사용 합 니 다.이것 은 거의 항상 큰 문제 다!
strcpy
위험 하 다
strncpy 로 변경 합 니 다.
strcat
위험 하 다
strncat 로 변경 합 니 다.
sprintf
위험 하 다
snprintf 를 사용 하거나 정밀도 설명 자 를 사용 합 니 다.
scanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
sscanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
fscanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
vfscanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
vsprintf
위험 하 다
vsnprintf 를 사용 하거나 정밀도 설명 자 를 사용 합 니 다.
vscanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
vsscanf
위험 하 다
정밀도 설명 자 를 사용 하거나 스스로 해석 합 니 다.
streadd
위험 하 다
분 배 된 목적지 의 매개 변수 크기 가 원본 매개 변수 크기 의 4 배 임 을 확보 합 니 다.
strecpy
위험 하 다
분 배 된 목적지 의 매개 변수 크기 가 원본 매개 변수 크기 의 4 배 임 을 확보 합 니 다.
strtrns
위험 하 다.
목적지 크기 가 최소한 원본 문자열 과 같 는 지 수 동 으로 확인 합 니 다.
realpath
위험 합 니 다.
할당 버퍼 크기 는 MAXPATHLEN 입 니 다.마찬가지 로 입력 매개 변수 가 MAXPATHLEN 을 초과 하지 않도록 수 동 으로 파 라 메 터 를 검사 합 니 다.
syslog
위험 합 니 다.
문자열 입력 을 이 함수 에 전달 하기 전에 모든 문자열 입력 을 합 리 적 인 크기 로 자 릅 니 다.
getopt
위험 합 니 다.
문자열 입력 을 이 함수 에 전달 하기 전에 모든 문자열 입력 을 합 리 적 인 크기 로 자 릅 니 다.
getopt_long
위험 합 니 다.
문자열 입력 을 이 함수 에 전달 하기 전에 모든 문자열 입력 을 합 리 적 인 크기 로 자 릅 니 다.
getpass
위험 합 니 다.
문자열 입력 을 이 함수 에 전달 하기 전에 모든 문자열 입력 을 합 리 적 인 크기 로 자 릅 니 다.
getchar
중등 위험
순환 에서 이 함 수 를 사용 하면 버퍼 경 계 를 확인 합 니 다.
fgetc
중등 위험
순환 에서 이 함 수 를 사용 하면 버퍼 경 계 를 확인 합 니 다.
getc
중등 위험
순환 에서 이 함 수 를 사용 하면 버퍼 경 계 를 확인 합 니 다.
read
중등 위험
순환 에서 이 함 수 를 사용 하면 버퍼 경 계 를 확인 합 니 다.
bcopy
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
fgets
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
memcpy
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
snprintf
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
strccpy
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
strcadd
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
strncpy
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.
vsnprintf
낮은 위험
버퍼 크기 가 말 한 것 만큼 크 도록 하 세 요.

좋은 웹페이지 즐겨찾기