다음 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)')//
답변
서문 : http://jsfiddle.net/WZXYr/2/ 에서 코드를 광범위하게 아름답게 수정하고 주석을 달았습니다.
가장 바깥 쪽 레이어를 고려하십시오.
eval(z = '...');
코드 문자열은 변수에 저장됩니다 z
. 할당 연산자는 할당 된 값을 반환하므로 코드 문자열도에 인수로 전달됩니다 eval
.
코드 문자열 z
은 eval
. 코드는 정리하더라도 매우 둔감하지만 다음과 같이 보입니다.
- 문자로 구분 된 base-36 숫자의 문자열을 구문 분석합니다
4
. - 글로벌 변수를 사용하여, 값의 맵을 채우고
e
,x
및y
홀드 상태에지도. 지도 상태는 부분적으로 벽시계 (new Date / 1e3
) 에서 현재 초의 함수입니다 . - 맵 값을 사용하여 코드는 출력 문자열을 생성합니다.
p
- 코드 사용은
p += " *#"[index]
공간, 별표 (*) 또는 해시 마크의 사용 여부를 결정하는index
사실이다e[x++] + e[x++]
(위에서 말했듯이,e
및x
지도 상태에 대한 책임이 있습니다) - 인덱스가의 길이보다 크면
" *#"
출력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)')
-
for
루프 출력 문자열의 각 문자를 추가한다p
(문자열 길이 172 개 문자이다)for(i=0;i<172;++i)
-
내부 조건은 애니메이션 캐릭터 인 62에서 67 사이의 캐릭터에 있는지 여부를 결정합니다.
if(i > 62 && i < 67)
-
그렇다면
!---
두 번째 벽시계 값의 10 분의 1을 기준으로 이동 하여를 출력 합니다. 이것은 애니메이션 효과를 제공합니다.p+="!---"[~~(new Date/1e2 + i)%4]
(
new Date
날짜 값을 0과 3 사이의 숫자로 변환하기 위해 주변의 모든 불쾌 함 이 실제로 존재합니다.) -
그렇지 않고 애니메이션 캐릭터가 아니라면 색인을 인쇄하십시오.
i
의해 정의 된 문자열에서 문자"eval(z='" + z + "')"
즉, and로
z
둘러싸인 코드 문자열eval('
')
입니다. -
마지막으로 문자열을 출력하고을 사용
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 메서드를 됩니다. - 각 줄 뒤에 후행 백 스페이스와 줄 바꿈이에 추가되고
p
HTML 문자열이 문서 본문에 할당됩니다.
최소한의 예에서 동일한 효과를 어떻게 다시 작성할 수 있습니까?
다음은 다른 예입니다.
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의 데모 )
이러한 종류의 애니메이션에 필요한 모든 관련 항목이 있습니다.
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>
요소 를 통한 출력 - 코드의 일부를 애니메이션 문자열로 바꾸기
답변
모든 코드가 포함 된 문자열이 평가되고 시간 초과가 루프를 만듭니다. 문자열라는 변수에 저장되어있는 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
}