Programing

JavaScript의 내장 문자열은 무엇입니까?

lottogame 2020. 6. 15. 08:19
반응형

JavaScript의 내장 문자열은 무엇입니까?


이 질문은 질문 제목에 요약하기 어렵습니다

업데이트이 질문에서 추출한 문자를 기반으로 입력에서 난독 처리 된 문자열을 작성하는 JSFiddle을 만들었습니다. 여기에 액세스 할 수 있습니까 , 아니면 요점 이 더 쉬울까요?

최근 에이 프로파일 에서 다음과 같은 재미있는 난독 화 JavaScript를 보았습니다 .

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1
+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+([,][
~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+
1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

놀람을 망쳐 서 미안하지만 이것이 평가되면 다음을 반환합니다.

"I love you" in Chrome
"I lone you" In Firefox
"I lo[e you" in IE10

이것이 작동 할 때 작동하는 방식은 일련의 메시지를 생성하고 이와 같이 문자를 빼내는 것입니다 (예 : "I"사용).

[]+1/!1
returns
"Infinity"
then
[[]+1/!1]
creates this array:
["Infinity"]
then
[[]+1/!1][1^1]
Takes the first (1^1 == 0) element of that array
"Infinity"
finally
[[]+1/!1][1^1][1>>1]
Takes the first (1>>1 == 0) char of that string
"I"

생성되는 다른 문자열은 다음과 같습니다.

({}+[])       -> "[object Object]" (where the space comes from)
([]+!!-[])    -> "false" (used for it's "l")
[/~/+{}][+!1] -> "/~/[object Object]" (this is used for an "o")
(/<</[1]+[])  -> "undefined"

나는 "n"과 "["의 대체물을 찾는 데 관심이 있었고 이것을 생각해 냈습니다.

String.fromCharCode(('1'.charCodeAt(0)<<1)+(10<<1))

1과 0을 사용하는 느낌에서 느끼지만 문자열과 전혀 관련이없는 것처럼 보이는 원래 코드의보다 우아한 측면 중 하나를 위반합니다. 다른 사람이 원래 난독 처리 된 코드와 일치하는 "v"를 생성하는 방법에 대한 아이디어가 있습니까?

여기에 많은 유능한 JavaScript 프로그래머가 이것을 자세히 살펴본 후에 발견 된 추가 정보가 있습니다.

Firefox는 다음 줄 때문에 "고독"을 반환합니다.

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+

[1^11<<1] 이로부터 특정 문자를 잘라냅니다.

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])

이것은 다음과 같이 평가됩니다.

"function test() {
    [native code]
}"

"V"가있는 것 같습니다 !!!

동일한 코드에서 다음을 반환하므로 Chrome은 '사랑합니다'를 반환합니다.

"function test() { [native code] }"

"실제 프로그래밍 문제"와의 의심스러운 연결에 대한 질문이 종결되기 전에 @ Supr 's , @ Cory 's@ alpha123 ' s에 기반한 요약 된 솔루션을 추가한다고 생각했습니다 .

alert([[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+(
[]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+[([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(
!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[
])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[
])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[
])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11
+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<
1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1
)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>
1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]+([,][~1]+[]
)[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+
(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</
[1]+[])[1/1.1&1])

코드와 메시지의 복잡성을 감안할 때 JavaScript 엔진이 느끼는 것이 얼마나 특별하다고 말하는 것과 거의 같습니다. :)


First of all, I would like to thank Jason and all the contributors for playing with that funny snippet. I have written that piece of code just for fun in order to send it to my wife on February 14 :) Having only Chrome installed on the laptop I had no options to check how it works in Firefox and IE. Moreover, I haven't really expected that toString() representation of build-in methods might look differently in other browsers.

Now, moving to the real problem, let's precisely have a look at the code. Yes, "v" was the real "problem" here. I found no other ways of getting this letter except parsing [native code] string, which can be taken from any built-in method. Since I limited myself with having no strings and no numbers except 1 used, I needed to exploit some method that has only available characters in its name.

Available characters can be obtained from existing keywords and string representations, i.e. from the start we had NaN, null, undefined, Infinity, true, false, and "[object Object]". Some of them can be easily converted to strings, e.g. 1/!1+[] gives "Infinity".

I have analyzed different build-in methods for arrays [], objects {}, regular expressions /(?:)/, numbers 1.1, strings "1", and discovered one beautiful method of RegExp object called test(). Its name can be assembled from all available characters, e.g. "t" and "e" from true, and "s" from false. I have created a string "test" and addressed this method using square brackets notation for regex literal /-/, correctly identified in this line:

/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]

As was already discussed, this piece of code is evaluated in Chrome as:

function test() { [native code] }

in Firefox as:

function test() {
    [native code]
}

and in IE as:

 function test() {     [native code] }  

(in the latter pay special attention to the space before function keyword)

So, as you clearly see, my code was getting the 24th character from the presented string, which in Chrome was "v" (as was planned), but unfortunately in Firefox and IE -- "n" and "[" respectively.

