C (x86_64), 11, 30, 34 또는 34 + 15 = 49 바이트
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
라이브러리 함수를 사용 SIGILL
하여 다양한 방법을 통해 던지는 몇 가지 솔루션을 제출 했지만 라이브러리 함수가 문제를 해결한다는 점에서 속임수입니다. 다음은 라이브러리 함수를 사용하지 않고 운영 체제가 실행 불가능한 코드를 실행할 수있는 위치에 대해 다양한 가정을하는 다양한 솔루션입니다. (여기서 상수는 x86_64에 대해 선택되었지만 불법 명령이있는 대부분의 다른 프로세서에 대한 작업 솔루션을 얻도록 변경할 수 있습니다.)
06
x86_64 프로세서의 정의 된 명령에 해당하지 않는 기계 번호의 가장 낮은 바이트입니다. 따라서 우리가해야 할 일은 실행하는 것입니다. (또는 2F
정의되지 않았으며 인쇄 가능한 단일 ASCII 문자에 해당합니다.) 이들 중 어느 것도 항상 정의되어 있지는 않지만 현재로서는 정의되어 있지 않습니다.
여기서 첫 번째 프로그램 2F
은 읽기 전용 데이터 세그먼트에서 실행 됩니다. 대부분의 링커에서 작업 점프를 생성 할 수 없습니다 .text
로를 .rodata
(또는 OS의 상당)가 이제까지 제대로 세그먼트 프로그램에 유용 할 것이 아닙니다의로, 아직 작동하는 운영 체제를 찾지 못했습니다. 또한 많은 컴파일러가 문제의 문자열을 넓은 문자열로 원한다는 사실을 허용해야합니다.L
; 나는 이것이 작동하는 모든 운영 체제가 상당히 오래된 관점을 가지고 있기 때문에 기본적으로 C94 이전의 표준을 구축하고 있다고 가정합니다. 이 프로그램이 작동하는 곳이 없을 수도 있지만이 프로그램이 작동하는 곳이있을 수도 있으므로 더 모호하고 의심스럽지 않은 잠재적 답변 모음에이 프로그램을 나열하고 있습니다. (이 답변을 게시 한 후 Dennis는 main[]={6}
채팅에서 길이가 같고 문자 너비에 문제가 없으며 잠재적 인 가능성을 암시 할 수 있는 채팅 가능성 을 언급 했습니다 main=6
.이 답변을 합리적으로 주장 할 수는 없습니다. 내 자신을 생각하지 않았기 때문에
여기서 두 번째 프로그램 06
은 읽기-쓰기 데이터 세그먼트에서 실행 됩니다. 쓰기 가능한 데이터 세그먼트는 악용 가능성이 높은 설계 결함으로 간주되므로 대부분의 운영 체제에서 세그먼트 화 오류가 발생합니다. 그러나 이것이 항상 사실은 아니 었으므로 충분히 오래된 버전의 Linux에서 작동하지만 쉽게 테스트 할 수는 없습니다.
세 번째 프로그램은 06
스택에서 실행 됩니다. 다시 말하지만, 보안상의 이유로 스택은 일반적으로 쓰기 불가능으로 분류되기 때문에 오늘날에는 분할 오류가 발생합니다. 내가 본 링커 문서는 스택에서 실행하는 것이 합법적 이었다는 것을 암시합니다 (앞의 두 경우와 달리 때로는 유용합니다). 테스트 할 수는 없지만 일부는 확실합니다. 이것이 작동하는 Linux 버전 (및 아마도 다른 운영 체제).
마지막으로 -Wl,-z,execstack
( 백엔드의 일부로 gcc
GNU ld
를 사용하는 경우 )에 (15 바이트 페널티)를 부여 하면 실행 가능한 스택 보호가 명시 적으로 해제되어 세 번째 프로그램이 작동하고 예상대로 잘못된 작동 신호가 발생합니다. 나는 한 테스트 작업이 49 바이트 버전을 확인했습니다. (Dennis는 채팅 에서이 옵션이 분명히 작동하여 main=6
6 + 15의 점수를 줄 것이라고 언급했습니다 . 6이 엄청나게 스택에 있지 않다면 링크 옵션이 분명히 그 이름이 암시합니다.)
raise(SIGILL)
하시겠습니까?