抛出SIGILL的最短代码


76

背景

我们已经对抛出SIGSEGV提出了挑战,那么为什么不对抛出SIGILL提出挑战呢?

什么是SIGILL?

SIGILL是在处理器处发出非法指令的信号,这种情况很少发生。收到SIGILL后的默认操作是终止程序并编写核心转储。SIGILL的信号ID为4。您很少遇到SIGILL,除了通过,我完全不知道如何在您的代码中生成它sudo kill -s 4 <pid>

规则

您将在程序中具有root用户,但是如果出于任何原因您不想这样做,则也可以使用普通用户。我在使用德语语言环境的Linux计算机上,我不知道在捕获SIGILL后显示的英文文本,但是我认为它类似于“非法指令”。抛出SIGILL的最短程序获胜。


6
您可能想澄清指令是否必须由内核生成。特别是,您是否要允许该程序仅使用libc调用直接生成它raise(SIGILL)

1
确实的确如此Illegal instruction (core dumped)
暴民埃里克

@ ais523一切都允许。
洛克人

5
对于任何可以提高SIGILL的硬件,答案将与指令长度相同。只需将非法指令放在某处并尝试执行它即可。唯一有趣的是涉及的复杂工具链。
OrangeDog

3
*发布旧程序无法正常工作的人*
RudolfJelin

Answers:


112

PDP-11汇编程序(UNIX第六版),1字节

9

指令9在PDP-11上不是有效的指令(八进制为,它000011不会出现在指令列表(PDF)中)。UNIX第六版附带的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.hgithub.com/freebsd/freebsd/blob/master/sys/sys/signal.h-相同的语义1到13,但只有1、2和13具有完全相同的名称。(仅在V7中添加了SIGALRM / 14和SIGTERM / 15。)(System V世系进行了几处更改,特别是将SIGBUS从10更改为7(取代了无用的SIGEMT)和SIGSYS超过15,从而为SIGUSR1和SIGUSR2。)
zwol

4
@cat POSIX和SUS实际上没有指定信号的值-当作为kill命令的参数传递时,它们确实指定了一些数字的含义,但不包括SIGILL。
Random832 '16

7
a.out实际上有多个字节(9指令编译为两个字节,并且汇编程序还添加了页眉和页脚以使程序可执行)。这就是为什么我用汇编语言而不是机器代码编写程序的原因。汇编语言程序仅包含一个字节,然后编译为包含更多字节的程序;这是一个代码高尔夫球问题(最小化源代码的大小),而不是大小编码问题(最小化可执行文件的大小),因此重要的是源代码的1字节大小。

2
非常巧妙地滥用了旧的但很棒的系统。
2016年

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 –是无效的操作码,因此程序以SIGILL终止。


C(x86_64,gcc),13个字节

const main=6;

在线尝试!

这个怎么运作

如果没有const修饰符,则生成的程序集将如下所示。

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

GCC的链接器将最后一行视为生成的对象不需要可执行堆栈的提示。由于main已明确放置在数据段中,因此它包含的操作码不可执行,因此程序将终止SIGSEGV(分段错误)。

删除第二行或最后一行将使生成的可执行文件按预期工作。最后一行可以用编译器标志忽略-zexecstack在线尝试!),但这花费12个字节

一个较短的替代方法是使用const修饰符声明main,从而导致以下汇编。

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

这无需任何编译器标志即可工作。请注意,这main=6;会在data中写入定义的“函数” ,但是const修饰符使GCC 改为在rodata中写入它,(至少在我的平台上)它可以包含代码。


喜欢完全避免使用函数:)但是,如何使用C术语呢?编译器是否看到那个main是6并尝试调用它(我猜这会让它放弃并尝试指令)?
Mia yun Ruse

11
@JackDobson这是未定义的行为,因此它在C语言下不起作用;您受编译器的摆布。出于某种原因,Clang甚至发出了警告:“具有外部链接的名为'main'的变量具有未定义的行为”。
Bobby Sacamano '16

2
main仅当您打开警告(-Wall或者-pedantic将要这样做)时,GCC才会抱怨不是功能。
zwol

我认为,对于类似Unix的系统,可执行文件具有text / data / bss 是相当标准的。链接器将该.rodata 放置在可执行文件的文本段内,并且我希望在几乎所有平台上都是这种情况。(内核的程序加载器仅关心段,而不关心节)。
彼得·科德斯

