SIGILL을 던지는 가장 짧은 코드


76

배경

우리는 이미 SIGSEGV 던지기에 대한 도전을 가지고 있습니다. 그렇다면 SIGILL 던지기에 대한 도전은 어떻습니까?

SIGILL은 무엇입니까?

SIGILL은 프로세서에서 잘못된 명령을 나타내는 신호로, 거의 발생하지 않습니다. SIGILL을받은 후 기본 조치는 프로그램을 종료하고 코어 덤프를 작성하는 것입니다. SIGILL의 신호 ID는 4입니다. SIGILL은 매우 드물게 발생하며를 통해 코드에서 생성하는 방법을 전혀 모릅니다 sudo kill -s 4 <pid>.

규칙

프로그램에 뿌리가 있지만 어떤 이유로 든 원하지 않는 경우 일반 사용자를 사용할 수도 있습니다. 나는 독일어 로켈이있는 Linux 컴퓨터에 있고 SIGILL을 잡은 후에 표시되는 영어 텍스트를 모르지만 '불법 교육'과 같은 것이라고 생각합니다. SIGILL을 던지는 가장 짧은 프로그램이 이깁니다.


6
명령어가 커널에 의해 생성되어야하는지 여부를 명확히 할 수 있습니다. 특히, 프로그램이 libc 호출을 사용하여 직접 생성하도록 허용 raise(SIGILL)하시겠습니까?

1
정말 말합니다 Illegal instruction (core dumped).
Outgolfer Erik

@ ais523 모든 것이 허용됩니다.
Mega Man

5
SIGILL을 높일 수있는 하드웨어의 경우 답은 명령어 길이와 동일합니다. 불법 명령을 어딘가에 놓고 실행하십시오. 유일한 흥미로운 것은 관련된 복잡한 툴체인 일 것입니다.
OrangeDog

3
* 작동하지 않는 오래된 프로그램을 게시 한 사람들 *
RudolfJelin

답변:


112

PDP-11 어셈블러 (UNIX Sixth Edition), 1 바이트

9

지침 9는 PDP-11에 대한 유효한 지침이 아닙니다 (8 진수 는 지침 목록에000011 표시되지 않음 (PDF)). UNIX Sixth Edition과 함께 제공되는 PDP-11 어셈블러는 이해하지 못하는 모든 것을 파일에 직접 반영합니다. 이 경우 9는 숫자이므로 리터럴 명령어 9를 생성합니다. 또한 파일이 처음부터 실행되기 시작하는 이상한 속성 (현재 어셈블리 언어에서는 비정상적 임)이 있으므로 프로그램을 만들기 위해 선언 할 필요가 없습니다. 작업.

이 에뮬레이터를 사용하여 프로그램을 테스트 할 수는 있지만 프로그램을 입력하기 위해 다소 싸워야합니다.

파일 시스템, 편집기, 터미널 및 이미 사용 방법을 알고 있다고 생각한 유사한 것을 사용하는 방법을 알아 낸 후에는 결과가 다음과 같습니다.

% a.out
Illegal instruction -- Core dumped

나는 이것이 진짜 SIGILL신호 임을 문서에서 확인했다. (그리고 그때까지도 같은 신호 번호, 4를 가졌다!)


1
POSIX 및 UNIX와 SUS 밀접하게 :) 관련되어 있기 때문에 동일한 신호 번호를했다
고양이

4
V6의 거의 모든 신호 번호는 오늘날에도 여전히 동일한 의미를 갖습니다. 니모닉은 실제로 숫자보다 안정적이지 않았습니다. 비교 minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h을 함께 github.com/freebsd/freebsd/blob/master/sys/sys/signal.h -에 대해 동일한 의미를 1 ~ 13이지만 1, 2, 13 만 정확히 동일한 이름을 갖습니다. (SIGALRM / 14 및 SIGTERM / 15는 V7에서만 추가되었습니다.) (System V 계보는 SIGBUS를 10에서 7 (이용할 수없는 SIGEMT 대체) 및 SIGSYS를 15 이상으로 이동하여 SIGUSR1 및 SIGUSR2.)
zwol

4
@cat POSIX 및 SUS는 실제로 신호 값을 지정하지 않습니다. kill 명령에 인수로 전달 될 때 일부 숫자의 의미를 지정하지만 SIGILL은 포함되지 않습니다.
Random832

