2011-01-18 14 views
7


Questo frammento di codice mi ha fatto impazzire, qualcuno potrebbe aiutarmi a spiegare questo?Hai bisogno di aiuto per spiegare un codice C++ offuscato?

#include <stdio.h> 
char*_="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX"; 
int main(int l){for(l+=7;l!=putchar(010);++l);if(*(++_))main 
    (*_!=88?(putchar(*_^073)|putchar(33))&1:0xffff2a8b);} 

Grazie,
Chan Nguyen

+3

Rifiuta offuscamento. –

+2

Appiccare il fuoco a questo pezzo di codice. –

+0

@Fred Larson: ho cercato su Google, ma non sono riuscito a trovare alcuna informazione pertinente. Potresti condividere un po 'di luce? – Chan

risposta

7

Al fine di capire come funziona questo codice, avviare riscrittura in modo leggibile:

#include <stdio.h> 

char*_="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX"; 

int main(int l) 
{ 
    for(l += 7; l != putchar(010); ++l) { 
    } 

    if(*(++_)) { 
     main((*_ != 88) ? (putchar(*_^073) | putchar(33))&1 : 0xffff2a8b); 
    } 

    return 0; 
} 

Ora cerchiamo di capire che:

  • il suo parametro l (che sarà essere 1, se si esegue questo programma senza parametri) viene incrementato di 7 (diventa 8)

  • il ciclo stamperà 010 (ottale per 8: ascii backspace) fino l==8 (quindi non farà nulla quando si eseguire il programma

  • se il carattere successivo puntato da _x ora) è diverso da 0 (questo probabilmente significa "fino a quando abbiamo raggiunto la fine del _"), main si chiama, ma consente di vedere ciò che accade mentre stiamo valutando i suoi parametri:

    • il carattere correntemente puntata dal _ è diverso da 88 (88 è x in ASCII), quindi il parametro principale sarà il risultato dell'espressione (putchar(*_^073) | putchar(33))&1:

      valutando main 's parametri due caratteri vengono stampati

      • primo è: *_^073, che è, 120^59 (poiché x è 120, in aSCII, e 073 in ottale è 59 in decimale), che è 67: 120 (0b1000011) XOR 59 (0b111011) = 67 0b1000011

      • secondo è 33 (!)

      main parametro sarà poi il risultato di (67|33)&1, che è 1

Se si vuole veramente capire cosa succederà nei dettagli dovrai continuare con questo lavoro, ma sarai in grado di vedere cosa succede eseguendo il programma (magari mettilo usleep(10000) da qualche parte, in modo da poter effettivamente vedere l'output). Scriverà una stringa rotante "Corsix!".

Scrivere un programma come questo è abbastanza semplice: una volta deciso come funziona l'algoritmo, è facile generare una stringa, come _, che fa generare all'algoritmo ciò che si desidera, ma per decodificarlo è molto più difficile .

+0

Mille grazie per i tuoi grandi sforzi! – Chan

4

Mentre questo pezzo di codice non è conforme allo standard, gcc lo compila e l'output è coerente con la mia analisi del codice. Purtroppo, non riesco davvero a interpretare l'output senza un po 'più di contesto. Se ignoro le backspace, l'output simile a questa:

C!o!r!s!i!... 

per analizzare il codice, inizieremo con la formattazione un po ':

#include <stdio.h> 

char* _ ="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX"; 

int main(int l){ 
    for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char 
    if(*(++_)) 
     main(
      *_ != 88 ? // *_ != 'X' 
       (putchar(*_^073) | putchar(33)) & 1 : // 33 = '!' 
       0xffff2a8b); 
} 

Ecco un paio di cose da notare prima di vai oltre:

  1. Se putchar riesce, restituisce il carattere che è stato passato.
  2. In C, i numeri che iniziano con 0 sono in realtà ottali e non decimali. Quindi 010 è davvero il numero decimale 8.

Ora notare che ogni volta che il puntatore _ è in output, è XOR con il valore ottale 073. Se applichiamo questo su l'intera stringa otteniamo:

cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc 

Inizia a somigliare all'output che abbiamo visto in precedenza. Riprendiamo analizzando alcune delle linee più interessanti:

for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char 

Il punto di questa linea è quello di produrre una serie di backspaces. Se l è uguale a 1, emetterà solo un backspace. Ma se è uguale a qualcos'altro, impazzisce nelle discariche di un camion carico di caratteri. Il comportamento dipende da come viene chiamato main. All'avvio, sembra essere sempre chiamato con il valore 1 (non so perché).

Ora diamo un'occhiata ai componenti della chiamata principale ricorsiva.

(putchar(*_^073) | putchar(33)) & 1 : // 33 = '!' 

Questo è il primo ramo possibile. Prima emette uno dei caratteri XORed e poi emette un '!' char. Se osservate il modello di bit di 33, noterete che (x | 33) & 1 valuterà sempre a 1. Quindi in questo caso stiamo solo emettendo un singolo carattere di backspace nel ciclo for.

Il secondo ramo invece è un po 'più complicato perché il valore passato a main non è 1. Se si guarda attentamente l'output del programma si noterà che emette un carico di backspaces su un determinato camion posto nella stringa. Senza contesto, non posso davvero dire quale sia l'obiettivo.

Ora che abbiamo tutti i pezzi, cerchiamo di riscrivere il codice:

#include <stdio.h> 

#define BIG_CONSTANT 42 // Not the actual value. 

int main() { 
    char* str = "cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc"; 

    putchar(8); 

    char* c = str; 
    while (*c != '\0') { 

     if (*c != 'c') { // 'X'^073 = 'c' 
      putchar(*c); 
      putchar('!'); 
      putchar(8); 
     } 
     else { 
      for (int i = 0; i < BIG_CONSTANT; ++i) 
       putchar(8); 
     } 
     c++; 
    } 
} 

mio C è un po 'arrugginito quindi questo potrebbe non compilare/run. Dovrebbe comunque darti una buona idea di cosa sta succedendo.

EDIT: Beh, ero un po 'in ritardo nel pubblicare la mia risposta e ho appena realizzato che la mia console stava stampando i backspaces un po' alla lettera invece di rimuovere solo caratteri. Ecco perché ho interpretato un po 'male l'output. Quindi, come dice la risposta accettata, se si elaborano correttamente i backspaces, stampa Corsix !.

+0

Wow! Grazie mille;) – Chan

+0

@ Chan Ora che ne guardo un'altra, penso di aver fatto un errore da qualche parte. Se guardi il codice C, tutti i '!' i caratteri verranno cancellati dal backspace che viene emesso subito dopo. Dato che il comportamento è abbastanza banale, penso che l'analisi sia ciò che conta davvero qui, quindi non darò la caccia al problema. –

Problemi correlati