[javascript] 이 난독 화 된 JavaScript는 어떻게 작동합니까?

다음 JavaScript는 어떻게 작동합니까?

나는 그것이 축소 된 코드라는 것을 이해합니다. 난독 해제를 조금 시도했지만이 효과를 얻는 방법에 대한 명확한 개념을 얻을 수 없습니다. 어떤 종류의 반복, Date 객체 사용, 이상한 문자열 조작, Math 함수에 문자열을 사용하고 있음을 알 수 있습니다. 그러면 코드가 자체적으로 인쇄됩니다.

최소한의 예제로 동일한 효과를 어떻게 다시 작성할 수 있습니까?

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



답변

서문 : http://jsfiddle.net/WZXYr/2/ 에서 코드를 광범위하게 아름답게 수정하고 주석을 달았습니다.

가장 바깥 쪽 레이어를 고려하십시오.

eval(z = '...');

코드 문자열은 변수에 저장됩니다 z. 할당 연산자는 할당 된 값을 반환하므로 코드 문자열도에 인수로 전달됩니다 eval.

코드 문자열 zeval. 코드는 정리하더라도 매우 둔감하지만 다음과 같이 보입니다.

  1. 문자로 구분 된 base-36 숫자의 문자열을 구문 분석합니다 4.
  2. 글로벌 변수를 사용하여, 값의 맵을 채우고 e, xy홀드 상태에지도. 지도 상태는 부분적으로 벽시계 ( new Date / 1e3) 에서 현재 초의 함수입니다 .
  3. 맵 값을 사용하여 코드는 출력 문자열을 생성합니다. p
    • 코드 사용은 p += " *#"[index]공간, 별표 (*) 또는 해시 마크의 사용 여부를 결정하는 index사실이다 e[x++] + e[x++](위에서 말했듯이, ex지도 상태에 대한 책임이 있습니다)
    • 인덱스가의 길이보다 크면 " *#"출력 p을의 문자로 채우는 대체 코드가 있습니다 z. 내부 캐릭터는 애니메이션 캐릭터로 채워지고 외부 캐릭터는에서 가져옵니다 z.

코드 끝에는 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. 그렇다면 !---두 번째 벽시계 값의 10 분의 1을 기준으로 이동 하여를 출력 합니다. 이것은 애니메이션 효과를 제공합니다.

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

    ( new Date날짜 값을 0과 3 사이의 숫자로 변환하기 위해 주변의 모든 불쾌 함 이 실제로 존재합니다.)

  4. 그렇지 않고 애니메이션 캐릭터가 아니라면 색인을 인쇄하십시오.i 의해 정의 된 문자열에서 문자

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

    즉, and로 z둘러싸인 코드 문자열eval('') 입니다.

  5. 마지막으로 문자열을 출력하고을 사용 setTimeout하여 z다음 실행을 대기열에 추가합니다 .

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

내 최종 출력이되지 않도록주의 확실히 내가 끝으로 갈수록 백 슬래시를 차지하지 – -하지만 여전히 당신에게 기술이 일반적으로 어떻게 작동하는지 꽤 좋은 아이디어를 제공해야 맞다.


답변

다음은 주석이 달린 소스입니다. 추신 : 나는 저자 다;)

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()


답변

다음은 수동으로 난독 해제 된 또 다른 버전으로, 모든 초기화를 표현에서 벗어나 자신의 명령문으로 이동합니다.

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이 추가 될 문자열 버퍼 및 n기본 36으로 인코딩 된 숫자의 배열을 합니다 (에서 문자열에 조인되고 "4"주석은에서 고려되지 않는 관련없는 쓰레기 parseInt임).
  • 의 각 숫자는 n한 줄 ( n.length == 16)을 인코딩 합니다. 이제 열거 됩니다.
  • 많은 변수가 초기화되고 일부는 e일련 배열 리터럴 하지만 사용시 숫자 ( x), 부울 ( r) 또는 문자열 ( t) 로 캐스트 됩니다.
  • 숫자의 각 숫자 t가 열거되어 r매 턴마다 부울이 반전 됩니다. 다른 각도의 x경우 및 현재 시간 에 따라 new Date / 1000(애니메이션을 제공하도록) 배열 e은 일부 비트 연산자 를 사용하여 채워집니다. -로 1될 때 r잘못된이고 2때이야r 그 때 그러하다.
  • 그런 다음 루프는 이미지의 61 개 열을 반복합니다. x=0 두 번의 단계로 122 개 하여 단일 문자를p .
  • B백 슬래시 인 문자열 S은 코드 문자열에서 빌드됩니다.z 백 슬래시와 아포스트로피를 이스케이프 소스에서 보이는 내용을 정확하게 표현합니다.
  • 의 두 연속 번호 e가 추가되고에서 캐릭터에 액세스 " *#"하여 애니메이션 이미지를 만드는 데 사용됩니다 . 인덱스 중 하나가 정의되지 않은 경우 인덱스는 정의 NaN되지 않은 문자로 확인되고 대신 S문자열 의 각 문자를 가져옵니다 (공식 확인 x/2+61*y-1). 해당 문자가 단어 문자 여야 하는 경우fontcolor String 메서드를 됩니다.
  • 각 줄 뒤에 후행 백 스페이스와 줄 바꿈이에 추가되고 pHTML 문자열이 문서 본문에 할당됩니다.

최소한의 예에서 동일한 효과를 어떻게 다시 작성할 수 있습니까?

다음은 다른 예입니다.

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

( jsfiddle.net의 데모 )

이러한 종류의 애니메이션에 필요한 모든 관련 항목이 있습니다.

  • setIntervalDate 애니메이션
  • 자체 코드 ( 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>요소 를 통한 출력

  • 코드의 일부를 애니메이션 문자열로 바꾸기

답변

모든 코드가 포함 된 문자열이 평가되고 시간 초과가 루프를 만듭니다. 문자열라는 변수에 저장되어있는 z주석 사이에, 그리고 코드의 중간에 /**/에 “지구 ASCII 아트”가있다. 코드는 주석을 구문 분석하고 문서 내용을 변경하여 js를 유지하고 아트를 업데이트합니다. Bellow는 슬라이스 된 코드입니다.

  p="<pre>";
  for(y in n="zw24l6k4e3t4jnt4qj24xh2 x42kty24wrt413n243n9h243pdxt41csb yz43iyb6k43pk7243nmr24".split(4)){
    for(a in t = parseInt(n[y],36)+(e=x=r=[]))
      for(r=!r,i=0;t[a]>i;i+=.05)
        with(Math) x-= .05,0>cos(o=new Date/1e3+x/PI)&&(e[~~(32*sin(o)*sin(.5+y/7))+60] =-~ r);
          for(x=0;122>x;) p += "   *#"[e[x++]+e[x++\]] ||
              (S=("eval"+"(z=\'"+z.split(B = "\\\\").join(B+B).split(Q="\'").join(B+Q)+Q+")//m1k")[x/2+61*y-1]).fontcolor(/\\w/.test(S)&&"#\03B");
    p += B+"\\n"
    document.body.innerHTML= p
  }


답변