Comment fonctionne ce programme C?
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
Il se compile tel quel (testé sur gcc 4.6.3
). Il imprime l'heure lors de la compilation. Sur mon système:
!! !!!!!! !! !!!!!! !! !!!!!!
!! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !!
!! !!!!!! !! !! !! !! !! !!!!!!
!! !! !! !! !! !! !!
!! !! !! !! !! !! !!
!! !!!!!! !! !! !! !!!!!!
Source: sykes2 - Une horloge sur une seule ligne , suggère l'auteur sykes2
Quelques conseils: Aucun avertissement de compilation par défaut. Compilé avec -Wall
, les avertissements suivants sont émis:
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]
c
obfuscation
deobfuscation
banal
la source
la source
printf("%d", _);
au début desmain
impressions: pastebin.com/HHhXAYdJint
./a.out $(seq 0 447)
Réponses:
Désobscurcissons-le.
Indentation:
Présentation de variables pour démêler ce gâchis:
Notez cela à
-~i == i+1
cause du complément à deux. Par conséquent, nous avonsMaintenant, notez que
a[b]
c'est la même choseb[a]
et appliquez à-~ == 1+
nouveau la modification:Convertir la récursivité en boucle et se faufiler dans un peu plus de simplification:
Cela génère un caractère par itération. Chaque 64ème caractère, il sort une nouvelle ligne. Sinon, il utilise une paire de tableaux de données pour déterminer ce qu'il faut sortir et met soit le caractère 32 (un espace) soit le caractère 33 (a
!
). Le premier tableau (">'txiZ^(~z?"
) est un ensemble de 10 bitmaps décrivant l'apparence de chaque caractère, et le second tableau (";;;====~$::199"
) sélectionne le bit approprié à afficher dans le bitmap.Le deuxième tableau
Commençons par examiner la deuxième table,
int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
.i/64
est le numéro de ligne (6 à 0) eti*2&8
est 8 ssii
4, 5, 6 ou 7 mod 8.if((i & 2) == 0) shift /= 8; shift = shift % 8
sélectionne soit le chiffre octal haut (pouri%8
= 0,1,4,5), soit le chiffre octal bas (pouri%8
= 2,3,6,7) de la valeur du tableau. La table de décalage finit par ressembler à ceci:ou sous forme de tableau
Notez que l'auteur a utilisé le terminateur nul pour les deux premières entrées de table (sournois!).
Ceci est conçu après un affichage à sept segments, avec
7
s comme blancs. Ainsi, les entrées du premier tableau doivent définir les segments qui s'allument.Le premier tableau
__TIME__
est une macro spéciale définie par le préprocesseur. Il se développe en une constante de chaîne contenant l'heure à laquelle le préprocesseur a été exécuté, sous la forme"HH:MM:SS"
. Notez qu'il contient exactement 8 caractères. Notez que 0-9 ont des valeurs ASCII 48 à 57 et:
une valeur ASCII 58. La sortie est de 64 caractères par ligne, ce qui laisse 8 caractères par caractère de__TIME__
.7 - i/8%8
est donc l'indice de ce__TIME__
qui est actuellement en cours de sortie (le7-
est nécessaire parce que nous itéronsi
vers le bas). Donc,t
c'est le caractère d'__TIME__
être sorti.a
finit par égaler ce qui suit en binaire, selon l'entréet
:Chaque numéro est un bitmap décrivant les segments qui sont allumés dans notre affichage à sept segments. Comme les caractères sont tous en ASCII 7 bits, le bit haut est toujours effacé. Ainsi,
7
dans la table des segments, l'impression est toujours vide. Le deuxième tableau ressemble à ceci avec le7
s en blanc:Ainsi, par exemple,
4
est01101010
(bits 1, 3, 5 et 6 définis), qui s'imprime commePour montrer que nous comprenons vraiment le code, ajustons un peu la sortie avec ce tableau:
Ceci est codé comme
"?;;?==? '::799\x07"
. À des fins artistiques, nous ajouterons 64 à quelques-uns des caractères (puisque seuls les 6 bits les plus faibles sont utilisés, cela n'affectera pas la sortie); cela donne"?{{?}}?gg::799G"
(notez que le 8ème caractère n'est pas utilisé, nous pouvons donc en faire ce que nous voulons). Mettre notre nouvelle table dans le code d'origine:on a
comme nous nous y attendions. Ce n'est pas aussi solide que l'original, ce qui explique pourquoi l'auteur a choisi d'utiliser le tableau qu'il a fait.
la source
*
(déréférencement) et un+
: PFormater ceci pour une lecture plus facile:
Donc, en l'exécutant sans arguments, _ (argc conventionnellement) l'est
1
.main()
s'appellera récursivement lui-même, en passant le résultat de-(~_)
(NOT négatif au niveau du bit de_
), donc vraiment ça ira 448 récursions (Seulement condition où_^448 == 0
).En prenant cela, il imprimera 7 lignes larges de 64 caractères (la condition ternaire externe, et
448/64 == 7
). Alors réécrivons-le un peu plus propre:Maintenant,
32
est décimal pour l'espace ASCII. Il imprime un espace ou un '!' (33 est «!», D'où le «&1
» à la fin). Concentrons-nous sur le blob au milieu:Comme l'a dit une autre affiche,
__TIME__
c'est le temps de compilation du programme, et c'est une chaîne, donc il y a de l'arithmétique de chaîne en cours, ainsi que de tirer parti d'un indice de tableau bidirectionnel: a [b] est identique à b [a] pour les tableaux de caractères.Cela sélectionnera l'un des 8 premiers caractères de
__TIME__
. Il est ensuite indexé en[">'txiZ^(~z?"-48]
(0-9 caractères sont 48-57 décimaux). Les caractères de cette chaîne doivent avoir été choisis pour leurs valeurs ASCII. Cette même manipulation de code ASCII de caractère continue à travers l'expression, pour aboutir à l'impression d'un '' ou '!' en fonction de l'emplacement dans le glyphe du personnage.la source
Ajout aux autres solutions,
-~x
est égal àx+1
car~x
est équivalent à(0xffffffff-x)
. C'est égal à(-1-x)
en complément de 2s, il en-~x
est de même-(-1-x) = x+1
.la source
J'ai désobscurci autant que je le pouvais les arithmétiques modulo et j'ai supprimé
Élargir un peu plus:
la source