7
a.out실제로 여러 바이트가 들어 있습니다 ( 9명령은 2 바이트로 컴파일되고 어셈블러는 프로그램을 실행 가능하게하기 위해 헤더와 바닥 글도 추가합니다). 그래서 기계 코드가 아닌 어셈블리 언어로 프로그램을 작성했습니다. 어셈블리 언어 프로그램에는 1 바이트 만 있고 더 많은 바이트를 가진 프로그램으로 컴파일됩니다. 이것은 크기 코딩 문제 (실행 파일 크기 최소화) 가 아니라 코드 골프 문제 (소스 크기 최소화)이므로 중요한 소스의 1 바이트 크기입니다.

2
오래되었지만 멋진 시스템을 매우 영리하게 남용했습니다.
마스트

81

C (x86_64, tcc ), 7 바이트

main=6;

이 답변에서 영감을 얻었습니다 .

온라인으로 사용해보십시오!

작동 원리

생성 된 어셈블리는 다음과 같습니다.

    .globl  main
main:
    .long 6

TCC는 정의 된 "기능"을 데이터 세그먼트 에 배치하지 않습니다 .

컴파일 후 _start 는 평소와 같이 main 을 가리 킵니다 . 결과 프로그램이 실행될 때 main 코드 가 필요하고 little-endian (!) 32 비트 정수 6을 찾습니다 . 0x06 0x00 0x00 0x00 으로 인코딩됩니다 . 첫 번째 바이트 ( 0x06 )는 잘못된 opcode이므로 프로그램은 SIGILL로 종료됩니다 .


C (x86_64, gcc ), 13 바이트

const main=6;

온라인으로 사용해보십시오!

작동 원리

const 수정자가 없으면 생성 된 어셈블리는 다음과 같습니다.

    .globl  main
    .data
main:
    .long   6
    .section    .note.GNU-stack,"",@progbits

GCC의 링커는 마지막 줄을 생성 된 개체에 실행 가능한 스택이 필요하지 않다는 힌트로 처리합니다. 이후 메인가 명시 적으로 배치되는 데이터 섹션에 포함 된 op 코드가 실행되지 않으므로 상기 프로그램은 종료한다 SIGSEGV (세그멘테이션 결함).

두 번째 또는 마지막 줄을 제거하면 생성 된 실행 파일이 의도 한대로 작동합니다. 마지막 행은 컴파일러 플래그 -zexecstack( 온라인 시도! )를 사용하여 무시할 수 있지만 비용은 12 바이트 입니다.

더 짧은 대안은 const 수정자를 사용하여 main 을 선언 하여 다음 어셈블리를 생성하는 것입니다.

        .globl  main
        .section    .rodata
main:
        .long   6
        .section    .note.GNU-stack,"",@progbits

이것은 컴파일러 플래그없이 작동합니다. 그 주 main=6;에 정의 된 "기능"작성합니다 데이터를 하지만, CONST 수정은 GCC는 그것을 쓸 수 rodata (적어도 내 플랫폼에서) 코드를 포함하도록 허용하는 대신.


함수를 사용하는 것조차 완전히 피하는 것을 좋아하십시오 :) 이것이 C 용어로 어떻게 작동합니까? 컴파일러는 그것이 main6 임을보고 그것을 호출하려고 시도합니까?
Mia Yun Ruse

11
@ JackDobson 정의되지 않은 동작이므로 C 측면에서 작동하지 않습니다. 당신은 컴파일러의 자비에 있습니다. Clang은 어떤 이유로 "외부 연결이있는 'main'이라는 변수에 정의되지 않은 동작이 있습니다."
Bobby Sacamano

2
GCC는 main기능이 아니라고 경고를 설정 한 경우에만 ( -Wall또는 -pedantic그렇게 할 경우) 불평 합니다.
zwol

유닉스 계열 시스템의 실행 파일이 text / data / bss 세그먼트 를 갖는 것이 표준이라고 생각합니다 . 링커는 .rodata 섹션을 실행 파일의 텍스트 세그먼트 안에 배치하며 거의 모든 플랫폼에서 해당됩니다. (커널의 프로그램 로더는 섹션이 아닌 세그먼트에만 관심이 있습니다).
Peter Cordes

3
또한 06x86-64에서는 잘못된 명령 일뿐입니다. 32 비트 모드에서는이므로이 PUSH ES답변은 기본적으로 컴파일러에서만 작동합니다 -m64. ref.x86asm.net/coder.html#x06을 참조하십시오 . 모든 미래의 x86 CPU에서 잘못된 명령으로 디코딩 보장된다 유일한 바이트 시퀀스는 2 바이트입니다 UD2 : 0F 0B. 다른 것은 미래의 접두사 또는 명령어 인코딩 일 수 있습니다. 그럼에도 불구하고 C 컴파일러가 main레이블을 몇 바이트에 붙일 수있는 멋진 방법을 제안했습니다 !
Peter Cordes