3
另请注意,这06只是x86-64中的无效指令。在32位模式下为PUSH ES,因此此答案仅适用于默认为的编译器-m64。请参阅ref.x86asm.net/coder.html#x06。保证在将来所有x86 CPU上都作为非法指令解码的唯一字节序列是2字节UD20F 0B。其他可能是将来的前缀或指令编码。尽管如此,还是为让C编译器main在某些字节上粘贴标签的一种很酷的方式而赞扬!
彼得·科德斯

39

Swift,5个字节

[][0]

访问空数组的索引0。这将调用fatalError(),从而显示错误消息并因SIGILL而崩溃。 您可以在这里尝试


这是一个比较棘手的问题之一;)
Mega Man

26
...为什么它会因SIGILL崩溃?谁认为这是一个适当的信号?血腥的时髦:D
Muzer

4
@Asu否;fatalError()跑步故意撞车ud2。为什么他们选择这样做,我不知道,但也许他们认为错误消息“非法指令”是有意义的,因为该程序做了一些非法的事情。
NobodyNada's

2
辉煌。我敢打赌,这也是导致崩溃的最短的Swift代码。
2016年

3
@JAL是的;我想不到任何简短的内容。我试过了nil!,但是编译器无法推断结果类型。(另外,嗨,日航!)
NobodyNada

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 '16

另外,我不知道我们如何计算原始汇编的字节数,但是00 00 0f 0bud2…… 的机器语言
wchargin

5
@wchargin:这是x86 + GNU C的答案。这是可移植到所有GNU系统的。另请注意,UD2只有2个字节。您在其中获得这些00字节的IDK ;它们不属于UD2的机器代码。顺便说一句,正如我在Dennis的回答中所评论的那样,x86-64中目前有一个字节的非法指令,但不能保证它们会保持这种状态。
彼得·科德斯

@wchargin:我们像您期望的那样为机器代码功能/程序计算字节数。请参阅我的一些答案,例如32字节x86-64机器代码中的Adler328字节x86-32机器代码中的GCD
彼得·科德斯

1
@Ruslan:不是。00 00在x86-64中解码相同的内容(如add [rax], al)。 00 00 0f 0b通常会在SIGILL之前使用SIGSEGV,除非您碰巧在中有一个可写的指针rax
彼得·科德斯

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选择的,但是您可以对其进行更改,以获得适用于大多数其他具有非法指令的处理器的有效解决方案。)

06是与x86_64处理器上定义的指令不对应的机器代码的最低编号字节。因此,我们要做的就是执行它。(或者,2F它也是未定义的,并且对应于一个可打印的ASCII字符。)不能保证始终未定义这两个字符,但是至今尚未定义它们。

这里的第一个程序2F从只读数据段执行。大多数链接程序都无法产生从.text.rodata(或与操作系统等效)的工作跳转,因为在正确分段的程序中,它永远不会有用。我尚未找到可在其上运行的操作系统。您还必须考虑到许多编译器希望所讨论的字符串为宽字符串这一事实,这将需要一个额外的L; 我假设可以运行的任何操作系统对事物的看法都已经过时,因此默认情况下是为C94之前的标准构建的。该程序可能无处工作,但该程序也可能存在某处,因此我将其列在此组合中。(在我发布此答案后,丹尼斯还在main[]={6}聊天中提到了可能性,该长度相同,并且不会遇到字符宽度问题,甚至暗示了潜在的可能性main=6;我无法合理地将这些答案声明为我的,因为我自己没有想到它们。)

这里的第二个程序06从读写数据段执行。在大多数操作系统上,这将导致分段错误,因为可写数据段被认为是严重的设计缺陷,有可能导致被利用。但是,情况并非总是如此,因此它可能适用于足够旧的Linux版本,但是我无法轻松对其进行测试。

第三个程序06从堆栈执行。再次,这现在引起分段错误,因为出于安全原因通常将堆栈分类为不可写。我见过很多的链接器文档暗示,从堆栈中执行该链接是合法的(与前两种情况不同,这样做有时是有用的),因此尽管我无法对其进行测试,但我敢肯定,其中有些可以在其上运行的Linux版本(可能还有其他操作系统)。

