93

次の JavaScript はどのように機能しますか?

縮小コードであることは理解しています。少し難読化を解除しようとしましたが、この効果がどのように達成されるかについて明確な概念を得ることができません。ある種の反復、Date オブジェクトの使用、奇妙な文字列操作、Math 関数の使用に Strings を使用していることがわかります。その後、コード自体が出力されます。

最小限の例で同じ効果をどのように書き直すことができるでしょうか?

eval(z='p="<"+"pre>"/* ,.oq#+     ,._, */;for(y in n="zw24l6k\
4e3t4jnt4qj24xh2 x/* =<,m#F^    A W###q. */42kty24wrt413n243n\
9h243pdxt41csb yz/* #K       q##H######Am */43iyb6k43pk7243nm\
r24".split(4)){/* dP      cpq#q##########b, */for(a in t=pars\
eInt(n[y],36)+/*         p##@###YG=[#######y */(e=x=r=[]))for\
(r=!r,i=0;t[a/*         d#qg `*PWo##q#######D */]>i;i+=.05)wi\
th(Math)x-= /*        aem1k.com Q###KWR#### W[ */.05,0>cos(o=\
new Date/1e3/*      .Q#########Md#.###OP  A@ , */+x/PI)&&(e[~\
~(32*sin(o)*/* ,    (W#####Xx######.P^     T % */sin(.5+y/7))\
+60] =-~ r);/* #y    `^TqW####P###BP           */for(x=0;122>\
x;)p+="   *#"/* b.        OQ####x#K           */[e[x++]+e[x++\
]]||(S=("eval"/* l         `X#####D  ,       */+"(z=\'"+z.spl\
it(B = "\\\\")./*           G####B" #       */join(B+B).split\
(Q="\'").join(B+Q/*          VQBP`        */)+Q+")//m1k")[x/2\
+61*y-1]).fontcolor/*         TP         */(/\\w/.test(S)&&"#\
03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)')//

JSFiddle

4

4 に答える 4

69

序文: http://jsfiddle.net/WZXYr/2/で広範囲にわたってコードを美化し、注釈を付けました。

最も外側の層を考えてみましょう:

eval(z = '...');

変数 にはコード文字列が格納されますz。代入演算子は割り当てられた値を返すため、コード文字列も引数として に渡されますeval

コード文字列zは の内部で実行されevalます。クリーンアップしても、コードは非常にわかりにくいですが、次のように見えます。

  1. 文字で区切られた base-36 数値の文字列を解析します4
  2. グローバル変数ex、およびを使用して値のマップを設定し、yマップの状態を保持します。マップの状態の一部は、壁時計の現在の秒の関数です ( new Date / 1e3)。
  3. マップ値を使用して、コードは出力文字列を生成します。p
    • コードはp += " *#"[index]、スペース、アスタリスク、またはハッシュマークを使用するかどうかを決定するために使用します。index実際にはe[x++] + e[x++](上記のように、eマップxの状態を担当します)
    • インデックスが の長さよりも大きい場合、出力に からの文字" *#"を入力するフォールバック コードがあります。内側のキャラクタにはアニメーション キャラクタが取り込まれ、外側のキャラクタは から取得されます。pzz

コードの最後にはsetTimeout(z)、コード文字列を非同期的に評価するへの呼び出しがありますz。この の繰り返し呼び出しzにより、コードをループさせることができます。

簡単な例:

これは非常に単純なバージョンです ( http://jsfiddle.net/5QXn8/ ):

eval(z='p="<"+"pre>";for(i=0;i<172;++i)if(i > 62 && i < 67)p+="!---"[~~(new Date/1e2 + i)%4];else p += ("eval(z=\'" + z + "\')")[i];document.body.innerHTML = p;setTimeout(z)')
  1. forループは、各文字を出力文字列に追加します(p文字列の長さは 172 文字です)。

    for(i=0;i<172;++i)
    
  2. 内側の条件は、位置 62 から 67 の間のキャラクター (アニメーション化されたキャラクター) にいるかどうかを決定します。

    if(i > 62 && i < 67)
    
  3. そうであれば!---、2 番目の壁時計値の 10 分の 1 に基づいてシフトされた を出力します。これにより、アニメーション効果が得られます。

    p+="!---"[~~(new Date/1e2 + i)%4]
    

    (厄介なnew Dateことはすべて、日付値を 0 から 3 の間の数値に変換するためだけに存在します。)

  4. それ以外の場合、アニメーション化されたキャラクターでない場合は、iによって定義された文字列からインデックス文字を出力します

    "eval(z='" + z + "')"
    

    つまり、 と で囲まzれたコード文字列です。eval('')

  5. 最後に、文字列を出力し、次setTimeoutの別の実行をキューに入れるために使用しますz

    document.body.innerHTML = p;setTimeout(z)
    

私の最終的な出力は完全に正しくないことに注意してください末尾のバックスラッシュを考慮していませんが、それでも、テクニックが一般的にどのように機能するかについてはかなり良いアイデアが得られるはずです。

于 2013-09-16T19:18:44.390 に答える
36

注釈付きソースはこちら。Ps: 私は作者です ;)