39

스위프트, 5 바이트

[][0]

빈 배열의 인덱스 0에 액세스하십시오. 이 호출 fatalError()은 오류 메시지를 인쇄하고 SIGILL과 충돌합니다. 여기서 시도해 볼 수 있습니다 .


이것은 까다로운 것들 중 하나입니다.)
Mega Man

26
... 지상에서 SIGILL과 충돌하는 이유는 무엇입니까? 이것이 적절한 신호라고 생각한 사람은 누구입니까? Bloody
hipsters

4
@ 아수; fatalError()를 실행하여 의도적으로 충돌합니다 ud2. 그들이 내가 모르는 일을하기로 선택한 이유는 무엇인가, 프로그램이 잘못된 일을했기 때문에 "잘못된 명령"오류 메시지가 의미가 있다고 생각했을 것입니다.
NobodyNada

2
훌륭한. 충돌이 발생하는 가장 짧은 Swift 코드이기도합니다.
JAL

3
@JAL 그래; 더 짧은 것은 생각할 수 없습니다. 시도 nil!했지만 컴파일러가 결과 유형을 유추 할 수 없었습니다. (또한 안녕 JAL!)
아무도 Nada

23

GNU C, 25 바이트

main(){__builtin_trap();}

GNU C (확장자를 가진 C의 특정 방언)에는 의도적으로 프로그램을 중단시키는 명령이 포함되어 있습니다. 정확한 구현은 버전마다 다르지만 종종 개발자는 충돌을 가능한 한 저렴하게 구현하려고 시도하는데, 일반적으로 불법 명령을 사용합니다.

테스트에 사용한 특정 버전은 gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; 그러나이 프로그램은 상당히 넓은 범위의 플랫폼에서 SIGILL을 발생 시키므로 이식성이 뛰어납니다. 또한 실제로 잘못된 명령을 실행하여 수행합니다. 위의 기본 최적화 설정으로 컴파일하는 어셈블리 코드는 다음과 같습니다.

main:
    pushq %rbp
    movq %rsp, %rbp
    ud2

ud2 는 인텔이 항상 정의되지 않은 상태로 유지한다고 보증하는 지침입니다.


11
−6 :main(){asm("ud2");}
wchargin

또한 원시 어셈블리의 바이트 수를 계산하는 방법을 모르지만 다음 00 00 0f 0b에 대한 기계어입니다 ud2.
wchargin

5
@ wchargin : 그것은 x86 + GNU C 답변입니다. 이것은 모든 GNU 시스템에 이식 가능합니다. 또한 UD2는 2 바이트에 불과합니다 . 그 00바이트 를 얻은 IDK ; 그것들은 UD2의 기계 코드의 일부가 아닙니다. BTW, Dennis의 답변에 대해 언급 했듯이 현재 x86-64에는 1 바이트의 불법 명령이 있지만 그와 같은 방식을 유지할 수는 없습니다.
Peter Cordes

@ wchargin : 우리는 기계 코드 기능 / 프로그램과 같은 바이트 수를 계산합니다. 32 바이트 x 86-64 머신 코드의 Adler32 또는 8 바이트 x 86-32 머신 코드의 GCD 와 같은 내 답변 중 일부를 참조하십시오 .
Peter Cordes

1
@Ruslan : 그들은 아니다; 00 00x86-64에서 (와 같이 add [rax], al) 동일하게 디코딩합니다 . 00 00 0f 0b에 쓰기 가능한 포인터가 없으면 SIGILL 전에 SIGSEGV를 사용 rax합니다.
Peter Cordes

22

C (x86_64), 11, 30, 34 또는 34 + 15 = 49 바이트

main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}

라이브러리 함수를 사용 SIGILL하여 다양한 방법을 통해 던지는 몇 가지 솔루션을 제출 했지만 라이브러리 함수가 문제를 해결한다는 점에서 속임수입니다. 다음은 라이브러리 함수를 사용하지 않고 운영 체제가 실행 불가능한 코드를 실행할 수있는 위치에 대해 다양한 가정을하는 다양한 솔루션입니다. (여기서 상수는 x86_64에 대해 선택되었지만 불법 명령이있는 대부분의 다른 프로세서에 대한 작업 솔루션을 얻도록 변경할 수 있습니다.)