In order to make the same output in all the browsers, I have used different approach than illustrated in the other answers. Now the modified version looks like that:

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+/\[[^1]+\]/[([]+![])[1<<1<<
1]+(/|/[(1+{})[1+11>>>1]+[[]+{}][+!1][1]+([]+1/[])[1<<1>>1]
+([1<1]+[])[1+11>>>1+1]+[[!!1]+1][+[]][1-1]+([]+!!/!/)[1|1]
+(/1/[1]+[])[!1%1]+(-{}+{})[-1+1e1-1]+(1+[!!1])[1]+([]+1+{}
)[1<<1]+[!!/!!/+[]][+[]][1&1]]+/=/)[1e1+(1<<1|1)+(([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[1^1]==+!1)]+(!![]+{})[1|1<<1]+[1+{}+1][!1+!1][(11>>1)+1
]](([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+
(!!1+[])[1^1]]))[1&.1][11>>>1]+([,][~1]+[])[1-~1]+[[]+{}][!
1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[]
,[]+{}][1<<1>>>1][1||1]+(/[<+>]/[1&1|1]+[1.1])[1/11.1&1.11]

However, in order to intrigue the readers I won't provide a solution for that. I honestly believe that you will easily understand how it works... and some can even surprise their beloved in cross-browser way ;)

P.S. Yet Another Obfuscator

Inspired by Jason's idea to create a universal obfuscating tool, I have written one more. You can find it at JSBin: http://jsbin.com/amecoq/2. It can obfuscate any text that contains numbers [0-9], small latin letters [a-z], and spaces. The string length is limited mostly with your RAM (at least the body of my answer was successfully obfuscated). The output is supported by Chrome, Firefox, and IE.

Hint: the tool uses different obfuscation approach than was presented above.


Why isn't the native code bit from the question being used? This one gives a 'v' in both Chrome and Firefox:

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]>([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]?([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]

Edit to support IE and do it without the ternary operator: This one works in Chrome, IE, and FF. Builds an array and uses == to determine browser.

[([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]

Readable:

[
    //ie
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],
    //ch
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],
    //ff
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]
]
[
    //ch?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+
    //ff?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)
]

This is about as close as I could get, unfortunately it violates the convention of the original obfuscation by making a call to unescape():

unescape((/%/+[])[1]+(/1/[1]+[])[1%1]+(+!1)+(+!1)+(1e1+(11*(1-~1)<<1)))

Teardown:

(/%/+[])[1]          => "%"
(/1/[1]+[])[1%1]     => "u"
(+!1)                => "0"
(+!1)                => "0"
(1e1+(11*(1-~1)<<1)) => "76"
===========================
unescape("%u0076")   => "v"

Other ideas:

  1. Somehow get to unescape("\x76")
  2. Somehow convert 118 without calling String.fromCharCode()
  3. Get the text from an exception with the word "Invalid" in it

Updates:

I started playing code golf and have been making it shorter, replacing parts with more 1s, etc.


Here's the part that generates the n/v:

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]

In Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) evaluates to

"function test() {
    [native code]
}"

while in Chrome it is

"function test() { [native code] }"

1^11<<1 equals 23. So due to Firefox's extra whitespace, this isn't quite enough to get to the 'v', and is instead 'n'.

And this is why you shouldn't rely on Function#toString behavior. ;)

EDIT: Finally I found a reasonably obfuscated cross-browser version:

[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]+([,][~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

This replaces the n/v section with:

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]

which exploits differences in parseInt (apparently Firefox parses numbers starting with 0 as octal, while Chrome doesn't) to add 4 in Firefox's case, thus getting 'v' from 'native' in both cases (I can't find another 'v' :P).
The parseInt looks a little out of place, but that's the best I can do for now.


For the general use-case, if character casing isn't a big concern, I might be inclined to cheat a little.

Create function "c" which turns a number 0 .. 25 into a character.

c=function(v){for(var i in window){for(var ci in i){if(parseInt(i[ci],(10+11+11)+(1<<1)+(1<<1))==(v+10)){return i[ci]}}}};

For performance reasons, pre-cache the letters, if you want.

l=[];for(var i=0; i<(11+11)+(1<<1)+(1<<1);i++){l[i]=c(i);}

In the Chrome console, the resulting array looks like this:

> l;
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "K", "l", "m", "n", "o", "p", "q", "r", "S", "t", "u", "v", "w", "x", "y", "Z"]

So ... your v might be l[10+10+1].

Alternatively, a general solution like this:

p=(function(){10%11}+[])[1+11+(1<<1)]; // "%"
u=(function(){club=1}+[])[1+11+(1<<1)]; // "u"
vc=p+u+(0+[])+(0+[])+((111>>1)+11+10+[]); // "%u0076"
unescape(vc);

Or, for this specific problem, maybe just:

(function(){v=1}+[])[10+(1<<1)]; // "v"

This gives a v in Chrome:

Object.getOwnPropertyNames(Object)[17][3];

And this does it in Firefox:

Object.getOwnPropertyNames(Object)[9][3]

They both pull it out of Object.prototype.preventExtensions(), so you could probably find a cross-browser way to reference that method. (It's the only 17-character name in Object.Prototype for starters.)

Feel free to build a more-obfuscated version of this and take all the credit for yourself, I'm out of time ;)


In chrome, the expression ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) evaluates to "function test() { [native code] }", the [1^11<<1] evaluates to 23 (bitwise operators cause the variable to be truncated to 32 bits)

참고URL : https://stackoverflow.com/questions/15978204/what-are-javascripts-builtin-strings

반응형