C (x86_64), 11, 30, 34 veya 34 + 15 = 49 bayt
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
SIGILL
Çeşitli yollarla atmak için kütüphane işlevlerini kullanan birkaç çözüm önerdim, ancak tartışmanın hile yaptığı, kütüphane işlevinin sorunu çözdüğüdür. Kütüphane işlevlerini kullanmayan ve işletim sisteminin çalıştırılabilir olmayan kodları çalıştırmanıza izin verme konusunda istekli olduğu konusunda çeşitli varsayımlarda bulunan çözümler. (Buradaki sabitler x86_64 için seçilmiştir, ancak yasa dışı talimatlara sahip çoğu diğer işlemciler için çalışma çözümleri almak üzere bunları değiştirebilirsiniz.)
06
x86_64 işlemci üzerindeki tanımlanmış bir talimatla uyuşmayan makine kodunun en düşük numaralı baytıdır. Tek yapmamız gereken onu yürütmek. (Alternatif olarak, 2F
aynı zamanda tanımsızdır ve tek bir yazdırılabilir ASCII karakterine karşılık gelir.) Bunların hiçbirinin her zaman tanımsız olması garanti edilmez, ancak bugün itibariyle tanımlanmamıştır.
Buradaki ilk program 2F
salt okunur veri bölümünden yürütülür . Bağlayıcıların çoğu , doğru bölümlere ayrılmış bir programda hiçbir zaman faydalı olamayacağından , .text
kendisinden .rodata
(veya işletim sistemlerinin eşdeğerinden) bir çalışma atlaması üretemez; Bunun üzerinde çalıştığı bir işletim sistemi bulamadım. Ayrıca birçok derleyicinin söz konusu dizginin geniş bir dize olmasını istemesine izin vermeniz gerekir;L
; Bunun üzerinde çalıştığı herhangi bir işletim sisteminin şeyleri oldukça eski bir görünüme sahip olduğunu ve bu nedenle varsayılan olarak C94 öncesi bir standart için oluşturulduğunu farz ediyorum. Bu programın çalıştığı hiçbir yerde olması mümkün değildir, ancak bu programın çalıştığı bir yerde olması da mümkün ve bu nedenle daha şüpheli-şüpheli-şüpheli-potansiyel şüpheli cevaplar koleksiyonunda listeliyorum. (Bu cevabı gönderdikten sonra Dennis main[]={6}
, aynı uzunluktaki ve karakter genişliği ile ilgili sorunlara rastlamayan ve hatta potansiyelini ima eden sohbet olasılığından da bahsetti main=6
; benim, kendileri hakkında düşünmediğim gibi.)
Buradaki ikinci program 06
okuma-yazma veri bölümünden yürütülür . Çoğu işletim sisteminde bu, segmentasyon hatasına neden olur, çünkü yazılabilir veri segmentleri, istismarları muhtemel kılan kötü bir tasarım hatası olarak kabul edilir. Yine de, her zaman böyle olmadı, bu yüzden muhtemelen yeterince eski bir Linux sürümünde çalışıyor, ancak kolayca test edemiyorum.
Üçüncü program 06
yığından yürütülür . Yine, bu, bugünlerde bir segmentasyon hatasına neden olmaktadır, çünkü yığın, güvenlik nedenleriyle normal olarak yazılamaz olarak sınıflandırılmaktadır. Gördüğüm bağlayıcı belgeler, yığıntan yürütmek için yasal olduğu anlamına gelir (önceki iki durumun aksine, bunu yapmak bazen yararlı olur), bu yüzden test edemesem de, biraz eminim. üzerinde çalıştığı Linux sürümü (ve muhtemelen diğer işletim sistemleri).
Son olarak, -Wl,-z,execstack
(15 bayt ceza) verirseniz ( arka ucun bir parçası olarak gcc
GNU kullanıyorsanız ld
), üçüncü programın çalışmasına ve beklendiği gibi yasadışı bir çalışma sinyali vermesine izin vererek çalıştırılabilir yığın korumasını açıkça kapatır. Ben var test edilmiş ve çalışmak için bu 49 bayt sürümünü doğrulandı. (Dennis, bu seçeneğin main=6
6 + 15 puan verecek görünüşte çalıştığı sohbette bahsetti . 6'nın açıkça yığında olmadığı göz önüne alındığında, bu seçeneğin çalıştığından oldukça şaşırdım; onun adı önerir.)
raise(SIGILL)
?