06x86_64 프로세서의 정의 된 명령에 해당하지 않는 기계 번호의 가장 낮은 바이트입니다. 따라서 우리가해야 할 일은 실행하는 것입니다. (또는 2F정의되지 않았으며 인쇄 가능한 단일 ASCII 문자에 해당합니다.) 이들 중 어느 것도 항상 정의되어 있지는 않지만 현재로서는 정의되어 있지 않습니다.

여기서 첫 번째 프로그램 2F은 읽기 전용 데이터 세그먼트에서 실행 됩니다. 대부분의 링커에서 작업 점프를 생성 할 수 없습니다 .text로를 .rodata(또는 OS의 상당)가 이제까지 제대로 세그먼트 프로그램에 유용 할 것이 아닙니다의로, 아직 작동하는 운영 체제를 찾지 못했습니다. 또한 많은 컴파일러가 문제의 문자열을 넓은 문자열로 원한다는 사실을 허용해야합니다.L; 나는 이것이 작동하는 모든 운영 체제가 상당히 오래된 관점을 가지고 있기 때문에 기본적으로 C94 이전의 표준을 구축하고 있다고 가정합니다. 이 프로그램이 작동하는 곳이 없을 수도 있지만이 프로그램이 작동하는 곳이있을 수도 있으므로 더 모호하고 의심스럽지 않은 잠재적 답변 모음에이 프로그램을 나열하고 있습니다. (이 답변을 게시 한 후 Dennis는 main[]={6}채팅에서 길이가 같고 문자 너비에 문제가 없으며 잠재적 인 가능성을 암시 할 수 있는 채팅 가능성 을 언급 했습니다 main=6.이 답변을 합리적으로 주장 할 수는 없습니다. 내 자신을 생각하지 않았기 때문에

여기서 두 번째 프로그램 06은 읽기-쓰기 데이터 세그먼트에서 실행 됩니다. 쓰기 가능한 데이터 세그먼트는 악용 가능성이 높은 설계 결함으로 간주되므로 대부분의 운영 체제에서 세그먼트 화 오류가 발생합니다. 그러나 이것이 항상 사실은 아니 었으므로 충분히 오래된 버전의 Linux에서 작동하지만 쉽게 테스트 할 수는 없습니다.

세 번째 프로그램은 06스택에서 실행 됩니다. 다시 말하지만, 보안상의 이유로 스택은 일반적으로 쓰기 불가능으로 분류되기 때문에 오늘날에는 분할 오류가 발생합니다. 내가 본 링커 문서는 스택에서 실행하는 것이 합법적 이었다는 것을 암시합니다 (앞의 두 경우와 달리 때로는 유용합니다). 테스트 할 수는 없지만 일부는 확실합니다. 이것이 작동하는 Linux 버전 (및 아마도 다른 운영 체제).

마지막으로 -Wl,-z,execstack( 백엔드의 일부로 gccGNU ld를 사용하는 경우 )에 (15 바이트 페널티)를 부여 하면 실행 가능한 스택 보호가 명시 적으로 해제되어 세 번째 프로그램이 작동하고 예상대로 잘못된 작동 신호가 발생합니다. 나는 테스트 작업이 49 바이트 버전을 확인했습니다. (Dennis는 채팅 에서이 옵션이 분명히 작동하여 main=66 + 15의 점수를 줄 것이라고 언급했습니다 . 6이 엄청나게 스택에 있지 않다면 링크 옵션이 분명히 그 이름이 암시합니다.)


gcc6이 기본 (자동) 모드 인 x86-64 / linux에서 const main=6;여러 변형과 마찬가지로 작동합니다. 이 링커 (귀하의 링커라고도 함) 에서 .text로 점프를 생성 할 수 있습니다 .rodata. 당신이 가지고 있던 문제는, 그없이 const, 당신이에 점프하고 쓰기 가능한 데이터 세그먼트 ( .data현대 하드웨어에서 실행되지 않습니다). 메모리 보호 하드웨어가 페이지를 읽을 수는 있지만 실행할 수없는 것으로 표시 할 수없는 구형 x86에서 작동했을 것입니다.
zwol

C89에서도 main함수 (§5.1.2.2.1) 여야합니다. gcc main가 경고 만 할 수있는 데이터 객체로 선언 하는 이유를 모르겠지만 -pedantic명령 줄 에서만 확인할 수 있습니다. 1990 년대 초에 누군가가 우연히 그렇게하지 않을 것이라고 생각했지만, 이런 종류의 게임을 제외하고는 의도적으로하는 것이 유용한 것은 아닙니다.
zwol

1
... 다시 main[]="/"읽으면 문자열 리터럴이 rodata에 들어가기 때문에 읽기 전용 데이터 세그먼트로 이동할 것으로 예상 됩니다. char *foo = "..."과 의 차이점으로 인해 문제가 발생했습니다 char foo[] = "...". char *foo = "..."에 대한 문법 설탕이다 const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];리터럴 문자열이 rodata 갈 않으며, 그래서 fooA는 별도의 를 가리키는 쓰기 가능한 전역 변수. char foo[] = "..."그러나을 사용 하면 전체 배열이 쓰기 가능한 데이터 세그먼트로 이동합니다.
zwol

