2009-11-15 3 views
7

은 그래서 간단한 버퍼 오버 플로우를 보여줍니다 코드의 간단한 조각이 :C에서 버퍼 오버플로를 잡을 수있는 도구는 무엇입니까?

#include <stdio.h> 

int main(void) 
{ 
    char c[4] = { 'A', 'B', 'C', 'D' }; 
    char d[4] = { 'W', 'X', 'Y', 'Z' }; 

    printf("c[0] is '%c'\n", c[0]); 

    d[4] = 'Z'; /* Overflow that overwrites c[0] */ 

    printf("c[0] is '%c'\n", c[0]); 

    return 0; 
} 

출력 :

$ ./a.out 
c[0] is 'A' 
c[0] is 'Z' 

내가 다음 GCC 옵션을 사용하여이 코드를 컴파일 시도하고 비행과 함께 전달 색상 :

gcc -Wall -Wextra -Wformat=2 -Wswitch-default -Wcast-align -Wpointer-arith \ 
    -Wbad-function-cast -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ 
    -Wcast-qual -Wshadow -Wwrite-strings -Wconversion -Wunreachable-code \ 
    -Wstrict-aliasing=2 -ffloat-store -fno-common -fstrict-aliasing \ 
    -Wstack-protector -fstack-protector-all -std=c99 -pedantic -O0 -ggdb3 

또한 libefence 및 Valgrind의을 시도했다. 리바운드는 힙에 대한 읽기/쓰기를 벗어나지 않기 때문에 통과 할 것으로 예상했지만 valgrind가 통과되면 놀랐습니다.

이 코드는 c [4]와 d [0]이 겹쳐지기 때문에 Segfault를 생성하지 않으며 도구를 놓치게하는 원인이라고 생각합니다.

그래서 무엇이 있습니까? CAN 이걸 잡으시겠습니까? 리눅스에서 작동하는 것은 무료 일 것입니다.

+0

최신 버전을 시도 할 수 있습니다. –

+0

당신 말이 맞아요, 불행하지만 'cppcheck'는 그렇습니다! – SiegeX

+0

실망스러운 gcc는 이것을 잡아 내지 못한다. 필자는 잠시 후에 역 참조가되지 않는 배열 끝 포인터에 대해 가짜로 경고하는 컴파일러 버그를 해결해야한다는 것을 고려해 보았다. http://stackoverflow.com/questions/1168525/c-gcc4-4-warning-array-subscript-is-above-array-bounds를 참조하십시오. 내 생각에 gcc *는 이것을 진단 할 필요가 없지만 옵션을 사용하지 않거나 반대 컴파일러 버그를 찾은 것 같아요. –

답변

5

시도 cppcheck. 그것은 나를 위해 일했습니다.

+0

'cppcheck'에 대한 호의적 인 호명. 전에이 소스 분석기에 대해 들어 본 적이 없지만 * 오류가 있음을 알 수 있습니다! – SiegeX

+1

새 URL은 다음과 같습니다. http://cppcheck.sourceforge.net/ –

+0

@AndrewSchools 감사합니다; URL이 업데이트되었습니다. – Teddy

0

제가 리눅스에 있다면, 먼저 valgrind를 시험해 볼 것입니다. 나는 그것을 처리 할 것이라고 생각합니다.

편집 : SiegeX 나는 (그것을에만 프로세스 실행에 관여으로 스택에 가드를 삽입 할 수있는 방법이 없기 때문에 의미가있는) Valgrind의하지 않는 것 같아요 말한다처럼 인 경우. 그러나 어쨌든 도구 상자에 넣을 가치가있는 좋은 도구이므로 게시를 유지할 것입니다.

+3

Valgrind * 질문에 분명하게 설명되어있는 내용을 포착하지 마십시오. . 이 투표를 중지하십시오. 편집 후 – SiegeX

+0

-1은 정말로 공정하지 않았습니다. – Fredrik

+0

@SiegeX : "Valgrind도 지나치게"외모를 내게 잡습니다. 나는 그것이 힙 할당 된 메모리를 잡으려고 설계 되었기 때문에 나는 그것을 다루지 않을 것이기 때문에 약간 놀랐다고 말해야한다. – Vatine

