SORU
13 Mart 2013, ÇARŞAMBA


Obfuscated C Code Contest 2006. Sykes2 açıklayınız.c

Nasıl bu C program çalışıyor mu?

main(_){_^448&&main(-~_);putchar(--_d?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}

(gcc 4.6.3 test) derler. Derlenmiş zaman yazdırır. Sistem: benim

    !!  !!!!!!              !!  !!!!!!              !!  !!!!!! 
    !!  !!  !!              !!      !!              !!  !!  !! 
    !!  !!  !!              !!      !!              !!  !!  !! 
    !!  !!!!!!    !!        !!      !!    !!        !!  !!!!!! 
    !!      !!              !!      !!              !!  !!  !! 
    !!      !!              !!      !!              !!  !!  !! 
    !!  !!!!!!              !!      !!              !!  !!!!!!

Kaynak: sykes2 - A clock in one line, sykes2 author hints

Bazı ipuçları: varsayılan başına uyarılar derleme. -Wall, derlenmiş, aşağıdaki uyarı üretilir

sykes2.c:1:1: warning: return type defaults to ‘int’ [-Wreturn-type]
sykes2.c: In function ‘main’:
sykes2.c:1:14: warning: value computed is not used [-Wunused-value]
sykes2.c:1:1: warning: implicit declaration of function ‘putchar’ [-Wimplicit-function-declaration]
sykes2.c:1:1: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
sykes2.c:1:1: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
sykes2.c:1:1: warning: control reaches end of non-void function [-Wreturn-type]

CEVAP
13 Mart 2013, ÇARŞAMBA


Hadi de bu nedenle.

Girintileme:

main(_) {
    _^448 && main(-~_);
    putchar(--_d
        ? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
        : 10);
}

Değişkenleri bu karmaşa çözmek için tanıtımı:

main(int i) {
    if(i^448)
        main(-~i);
    if(--i % 64) {
        char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
        char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    } else {
        putchar(10); // newline
    }
}

-~i == i 1 ikişer-tamamlayıcı yüzünden unutmayın. Bu nedenle, var

main(int i) {
    if(i != 448)
        main(i 1);
    i--;
    if(i % 64 == 0) {
        putchar('\n');
    } else {
        char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
        char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    }
}

Şimdi, 59**, ve -~ == 1 değişim daha geçerli olduğunu unutmayın:

main(int i) {
    if(i != 448)
        main(i 1);
    i--;
    if(i % 64 == 0) {
        putchar('\n');
    } else {
        char a = (">'txiZ^(~z?"-48)[(__TIME__-i/8%8)[7]]   1;
        char b = a >> ";;;====~$::199"[(i*2&8)|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    }
}

Bir döngü için özyineleme dönüştürme ve biraz daha sadeleştirme gizlice

// please don't pass any command-line arguments
main() {
    int i;
    for(i=447; i>=0; i--) {
        if(i % 64 == 0) {
            putchar('\n');
        } else {
            char t = __TIME__[7 - i/8%8];
            char a = ">'txiZ^(~z?"[t - 48]   1;
            int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
            if((i & 2) == 0)
                shift /= 8;
            shift = shift % 8;
            char b = a >> shift;
            putchar(32 | (b & 1));
        }
    }
}

Bu yineleme başına bir karakter verir. Her 64 karakter, bir satır çıktısını verir. Aksi takdirde, veri tabloları bir çift çıkış için, ve her iki karakter 32 (boşluk) veya karakter 33 koyar anlamaya (!) kullanır. İlk tablo (">'txiZ^(~z?") 10 bit eşlem her karakter görünümünü tarif eden bir dizi ve ikinci tablo (";;;====~$::199") bit eşlem görüntülemek için uygun bit seçer.

İkinci tablo

Başlangıç ikinci tablo, int shift = ";;;====~$::199"[(i*2&8) | (i/64)]; inceleyerek izin verin. i/64 satır sayısı (6, 0) ve i*2&8 i 4, 5, 6 veya 7 mod 8 8 ıff.

if((i & 2) == 0) shift /= 8; shift = shift % 8 ya da yüksek sekizlik rakam (i%8 = 0,1,4,5 için) veya tablo düşük sekizlik rakam (i%8 = 2,3,6,7) değerini seçer. Vardiya tablosu bu gibi bakıyor sona erer

row col val
6   6-7 0
6   4-5 0
6   2-3 5
6   0-1 7
5   6-7 1
5   4-5 7
5   2-3 5
5   0-1 7
4   6-7 1
4   4-5 7
4   2-3 5
4   0-1 7
3   6-7 1
3   4-5 6
3   2-3 5
3   0-1 7
2   6-7 2
2   4-5 7
2   2-3 3
2   0-1 7
1   6-7 2
1   4-5 7
1   2-3 3
1   0-1 7
0   6-7 4
0   4-5 4
0   2-3 3
0   0-1 7

ya da tablo şeklinde

00005577
11775577
11775577
11665577
22773377
22773377
44443377

Yazarın ilk iki tablo girdileri için null sonlandırıcı (gizli!) kullanılan unutmayın.

Bu boşlukları 7s ile yedi segment display, sonra tasarlanmıştır. Bu yüzden, ilk tablodaki girişleri yaktı kalk kesimleri tanımlamak gerekir.

İlk tablo

__TIME__ özel bir makro ön işlemci tarafından tanımlanır. Bir dize sabit, işleyişi, şeklinde "HH:MM:SS" çalıştırıldığı zaman içeren genişler. Tam olarak 8 karakter içerir inceleyin. 0-9 ASCII değerleri 48 ile 57 : ASCII değeri 58 olduğunu unutmayın. Çıkış __TIME__ karakter başına 8 karakter kalıyor her satırda 64 karakter.

7 - i/8%8 böylece halen çıkış olan __TIME__ Endeksi (7- i aşağıya doğru yineleme olduğumuz için tabi). Yani, t __TIME__ karakteri çıktı.

a ikili aşağıdaki tipidir, 46**: girişine bağlı olarak biter

0 00111111
1 00101000
2 01110101
3 01111001
4 01101010
5 01011011
6 01011111
7 00101001
8 01111111
9 01111011
: 01000000

Her sayı birbit eşlemyedi-segment bizim yaktı bu kesimleri görüntü tarif. Karakter 7-bit ASCII olduğu için, yüksek bit her zaman temizlenir. Böylece, 48* *segmentinde tablo hep boş olarak yazdırır. İkinci tablo boşlukları: 7s ile bu gibi görünüyor

000055  
11  55  
11  55  
116655  
22  33  
22  33  
444433  

Bu yüzden, örneğin, 51* *olarak yazdıran 01101010 (bit 1, 3, 5, ve 6 set),

----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--

Biz gerçekten kodu anlamak göstermek için, diyelim ki çıktı, bu tablo ile biraz ayarlayın:

  00  
11  55
11  55
  66  
22  33
22  33
  44

Bu "?;;?==? '::799\x07" olarak kodlanır. Sanatsal amaçlar için ekleyeceğiz 64 için bir kaç karakter (beri sadece düşük 6 bit kullanılır, bu kötü etkilemez çıkış); bu verir "?{{?}}?gg::799G" (not 8 karakter kullanılmayan, yani biz aslında yapmak istediğimiz her şeyi alacağız). Orijinal kodu yeni bizim masaya koyarak:

main(_){_^448&&main(-~_);putchar(--_d?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>"?{{?}}?gg::799G"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}

alıyoruz

          !!              !!                              !!   
    !!  !!              !!  !!  !!  !!              !!  !!  !! 
    !!  !!              !!  !!  !!  !!              !!  !!  !! 
          !!      !!              !!      !!                   
    !!  !!  !!          !!  !!      !!              !!  !!  !! 
    !!  !!  !!          !!  !!      !!              !!  !!  !! 
          !!              !!                              !!   

tam beklediğimiz gibi. Yazarın yaptığı tabloyu kullanmak için seçtim anlatan özgün, sağlam görünüşlü olarak değil.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Feel The Electricity!

    Feel The Ele

    20 ŞUBAT 2010
  • HowToBasic

    HowToBasic

    8 Aralık 2011
  • UnboxTechnology

    UnboxTechnol

    20 Ocak 2011