19

GNU (x86_64), 3 바이트

ud2

xxd시길 .S

00000000: 7564 32                                  ud2

$ as --64 sigill.S -o sigill.o; ld -S sigill.o -o시길

sigill.S: Assembler messages:
sigill.S: Warning: end of file not at end of a line; newline inserted
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078

$ ./sigill

Illegal instruction

$ objdump -d시길

sigill:     file format elf64-x86-64

Disassembly of section .text:

0000000000400078 <__bss_start-0x200002>:>
  400078:       0f 0b                   ud2

2 바이트 "소스"로 표현할 수있는 방법이 있어야합니다.
OrangeDog

아, 영리하다. 파일을 시작할 때 (선언없이) 시작점을 배치하고 비정상적인 빌드 시스템 구성에 대한 처벌을받지 않는 빌드 방법이 있는지 궁금합니다. 하나 찾지 못했지만 당신이 한 것처럼 보입니다.

@ ais523 : 예, 단일 파일 장난감 프로그램에 대한 일반적인 NASM / YASM 빌드 스크립트 ( asm-link)ld기본적으로 텍스트 세그먼트의 시작 또는 그와 같은 시작점이 있기 때문에 동일한 방식 으로이 소스에서 실행 파일을 빌드 합니다. 난 그냥 이것에 asm 소스 크기에 갈 생각하지 않았다 : P
Peter Cordes

18

QEMU의 Raspbian에 대한 배쉬, 4 (1?) 바이트

내 일이 아니야 나는 단지 다른 사람의 작업을보고합니다. 나는 주장을 시험 할 입장조차 없다. 이 과제의 중요한 부분은이 신호가 발생하고 포착되는 환경을 찾는 것 같습니다. QEMU, Raspbian 또는 bash의 크기는 포함하지 않았습니다.

2013 년 2 월 27 일 오후 8시 49 분에 사용자 emlhalac 이 Raspberry Pi fora에서 " 루트 하려고 할 때 '불법 교육을 받고 있습니다' "라고보고했습니다 .

ping

생산

qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction (core dumped)

예를 들어 훨씬 짧은 명령 이이 출력을 생성한다고 생각합니다 tr.

편집 : @fluffy의 설명 에 따라 입력 길이에 대해 추측 된 하한을 "1?"로 줄였습니다.


5
나는 [명령이 이길 것이라고 생각합니다 . :)
푹신한

17

x86 MS-DOS COM 파일, 2 바이트

편집 : 의견에서 지적했듯이 DOS 자체는 CPU 예외를 포착하지 않으며 단순히 응용 프로그램뿐만 아니라 전체 OS를 중단합니다. Windows XP와 같은 32 비트 NT 기반 OS에서 실행하면 실제로 잘못된 명령 신호가 트리거됩니다.

0F 0B

로부터 문서 :

잘못된 opcode를 생성합니다. 이 명령어는 소프트웨어 테스트에서 유효하지 않은 opcode를 명시 적으로 생성하기 위해 제공됩니다.

꽤 설명이 필요합니다. .com 파일로 저장하고 DOS 에뮬레이터에서 실행 DOS 에뮬레이터가 충돌합니다. Windows XP, Vista 또는 7 32 비트에서 실행하십시오.

Windows XP의 SIGILL


1
기술적으로 프로세서가 잘못된 명령 예외를 생성합니다. 그러나 DOS는 메모리 보호 및 예외 처리 기능이 매우 제한되어 있으며 정의되지 않은 동작 / OS 충돌로 이어질 경우 놀라지 않을 것입니다. OP는 커널이 오류를 잡아서 "잘못된 명령"을 콘솔에 출력해야한다고 말하지 않았다.
하사관