-1

리터럴 문자열을 참조하기 때문에이 경우 암시 적 null 문자가 있다고 생각합니다. 따라서 d [4]는 여전히 경계에 있습니다 (const char *로 상상해보십시오) .... 나는 부정확 할 수도 있습니다.

+1

내가 이것을 c [5] = "ABCD"로 선언했다면; 컴파일러는 결국 NUL 바이트에 던져 넣었을 것이다. 그러나 NUL 바이트는 4 문자만으로는 공간이 없으므로 버려집니다. 그러나 혼동을 줄이기 위해 초기화에 char을 명시 적으로 사용하도록 코드를 변경했습니다. – SiegeX

2

valgrind가 바이너리에서 작동하므로이 코드에 아무런 이상이 없었습니다. 이 (http://www.thefreecountry.com/programming/debuggers.shtml) 정적 소스 코드 분석기를 확인하십시오. 작동하지 않는다면 PC-lint (http://www.gimpel.com/html/pcl.htm)가이 문제를 처리 할 것입니다 ....

+0

정적 소스 분석기 추천을위한 +1 ... valgrind와 같은 것이 없다면 그 및/또는 동료 리뷰가 가장 많이 붙잡을 가능성이 높습니다. (그리고 그것에 대해 생각하면 valgrind가 그것을 찾지 못할 수는 없습니다. – Fredrik

+0

'debuggers.shtml'링크가 'cppcheck'(허용 대답)에 대해 이야기하지는 않지만이 링크는 그렇지 않은 경우 매우 유용한 링크입니다. 감사합니다 – SiegeX

+0

전에 cppcheck에 대해 들어 보지 못했습니다. 가장 오래된 릴리스는 2007 년 이었으므로 상대적으로 새로운 것입니다. 특히 PC 린트와 비교했을 때 ... – Malkocoglu

1

Rational Purify는 버퍼 오버 플로우, 메모리 누수, 손상 등을 감지하는 데 매우 효과적입니다.

언급 된 mem 패키지 in this SO answer은 다른 옵션 일 수 있습니다.

1

Coverity (정적 분석 도구)가이를 감지합니다.

0

버퍼 오버플로는 런타임까지 발생하지 않으므로 C에서 잡기가 상당히 어렵습니다. 하나의 가능성을 최소화하기 위해 몇 가지 경계 검사를하는 다소 안전한 표준 라이브러리 함수를 사용해야합니다. gets() 대신 fgets()를 사용합니다.

수동으로 많은 수의 배열을 조작하는 경우 알고리즘의 엣지 케이스를 확인하기 위해 단위 테스트를 작성해야합니다. Cmockery은 C에 대한 단위 테스트 프레임 워크의 한 예입니다.

+0

코드 (정적으로)가 * (c + 4)에 액세스하므로 c + 3가 마지막 유효한 주소 인 할당으로이 특정 버퍼 오버런이 catch 할 수있는 컴파일 타임이됩니다. – Vatine

0

자동 및 정적 저장소에서 Valgrind가 오버플로를 catch하지 않습니다. 최소한 기본적으로는 아닙니다. IIRC를 작동 시키려면 기본 옵션 인 "memcheck"가 아닌 일부 옵션을 켜거나 함께 제공된 "개발 중"도구를 실행해야합니다.

+0

필자는 최신 valgrind 3.5.0으로 업그레이드하고 --tool = exp-ptrcheck을 사용했으며 경고 및 오류가 전혀 발생하지 않았습니다. – SiegeX

0

Visual Studio (-Zi로 생각하고 있지만 틀릴 수도 있음)는 런타임 스택 검사기로 이러한 종류의 할당을받습니다. 선호하는 무료 리눅스 솔루션이 아니지만 잘 작동합니다.

2

Bugfighter C/C++을 사용해보십시오.

매일 같이 사용하고 array[5][5][5]과 같은 다차원 배열을 사용해도 정상적으로 작동합니다.

Bugfighter 웹 페이지는 www.bugfighter-soft.com입니다.

2

Valgrind의의 memcheck 스택의 경우 힙 메모리

에 대해 감지하는, 당신은 불행하게도,이 캐치하지 않았던 부목의 Valgrind의의 SGCheck