범위를 벗어난 어레이에 액세스하는 것이 얼마나 위험합니까 (C)? 때로는 배열 외부에서 읽거나 (이제 프로그램의 다른 부분이나 그 이상으로 사용되는 메모리에 액세스한다는 것을 이해합니다) 또는 배열 외부의 인덱스로 값을 설정하려고합니다. 프로그램이 때때로 충돌하지만 때로는 실행되어 예기치 않은 결과 만 나타납니다.
이제 내가 알고 싶은 것은 이것이 얼마나 위험합니까? 프로그램이 손상되면 그렇게 나쁘지 않습니다. 반면에 완전히 관련이없는 메모리에 액세스 할 수 있기 때문에 프로그램 외부에서 무언가를 깨 뜨리면 매우 나쁩니다. 나는 ‘모든 일이 일어날 수 있습니다’, ‘세그먼트가 가장 나쁜 문제 일 수 있습니다.’ , ‘하드 디스크가 분홍색으로 변하고 유니콘이 당신의 창 아래에서 노래를 부를 수 있습니다 ‘를 많이 읽었습니다 .
내 질문 :
- 배열 외부에서 값을 읽으면 프로그램 이외의 것이 손상 될 수 있습니까? 나는 물건을 보는 것이 아무것도 변하지 않는다고 상상할 것입니다. 예를 들어 내가 도달 한 파일의 ‘마지막으로 열린 시간’속성을 변경합니까?
- 설정 값이 배열 외부로 빠져 나갈 수 있습니까? 이
스택 오버플로 질문에서 메모리 위치에 액세스 할 수 있으며 안전 보장이 없다는 것을 수집합니다. - 이제 XCode 내에서 작은 프로그램을 실행합니다. 자체 메모리 외부에 도달 할 수없는 프로그램에 대해 추가 보호 기능을 제공합니까? XCode를 해칠 수 있습니까?
- 본질적으로 버그가있는 코드를 안전하게 실행하는 방법에 대한 권장 사항이 있습니까?
OSX 10.7, Xcode 4.6을 사용합니다.
답변
ISO C 표준 (언어의 공식 정의)에 관한 한, 범위를 벗어난 배열에 액세스하는 경우 ” 정의되지 않은 동작 “이 있습니다. 문자 그대로의 의미는 다음과 같습니다.
휴대 할 수 없거나 잘못된 프로그램 구조 또는 잘못된 데이터를 사용할 때이 국제 표준에 요구 사항이없는 행동
비표준 메모는 다음과 같이 확장됩니다.
정의되지 않은 동작은 예측할 수없는 결과로 상황을 완전히 무시하는 것, 환경의 특징적인 문서화 된 방식으로 진단 또는 프로그램 실행 중 (진단 메시지 발행 여부에 관계없이), 번역 또는 실행 종료 (발급 포함)에 이르기까지 다양합니다. 진단 메시지).
이것이 이론입니다. 현실은 무엇입니까?
“최상의”경우 현재 실행중인 프로그램이 소유하고 있거나 (프로그램이 오작동 할 수 있음) 현재 실행중인 프로그램이 소유 하지 않은 메모리에 액세스 할 수 있습니다 (아마도 프로그램이 세그먼테이션 오류와 같은 것으로 충돌). 또는 프로그램이 소유 한 메모리에 쓰려고 시도 할 수 있지만 읽기 전용으로 표시되어 있습니다. 이로 인해 프로그램이 중단 될 수도 있습니다.
그것은 프로그램이 서로 동시에 실행중인 프로세스를 보호하려고 시도하는 운영 체제에서 실행되고 있다고 가정합니다. 코드가 “베어 메탈 (bare metal)”에서 실행중인 경우, OS 커널 또는 임베디드 시스템의 일부인 경우 그러한 보호 기능이 없습니다. 오작동하는 코드는 그러한 보호 기능을 제공하는 것입니다. 이 경우 하드웨어 (또는 주변 사물 또는 사람)에 대한 물리적 손상을 포함하여 손상 가능성이 훨씬 더 큽니다.
보호 된 OS 환경에서도 항상 100 % 보호되는 것은 아닙니다. 예를 들어 권한이없는 프로그램이 루트 (관리) 액세스를 얻을 수있게하는 운영 체제 버그가 있습니다. 일반 사용자 권한이 있어도 오작동하는 프로그램은 과도한 리소스 (CPU, 메모리, 디스크)를 소비하여 전체 시스템을 중단시킬 수 있습니다. 많은 맬웨어 (바이러스 등)가 버퍼 오버런을 악용하여 시스템에 대한 무단 액세스를 얻습니다.
(역사적 예 : 코어 메모리 가있는 일부 구형 시스템 에서 타이트한 루프로 단일 메모리 위치에 반복적으로 액세스하면 문자 그대로 해당 메모리 덩어리가 녹을 수 있습니다. 다른 방법으로는 CRT 디스플레이 파괴 및 판독 이동 등이 있습니다 / 드라이브 캐비닛의 고조파 주파수로 디스크 드라이브의 헤드를 쓰면 테이블을 가로 질러 바닥으로 떨어집니다.)
그리고 항상 걱정할 Skynet 이 있습니다.
결론은 이것입니다. 의도적으로 나쁜 일을하는 프로그램을 작성할 수 있다면 적어도 이론적으로 버그가있는 프로그램이 우연히 같은 일을 할 수 있다는 것 입니다.
실제로, 그건 매우 맥 OS X 시스템에서 실행되는 버그 프로그램이 충돌보다 더 심각한 아무것도 할 것입니다 가능성. 그러나 버그가있는 코드가 실제로 나쁜 일을하는 것을 완전히 막을 수는 없습니다 .
답변
일반적으로 오늘날 운영 체제 (일반적으로 인기있는 운영 체제)는 가상 메모리 관리자를 사용하여 보호 된 메모리 영역의 모든 응용 프로그램을 실행합니다. 프로세스에 할당 / 할당 된 영역 외부의 REAL 공간에있는 위치를 단순히 읽거나 쓰는 것이 그리 쉬운 일이 아님이 밝혀졌습니다.
직접 답변 :
1) 읽기는 다른 프로세스를 거의 직접 손상시키지 않지만 프로그램 / 프로세스를 암호화, 암호 해독 또는 유효성 검사하는 데 사용되는 KEY 값을 읽으면 프로세스를 간접적으로 손상시킬 수 있습니다. 읽은 데이터를 기반으로 의사 결정을 내리는 경우 경계를 벗어나면 코드에 악영향을 줄 수 있습니다.
2) 메모리 주소로 액세스 할 수있는 로션에 쓰면 실제로 무언가를 손상시킬 수있는 유일한 방법은 쓰려는 메모리 주소가 실제로 하드웨어 레지스터 (실제로 데이터 저장이 아니라 일부 부분을 제어하기위한 위치) 인 경우입니다. RAM 위치가 아님). 사실, 다시 쓸 수없는 (또는 그 성격의) 프로그램 가능한 위치를 한 번 작성하지 않는 한 여전히 정상적으로 무언가를 손상시키지 않습니다.
3) 일반적으로 디버거 내에서 실행하면 코드가 디버그 모드로 실행됩니다. 디버그 모드에서 실행하면 실습 또는 불법으로 간주되는 작업을 수행했을 때 코드를 더 빨리 중지하지 않습니다.
4) 매크로를 사용하지 말고 이미 내장 된 배열 인덱스 바운드 검사가있는 데이터 구조 등을 사용하십시오.
추가
위의 정보는 실제로 메모리 보호 창이있는 운영 체제를 사용하는 시스템에만 해당됩니다. 내장 시스템 또는 메모리 보호 창 (또는 가상 주소 지정 창)이없는 운영 체제 (실시간 또는 기타)를 사용하는 시스템의 코드를 작성하는 경우 메모리를 읽고 쓰는 데 훨씬 더주의를 기울여야합니다. 이러한 경우에도 보안 문제를 피하기 위해 항상 SAFE 및 SECURE 코딩 방법을 사용해야합니다.
답변
경계를 확인하지 않으면 보안 허점을 포함하여 추악한 부작용이 발생할 수 있습니다. 못생긴 것 중 하나는 임의의 코드 실행 입니다. 전형적인 예 : 고정 크기 배열 strcpy()
이 있고 사용자가 제공 한 문자열을 거기에 넣는 데 사용 하는 경우 사용자는 버퍼를 오버플로하고 함수가있을 때 CPU가 반환 해야하는 코드 주소를 포함하여 다른 메모리 위치를 덮어 쓰는 문자열을 제공 할 수 있습니다 마무리합니다.
즉, 사용자가 프로그램을 본질적으로 호출하게하는 문자열을 보낼 수 있습니다.이 경우 프로그램이 exec("/bin/sh")
셸로 전환되어 모든 데이터 수집 및 머신을 봇넷 노드로 전환하는 등 시스템에서 원하는 모든 것을 실행합니다.
답변
당신은 쓰기:
나는 ‘무엇이 일어날 수 있는가’, ‘세그먼트가 가장 나쁜 문제일지도 모른다’, ‘하드 디스크가 분홍색으로 변하고 유니콘이 당신의 창 아래에서 노래를 부르고있을 수 있습니다’를 많이 읽었습니다.
총을 넣으십시오. 특정 조준 및 발사없이 창 밖으로 지적하십시오. 위험은 무엇입니까?
문제는 당신이 모르는 것입니다. 코드가 프로그램과 충돌하는 것을 덮어 쓰면 정의 된 상태로 중지되기 때문에 괜찮습니다. 그러나 충돌하지 않으면 문제가 발생하기 시작합니다. 프로그램을 관리하는 리소스는 무엇이며 어떻게 할 수 있습니까? 프로그램을 제어 할 수있는 리소스는 무엇이며 어떻게 할 수 있습니까? 이러한 오버플로로 인해 발생한 적어도 하나의 주요 문제를 알고 있습니다. 이 문제는 프로덕션 데이터베이스에 대한 관련이없는 변환 표를 엉망으로 만드는 의미없는 통계 함수에있었습니다. 그 결과 결과적으로 매우 비싼 정리가 이루어졌습니다. 실제로이 문제가 하드 디스크를 포맷했을 경우 훨씬 저렴하고 다루기 쉬울 것입니다.
운영 체제가 사용자를 보호한다는 아이디어는 낙관적입니다. 가능하면 경계를 쓰지 않도록하십시오.
답변
루트 또는 다른 권한있는 사용자로 프로그램을 실행하지 않으면 시스템에 아무런 영향을 미치지 않으므로 일반적으로 이것이 좋습니다.
임의의 메모리 위치에 데이터를 쓰면 각 프로세스가 자체 메모리 공간에서 실행될 때 컴퓨터에서 실행중인 다른 프로그램을 직접 “손상”시키지 않습니다.
프로세스에 할당되지 않은 메모리에 액세스하려고하면 운영 체제가 세그먼트 오류로 인해 프로그램 실행을 중지합니다.
따라서 루트로 실행하지 않고 / dev / mem과 같은 파일에 직접 액세스하지 않고도 프로그램이 운영 체제에서 실행중인 다른 프로그램을 방해 할 위험이 없습니다.
그럼에도 불구하고 우연히 임의의 데이터를 임의의 메모리 위치에 맹목적으로 쓰면 손상 될 수있는 모든 것을 손상시킬 수 있습니다.
예를 들어, 프로그램은 프로그램 어딘가에 저장된 파일 이름으로 지정된 특정 파일을 삭제하려고 할 수 있습니다. 실수로 파일 이름이 저장된 위치를 덮어 쓰면 대신 다른 파일을 삭제할 수 있습니다.
답변
NSArray
Objective-C의 s에는 특정 메모리 블록이 지정됩니다. 어레이의 경계를 초과하면 어레이에 할당되지 않은 메모리에 액세스하고 있음을 의미합니다. 이것은 다음을 의미합니다.
- 이 메모리는 어떤 값이든 가질 수 있습니다. 데이터 유형에 따라 데이터가 유효한지 알 수있는 방법이 없습니다.
- 이 메모리에는 개인 키 또는 다른 사용자 자격 증명과 같은 민감한 정보가 포함될 수 있습니다.
- 메모리 주소가 유효하지 않거나 보호되어있을 수 있습니다.
- 메모리는 다른 프로그램이나 스레드가 액세스하기 때문에 값을 변경할 수 있습니다.
- 다른 것들은 메모리 매핑 된 포트와 같은 메모리 주소 공간을 사용합니다.
- 알 수없는 메모리 주소에 데이터를 쓰면 프로그램이 중단되고 OS 메모리 공간을 덮어 쓰며 일반적으로 햇빛이 lo 수 있습니다.
프로그램의 측면에서 코드가 배열의 범위를 초과하는 경우를 항상 알고 싶습니다. 이로 인해 알 수없는 값이 반환되어 응용 프로그램이 중단되거나 유효하지 않은 데이터가 제공 될 수 있습니다.
답변
코드를 테스트 할 때 Valgrind에서이memcheck
도구 를 사용해보십시오 . 스택 프레임 내에서 개별 배열 경계 위반을 포착하지는 않지만 미묘하고 넓게 만드는 것을 포함하여 많은 다른 종류의 메모리 문제를 포착해야합니다. 단일 기능의 범위를 벗어난 문제.
매뉴얼에서 :
Memcheck는 메모리 오류 감지기입니다. C 및 C ++ 프로그램에서 일반적인 다음과 같은 문제점을 발견 할 수 있습니다.
- 메모리에 액세스하면 (예 : 힙 블록 오버런 및 언더런 실행, 스택의 상단 오버런 및 메모리가 해제 된 후의 메모리 액세스)해서는 안됩니다.
- 정의되지 않은 값, 즉 초기화되지 않았거나 다른 정의되지 않은 값에서 파생 된 값 사용
- 이중 해제 힙 블록과 같은 힙 메모리 해제 또는 malloc / new / new [] 대 사용 가능 / 삭제 / 삭제 []의 일치하지 않는 사용
- memcpy 및 관련 함수에서 src 및 dst 포인터가 겹칩니다.
- 메모리 누수가 발생합니다.
ETA : Kaz의 답변에 따르면, 만병 통치약은 아니며 특히 흥미로운 액세스 패턴을 사용할 때 항상 가장 유용한 결과를 제공하지는 않습니다 .