4
나는이 해결책에 대해 생각했지만 그것이 타당하다고 생각하지 않습니다. 이 질문에는 불법 명령 프로세서 트랩 뿐만 아니라 불법 명령 신호도 필요 하므로 트랩 에 응답하여 실제로 신호를 생성하는 운영 체제를 찾는 것이 목표였습니다 #UD. (또한 실제로 테스트하기로 결정했으며 DOS 에뮬레이터를 무한 루프에 넣는 것처럼 보였습니다.)

2
이것을 AMD K6-II의 실제 MS-DOS에서 테스트했습니다. EMM386을 실행하거나 실행하지 않고 시스템을 실행하면 시스템이 중단됩니다. (EMM386은 일부 오류를 포착하고 메시지와 함께 시스템을 중지하므로 차이가 있는지 테스트 할 가치가 있습니다.)
Mark

2
예, DOS 기반 창은 실제로 트랩을 잡고 최소한 앱을 중단시킬 수 있어야합니다.
Asu

2
@Asu XP 32 비트에서 작동하고 다른 모든 32 비트 Windows 시스템에서도 작동 함을 확인할 수 있습니다. 나는 이것이 충돌하는 것처럼 DOS 자체의 해결책이 아니라는 데 동의합니다.
하사관

13

C (32 비트 Windows), 34 바이트

f(i){(&i)[-1]-=9;}main(){f(2831);}

최적화없이 컴파일하는 경우에만 작동합니다 (그렇지 않으면 f함수 의 잘못된 코드 가 "최적화"됩니다).

main기능의 분해는 다음과 같습니다.

68 0f 0b 00 00    push 0b0f
e8 a1 d3 ff ff    call _f
...

우리는 push리터럴 값을 가진 명령어를 사용한다는 것을 알 수 있습니다 0b0f(little-endian, 그래서 바이트가 교환됩니다). call명령 (의 리턴 어드레스 푸시 ...기능의 파라미터 근처 스택에 위치해 명령). [-1]변위 를 사용 하여 함수는 리턴 주소를 대체하므로 바이트 0f 0b가 있는 9 바이트 이전을 가리 킵니다 .

이러한 바이트는 설계된대로 "정의되지 않은 명령어"예외를 발생시킵니다.


12

자바, 50 43 24 바이트

a->a.exec("kill -4 $$");

이것은 솜털의 대답 에서 명령을 도난당한 java.util.function.Consumer<Runtime>1 입니다 . 당신 그것을 호출 해야 하기 때문에 작동 합니다 !whateverNameYouGiveIt.accept(Runtime.getRuntime())

이것은 새로운 프로세스를 생성하고 SIGILL 자체를 던지기보다는 SIGILL을 던지게합니다.

1-기술적으로 는 쉘 명령을 실행하여 방금 생성 한 프로세스를 제어하는 ​​데 사용할 수 java.util.function.Function<Runtime, Process>있는를 Runtime#exec(String)반환 하기 때문일 수도 있습니다 java.lang.Process.


이러한 장황한 언어로 더 인상적인 일을하기 위해 여기에 72 60 48 바이트 보너스가 있습니다.

a->for(int b=0;;b++)a.exec("sudo kill -s 4 "+b);

이것은 하나를 Consumer<Runtime>포함하여 모든 프로세스 (자체 포함)를 거치는 프로세스입니다. 격렬한 충돌에 대한 더 나은 버팀대.


그리고 다른 보너스 (a Consumer<ANYTHING_GOES>)는 적어도 20 바이트에서 SIGILL을 던지는 합니다.

a->System.exit(132);

8

펄, 9 바이트

kill+4,$$

프로세스 신호를 보내기 위해 적절한 라이브러리 함수를 호출하고 프로그램으로 신호를 보냅니다 SIGILL. 여기에 실제로 불법적 인 지시는 없지만 적절한 결과를 낳습니다. (이것이 도전을 상당히 싸게 만든다고 생각하지만, 허용되는 것이 있으면 이것이 사용하는 허점입니다 ...)


에 대신 공백을 사용하여 동일한 게시물을 게시했습니다 +. :)
simbabque