function z(){                     // will be replaced with eval

  p = "<" + "pre>";               // use <pre> tag for formatted output

  for (                           // loop though lines
    y in n = (                    // y - the line number
      "zw24"      +               // n - the encoded data
      "l6k4"      +               // every line holds encoded data
      "e3t4"      +
      "jnt4"      +               // string will be concated in build process
      "qj24"      +
      "xh2  4"    +               // data after spaces will be ignored but
      "2kty24"    +               // … is used to not break block comments
      "wrt4"      +               // … which will save some chars
      "13n24"     +
      "3n9h24"    +
      "3pdxt4"    +
      "1csb   4"  +
      "3iyb6k4"   +
      "3pk724"    +
      "3nmr24"
    ).split(4)                    // data will be split by (unused) 4

  ){
    for (                         // loop throug every char in line
      a in t = parseInt(          // numbers are encoded as string
        n[y],                     // … with a base of 36
        36
      ) + (                       // large number will be converted to string
        e =                       // e - holds the rendered globe
        x =                       // x - horizonal position
        r = []                    // r - bitmap flag if pixel is set
      )
    ){
      r = !r;                     // toggle binary flag

      for (                       // look though bitmap states
        i = 0;                 
        t[a] > i;                 // draw pixel t[a]-times
        i += .05
      )
        with (Math)               // refer to Math later
          x -= .05,
          0 > cos(                // prevent backface visibility
            o =
              new Date / 1e3 +    // get rotation based on current time
              x / PI
          ) && (
            e[                    // access matrix
              ~~(                 // convert float to integer
                sin(o) *          // rotate around y axis
                sin(.5 + y/7) *
                32                // scale up the globe
              ) + 60              // move to center
            ] = -~r               // store bitmap state in render matrix
          )
    }

    for (                         // loop through columns
      x = 0;
      122 > x;                    // break after char 122
    ) p += "   *#"[               // add space, asterisk or hash
        e[x++] +                  // … based pixel opacity
        e[x++]
      ] || (S = (                 // otherwise use the original code
        "eval(z='" +              // inception of missing "eval" statement
          z
            .split(B = "\\")      // escape \ with \\
            .join(B + B)

            .split(Q = "'")       // escape ' with \'
            .join(B + Q) +

          Q +                     // add missing ')

          ")////////"             // add extra chars to fill mapping
        )[
          x / 2 +                 // get character at current position
          61 * y-1
        ]

      ).fontcolor(                // colorize outpu
        /\w/.test(S) &&           // test for [0-9A-Z]
        "#03B"                    // render blue
                                  // otherwise pink (default)
      );

    document.body.innerHTML =     // render output
      p +=                        // append new line
      B +                         // add backspace
      "\n";                       // add new line
  }

  setTimeout(z)                   // render animation on next frame
}
z()
于 2013-09-23T16:34:24.757 に答える
21

これは手動で難読化を解除した別のバージョンで、すべての初期化を式から独自のステートメントに移動しています。

z='p="<"+"pre>"/* ,.oq#+     ,._, */;for(y in n="zw24l6k\
4e3t4jnt4qj24xh2 x/* =<,m#F^    A W###q. */42kty24wrt413n243n\
9h243pdxt41csb yz/* #K       q##H######Am */43iyb6k43pk7243nm\
r24".split(4)){/* dP      cpq#q##########b, */for(a in t=pars\
eInt(n[y],36)+/*         p##@###YG=[#######y */(e=x=r=[]))for\
(r=!r,i=0;t[a/*         d#qg `*PWo##q#######D */]>i;i+=.05)wi\
th(Math)x-= /*        aem1k.com Q###KWR#### W[ */.05,0>cos(o=\
new Date/1e3/*      .Q#########Md#.###OP  A@ , */+x/PI)&&(e[~\
~(32*sin(o)*/* ,    (W#####Xx######.P^     T % */sin(.5+y/7))\
+60] =-~ r);/* #y    `^TqW####P###BP           */for(x=0;122>\
x;)p+="   *#"/* b.        OQ####x#K           */[e[x++]+e[x++\
]]||(S=("eval"/* l         `X#####D  ,       */+"(z=\'"+z.spl\
it(B = "\\\\")./*           G####B" #       */join(B+B).split\
(Q="\'").join(B+Q/*          VQBP`        */)+Q+")//m1k")[x/2\
+61*y-1]).fontcolor/*         TP         */(/\\w/.test(S)&&"#\
03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)';