最后,如果您给-Wl,-z,execstackgcc如果使用GNU ld作为后端的一部分)付出(15字节的罚款),它将显式关闭可执行的堆栈保护,从而使第三个程序正常工作并给出预期的非法操作信号。我已经测试并验证了此49字节版本可以正常工作。(丹尼斯在聊天中提到,该选项显然与配合使用main=6,得分为6 + 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中,并且foo是指向它的单独的可写全局变量。char foo[] = "..."但是,使用,整个数组将进入可写数据段。
zwol

19

GNU as(x86_64),3个字节

ud2

$ xxd sigill.S

00000000: 7564 32                                  ud2

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

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

sigill:     file format elf64-x86-64

Disassembly of section .text:

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

必须有一种方法可以在两字节的“源”中表达这一点……
OrangeDog,2016年

哦,聪明。我想知道是否有一种方法可以将入口点放在文件的开头(没有声明),并且不会因异常的构建系统配置而受到惩罚。我找不到一个,但看起来像您一样。

@ ais523:是的,我通常asm-link的单文件玩具程序的NASM / YASM build-script(将以相同的方式从该源代码生成可执行文件,因为ld默认入口点是文本段的开头或类似内容。我只是没有想到要在这个源代码上增加asm的大小:P
Peter Cordes,2016年

18

Bash在QEMU上的Raspbian上,4(1?)个字节

不是我的工作。我只是报告另一个人的工作。我什至无法测试该要求。由于此挑战的关键部分似乎是找到一个可以发出和捕获此信号的环境,因此,我不包括QEMU,Raspbian或bash的大小。

2013年2月27日晚上8:49,用户emlhalac在Raspberry Pi论坛上报告了“ 在尝试chroot时获取'非法指令' ”。

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异常,而只会挂起(而不仅仅是应用程序和整个操作系统)。在运行Windows XP等基于NT的32位操作系统上,确实会触发非法指令信号。

0F 0B

文档中

生成无效的操作码。提供此指令用于软件测试,以显式生成无效的操作码。

这是不言自明的。另存为.com文件,然后在任何DOS模拟器中运行 DOS模拟器将崩溃。在Windows XP,Vista或7 32位上运行。

Windows XP上的SIGILL


1
从技术上讲,它确实会导致处理器生成非法指令异常。但是,DOS具有非常有限的内存保护和异常处理功能,如果仅导致未定义的行为/操作系统崩溃,我也不会感到惊讶。OP并没有说内核必须捕获错误并在控制台上打印“ Illegal Instruction”。
仆人

4
我想到了这种解决方案,但我不认为这是有效的。这个问题需要一个非法的指令信号,而不仅仅是非法的指令处理器陷阱,因此目标是找到一个操作系统,该操作系统实际上会响应该#UD陷阱生成信号。(此外,我决定进行实际测试,它似乎使我的DOS仿真器陷入无限循环。)

2
我在AMD K6-II的实际MS-DOS上对此进行了测试。无论是否运行EMM386,运行它都只会挂起系统。(EMM386会捕获一些错误,并通过一条消息暂停系统,因此值得测试一下是否
2016年

2
是的,基于DOS的窗口应该能够真正捕获陷阱并至少会使应用程序崩溃。
阿苏

2
@Asu我可以确认它可以在32位XP上运行,并且可能会在所有其他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(小端,因此它的字节被交换了)。所述call指令将返回地址(的...,这是位于该函数的参数接近在栈上的指令)。通过使用[-1]位移,该函数将覆盖返回地址,因此它指向字节之前的9个字节0f 0b

按照设计,这些字节会导致“未定义指令”异常。


12

Java,50 43 24字节

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

这是java.util.function.Consumer<Runtime>1,其命令已从蓬松的答案中窃取。之所以有效,是因为您必须将其称为whateverNameYouGiveIt.accept(Runtime.getRuntime())

请注意,这将创建一个新进程并使它抛出SIGILL而不是抛出SIGILL本身。

1-从技术上讲,它也可能是a,java.util.function.Function<Runtime, Process>因为Runtime#exec(String)返回a java.lang.Process可以用来执行shell命令来控制刚创建的进程。


为了用这种冗长的语言做一些更令人印象深刻的事情,以下是72 60 48字节的奖励:

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

这是另一个Consumer<Runtime>经历所有过程(包括自身)的过程,使每个过程都引发SIGILL。更好地准备好进行暴力崩溃。


还有另一个好处(a Consumer<ANYTHING_GOES>),至少可以假装以20个字节抛出SIGILL:

a->System.exit(132);

8

Perl,9个字节

kill+4,$$

只需调用适当的库函数来发信号通知一个进程,并使用来获取程序以发信号通知自己SIGILL。这里没有涉及任何实际的非法指示,但是可以产生适当的结果。(我认为这使挑战相当便宜,但是如果允许的话,这就是您要使用的漏洞……)


来到这里张贴相同的内容,用空格代替+。:)
simbabque

2
当人们学习用于非高尔夫编程的Perl时,他们使用来学习它+。打了一段时间球后,他们+偶尔会炫耀一下。最终,他们编写了足够的程序,出于某种原因或其他+习惯,它们需要避免空格。(它也进行了较少歧义的解析,因为它可以解决触发括号中的特殊情况的工作。)

8

ARM统一汇编语言(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

在Raspberry Pi 3上测试。


不知怎的,这并不在皮2.工作
洛克人

7

Microsoft C(从Visual Studio 2005起),16字节

main(){__ud2();}

我很难对此进行测试,但是根据文档,它应该通过有意尝试从用户模式程序执行仅内核指令来产生一条非法指令。(请注意,由于非法指令使程序崩溃,因此我们不必尝试从中返回main,这意味着该K&R样式的main函数有效。VisualStudio从C89开始从未使用过,这通常是一件坏事,但它确实来自于C89在这里有用。)


您可以使用VS2015为Linux进行编译吗?因为我不认为SIGILL是在Windows中定义的,是吗?
Andrew Savinykh

7

Ruby,13个字节

`kill -4 #$$`

我猜可以安全地假设我们从* nix shell运行此程序。反引号文字将运行给定的shell命令。$$是正在运行的Ruby进程,#用于字符串插值。


不直接调用shell:

Ruby,17个字节

Process.kill 4,$$

6

任何shell(sh,bash,csh等),任何POSIX(10字节)

琐碎的回答,但我还没有看到有人发布。

kill -4 $$

只需将SIGILL发送到当前进程即可。OSX上的示例输出:

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

kill -4 1如果问题不是关于哪个程序引发SIGILL 的问题,您可以这样做
Mark K Cowan

@MarkKCowan Heh,好的观点,尽管这是扎根的……
蓬松的

2
You will have root in your programs-从答案中删除一个字节,然后在同一时间略微拖曳问题:D。奖励:你要杀了init
Mark K Cowan

2
@MarkKCowan:在Linux的(现代版本?)上init,即使没有root用户,实际上也不受它没有特别要求接收的信号的影响。不过,您也许可以通过使用其他POSIX OS来解决此问题。

2
kill -4 2然后:D
Mark K Cowan

6

ELF + x86机器代码,45字节

这应该是抛出SIGILL的Unix机器上最小的可执行程序(由于Linux不能识别可执行文件(如果将其缩小的话))。

nasm -f bin -o a.out tiny_sigill.asm在x64虚拟机上经过测试的进行编译。

实际的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     $ - $$

免责声明:以下教程中的代码编写最小的汇编程序以返回数字,但使用操作码ud2而不是mov:http//www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
我本来打算发布该教程的修改后的可执行文件,但是您击败了我。这应该赢;从系统资源的角度来看,这是一个真正的极简主义(文件内和内存中最多不超过45个字节,并且两者完全相同),并且没有其他汇编程序解决方案那样肿的解释器。就是这样。
Iwillnotexist Idonotexist

5

AutoIt,93字节

使用flatassembler内联汇编:

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

在SciTE交互模式下运行时,它将立即崩溃。Windows调试器应弹出一秒钟的时间。控制台输出将如下所示:

--> 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

您可以将其缩短为四个字节,例如ja 0
Mark K Cowan

1
或三位代表ud2
Mark K Cowan

1
可能是因为它试图跳转到某些数据吗?
阿苏

5

TI-83十六进制组件,2字节

PROGRAM:I
:AsmPrgmED77

运行为Asm(prgmI)。执行非法的0xed77操作码。我将每对十六进制数字都视为一个字节。




1

Linux Shell,9个字节

kill -4 0

发送SIGILL给PID为0的进程。我不知道哪个进程的PID为0,但它始终存在。

在线尝试!


来自man kill0 All processes in the current process group are signaled.
丹尼斯

1

GNU C,24 19 18字节

-4感谢Dennis
-1感谢ceilingcat

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

在线尝试!假设使用ASCII和x86_64。它尝试运行机器代码27,这是非法的。


shortC10 5 4字节

AV"'

等效于上面的GNU C代码。在线尝试!


L"\6"假设x86_64,也是非法的。
丹尼斯

@Dennis 0x06是什么指令?同样,这L不是必需的。
MD XF

未分配。
丹尼斯

未分配;这就是使它非法的原因。此外,'39 = 0x27,而不是0x39
丹尼斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.