2
사람들이 비 골프 프로그래밍에 대해 Perl을 배우면 +. 한동안 골프를 한 후, 그들은 +때때로 과시합니다. 결국, 그들은 어떤 이유로 든 공백을 피하는 데 필요한 충분한 프로그램을 작성했습니다 +. (또한 괄호에 대한 파서에서 특수한 경우를 트리거하는 데 효과적이므로 덜 모호하게 구문 분석됩니다.)

8

ARM Unified 어셈블러 언어 (UAL), 3 바이트

nop

예를 들면 다음과 같습니다.

$ as ill.s -o ill.o
$ ld ill.o -o ill
ld: warning: cannot find entry symbol _start; defaulting to 00010054
$ ./ill 
Illegal instruction

을 실행 한 후 nop프로세서는 .ARM.attributes섹션을 코드로 해석하여 어딘가에 잘못된 명령을받습니다.

$ objdump -D ill

ill:     file format elf32-littlearm


Disassembly of section .text:

00010054 <__bss_end__-0x10004>:
   10054:       e1a00000        nop                     ; (mov r0, r0)

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0:   00001341        andeq   r1, r0, r1, asr #6
   4:   61656100        cmnvs   r5, r0, lsl #2
   8:   01006962        tsteq   r0, r2, ror #18
   c:   00000009        andeq   r0, r0, r9
  10:   01080106        tsteq   r8, r6, lsl #2

라즈베리 파이 3에서 테스트되었습니다.


어떻게 든 이것은 파이 2에서 작동하지 않습니다.
Mega Man

7

Microsoft C (Visual Studio 2005 이상), 16 바이트

main(){__ud2();}

쉽게 테스트 할 수는 없지만 설명서 에 따르면 의도적으로 사용자 모드 프로그램에서 커널 전용 명령을 실행하여 잘못된 명령을 생성해야합니다. (부적절한 명령으로 인해 프로그램이 충돌하기 main때문에이 K & R 스타일 main함수가 유효 하다는 것을 의미하는 에서 다시 시도 할 필요는 없습니다 . Visual Studio는 C89에서 이동 한 적이없는 것이 일반적이지만 좋지 않습니다. 여기에 유용합니다.)


VS2015로 리눅스를 컴파일 할 수 있습니까? SIGILL이 Windows에 정의되어 있다고 생각하지 않습니까?
앤드류 Savinykh

7

루비, 13 바이트

`kill -4 #$$`

우리가 이것을 * nix 쉘에서 실행한다고 가정하는 것이 안전하다고 생각합니다. 백틱 리터럴은 주어진 쉘 명령을 실행합니다. $$실행중인 Ruby 프로세스이며 #문자열 보간입니다.


쉘을 직접 호출하지 않고 :

루비, 17 바이트

Process.kill 4,$$

6

모든 쉘 (sh, bash, csh 등), 모든 POSIX (10 바이트)

사소한 답변이지만 게시 한 사람을 보지 못했습니다.

kill -4 $$

SIGILL을 현재 프로세스로 보냅니다. OSX의 출력 예 :

bash-3.2$ kill -4 $$
Illegal instruction: 4

어떤 프로그램이 SIGILL을 kill -4 1발생시키는 지에 대한 질문이 구체적이지 않은 경우 할 수 있습니다
Mark K Cowan

@MarkKCowan Heh, 좋은 점은 루트를 가정하지만 ...
솜털 같은

2
You will have root in your programs-답변에서 바이트를 빼고 동시에 약간의 질문을 트롤하십시오 : D. 보너스 : 살해init
Mark K Cowan

2
@MarkKCowan : On (현대 버전?) Linux init는 실제로 루트로도 수신하도록 특별히 요청하지 않은 신호에 영향을받지 않습니다. 그래도 다른 POSIX OS를 사용하여이 문제를 해결할 수 있습니다.

2
kill -4 2then : D
Mark K Cowan

6

ELF + x86 머신 코드, 45 바이트

SIGILL을 발생시키는 유닉스 머신에서 가장 작은 실행 프로그램이어야합니다 (작은 경우 실행 파일을 인식하지 못하는 Linux로 인해).

nasm -f bin -o a.out tiny_sigill.asmx64 가상 머신에서 테스트하고로 컴파일하십시오 .

실제 45 바이트 바이너리 :

0000000 457f 464c 0001 0000 0000 0000 0000 0001

0000020 0002 0003 0020 0001 0020 0001 0004 0000

0000040 0b0f c031 cd40 0080 0034 0020 0001

어셈블리 목록 (아래 소스 참조) :