p = "<" + "pre>";
n = ["zw2", "l6k", "e3t", "jnt", "qj2", "xh2 x/* =<,m#F^    A W###q. */", "2kty2", "wrt", "13n2", "3n9h2", "3pdxt", "1csb yz/* #K       q##H######Am */", "3iyb6k", "3pk72", "3nmr2", ""]
for (y in n) {
    e = [];
    x = 0;
    r = true;
    t = parseInt(n[y], 36) + "";
    for (a in t) {
        r = !r
        for (i = 0; i < t[a]; i += 0.05) {
             x -= 0.05;
             o = new Date / 1e3 + x / Math.PI
             if (Math.cos(o) < 0)
                 e[~~(32 * Math.sin(o) * Math.sin(0.5 + y / 7)) + 60] = -~r;
        }
    for (x = 0; x < 122;) {
        S = "eval" + "(z='" + z.split(B = "\\").join(B + B).split(Q = "'").join(B + Q) + Q + ")//m1k"
        p += "   *#"[e[x++] + e[x++]] || S[x/2+61*y-1]).fontcolor(/\w/.test(S[x/2+61*y-1]) && "#03B");
    }
    p += B + "\n";
    document.body.innerHTML = p;
}
setTimeout(z)

何が起こるかは次のとおりです。

  • zすべてのコードを含む複数行の文字列です。evalエドです。
  • コードの最後で、 にz渡されsetTimeoutます。可能な限り高いレートで間隔を置いて評価することで、同様に機能requestAnimationFrameします。eval
  • コード自体pが 、HTML が追加される文字列バッファ、およびnbase-36 でエンコードされた数値の配列 ( によって文字列に結合され"4"、コメントは によって考慮されない無関係なガベージですparseInt) を初期化します。
  • の各数値はn1 行をエンコードします ( n.length == 16)。現在列挙されています。
  • 一連の変数が初期化され、一部はe配列リテラルに偽装されますが、使用時に数値 ( x) またはブール値 ( r) または文字列 ( t) にキャストされます。
  • 数値の各桁tが列挙され、r各ターンでブール値が反転されます。さまざまな角度の場合、および現在の時間xに応じて(アニメーションを提供するため)、配列はいくつかのビット単位の演算子を使用して埋められます- when is false およびs when is true その時点で。 new Date / 1000e1r2r
  • 次に、ループは画像の 61 列x=0を 122 まで 2 ステップで反復し、1 文字を に追加しpます。
  • BSバックスラッシュであるため、バックスラッシュとアポストロフィをエスケープすることによってコード文字列から文字列が構築されz、ソースでの外観を正確に表現します。
  • からの 2 つの連続する数字ごとeに追加され、 からの文字にアクセスするために使用さ" *#"れ、アニメーション イメージを構築します。インデックスの 1 つが定義されていない場合、インデックスはNaN未定義の文字に解決され、代わりに文字列からそれぞれのS文字が取得されます (式を確認してくださいx/2+61*y-1)。その文字が単語文字である必要がある場合は、 fontcolorString メソッドを使用して異なる色で表示されます。
  • 各行の後に、末尾のバックスペースと改行が に追加されp、HTML 文字列がドキュメントの本文に割り当てられます。

最小限の例で同じ効果をどのように書き直すことができるでしょうか?

次に例を示します。

setInterval(z='s=("setInterval(z=\'"+\
z.replace(/[\\\\\']/g,"\\\\$&")+"\')"\
).match(/.{1,37}/g).join("\\\\\\n");d\
ocument.body.innerHTML="<\\pre>"+s.sl\
ice(0, 175)+String( + new Date()).fon\
tcolor("red")+s.slice(188)')

この種のアニメーションに必要な関連事項がすべて含まれています。

  • setIntervalそしてDateアニメーションに

  • 独自のコード ( quineのようなもの) の再構成:

      s = ( "setInterval(z='" // the outer invokation
            + z.replace(/[\\\']/g,"\\$&") // the escaped version
          + "\')" ) // the end of the assignment
          .match(/.{1,37}/g).join("\\\n"); // chunked into lines
    
  • 出力ビアdocument.body.innerHTML<pre>要素

  • コードの一部をアニメーション文字列に置き換える

于 2013-09-16T20:12:01.553 に答える