;tiny_sigill.asm      
BITS 32


            org     0x00010000

            db      0x7F, "ELF"             ; e_ident
            dd      1                                       ; p_type
            dd      0                                       ; p_offset
            dd      $$                                      ; p_vaddr 
            dw      2                       ; e_type        ; p_paddr
            dw      3                       ; e_machine
            dd      _start                  ; e_version     ; p_filesz
            dd      _start                  ; e_entry       ; p_memsz
            dd      4                       ; e_phoff       ; p_flags


_start:
                ud2                             ; e_shoff       ; p_align
                xor     eax, eax
                inc     eax                     ; e_flags
                int     0x80
                db      0
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
                db      1                       ; e_phnum
                                                ; e_shentsize
                                                ; e_shnum
                                                ; e_shstrndx

  filesize      equ     $ - $$

면책 조항 : 숫자를 반환하기 위해 가장 작은 조립 프로그램을 작성하지만 mov 대신 opcode ud2를 사용하는 다음 자습서의 코드 : http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
그 정확한 튜토리얼의 수정 된 실행 파일을 게시하려고했지만 당신이 나를 이겼습니다. 이것은 이길 가치가있다. 시스템 리소스 측면에서 진정한 미니멀리스트 (파일 내 및 메모리 모두에서 45 바이트를 넘지 않아야하며 둘 다 정확히 동일합니다) 및 다른 어셈블러 솔루션과 같은 부풀린 인터프리터는 없습니다. 그것은 단순히 그것이 무엇인지입니다.
Idonotexist Idonotexist

5

AutoIt , 93 바이트

flatassembler 인라인 어셈블리 사용 :

#include<AssembleIt.au3>
Func W()
_("use32")
_("ud2")
_("ret")
EndFunc
_AssembleIt("int","W")

SciTE 대화식 모드에서 실행하면 즉시 충돌합니다. Windows 디버거가 1 초 동안 팝업됩니다. 콘솔 출력은 다음과 같습니다.

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
0x0F0BC3
!>14:27:09 AutoIt3.exe ended.rc:-1073741795

-1073741795WinAPI에서 정의되지 않은 오류 코드는 어디에 있습니까 ? 음수 일 수 있습니다.

내 자신의 어셈블러 LASM을 사용하는 것과 비슷합니다 .

#include<LASM.au3>
$_=LASM_ASMToMemory("ud2"&@CRLF&"ret 16")
LASM_CallMemory($_,0,0,0,0)

5

NASM, 25 바이트

나는 이것이 어떻게 작동하는지 모르겠다. 특히 내 컴퓨터 (Linux x86_64)에서만 작동한다.

global start
start:
jmp 0

다음과 같이 컴파일 및 실행하십시오.

$ nasm -f elf64 ill.asm && ld ill.o && ./a.out
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
Illegal instruction

당신은 아마로, 4 바이트로 단축 할 수ja 0
마크 K 코완

1
또는 세 가지로ud2
마크 K 코완

1
아마도 일부 데이터로 이동하려고하기 때문에?
Asu

5

TI-83 육각 어셈블리, 2 바이트

PROGRAM:I
:AsmPrgmED77

로 실행하십시오 Asm(prgmI). 잘못된 0xed77 opcode를 실행합니다. 16 진수의 각 쌍을 1 바이트로 계산합니다.



3

x86 .COM, 1 바이트

c

ARPL#UD16 비트 모드의 원인


1

리눅스 쉘, 9 바이트

kill -4 0

SIGILLPID 0을 사용하여 프로세스로 보냅니다. 어떤 프로세스에 PID 0이 있는지는 모르지만 항상 존재합니다.

온라인으로 사용해보십시오!


보낸 사람 man kill:0 All processes in the current process group are signaled.
데니스

1

GNU C, 24 19 18 바이트

Dennis에게 -4,
ceilingcat 덕분에 -1

main(){goto*&"'";}

온라인으로 사용해보십시오! 이것은 ASCII와 x86_64를 가정합니다. 기계 코드를 실행하려고 시도하는데 27, 이는 불법입니다.


shortC , 10 5 4 바이트

AV"'

위의 GNU C 코드와 같습니다. 온라인으로 사용해보십시오!


L"\6"x86_64를 가정하면 불법입니다.
데니스

@Dennis 0x06이란 무엇입니까? 또한 L필요하지 않습니다.
MD XF

할당되지 않았습니다.
Dennis

할당되지 않았습니다. 그것이 불법입니다. 또한, '39 = 0x27에의 하지 아님 0x39 .
Dennis

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.