Recently I came across an interesting website that illustrates a Javascript Obfuscator: http://bl.ocks.org/jasonsperske/5400283
For example, (([]===[])+/-/)[1] gives a and (1+{})[(1<<1)+1] gives b.
I have tried hard to understand the evaluation sequence of these obfuscated result but was in vain.
Taking (1+{})[(1<<1)+1] as an example, I understand that << is the bitwise shift operator and will return 2, so the expression becomes (1+{})[3]. But then I cannot understand what does it mean by 1+{} and [3].
Google isn't really helpful to this problem as search engines don't like the brackets or slashes very much, so in case there are duplicate questions I'm sorry about that.
It's just obfuscation tricks.
for example :
[]===[] ===> false
and
([]===[])+/-/ ===> "false/-/" ( You could test it in the console by yourself)
So what is (([]===[])+/-/)[1] ? ( second char)
That's right :'a'
You may want to look at this also :
You could go step by step:
(([]===[]))
is simply false. Converted into a string "false/-/"and indexed by [1] gives you the a of the string "false".
The same goes for (1+{}) which results in the string "1[object Object]".
And 1<<1+1 is another way of writing 3 so this results in "1[object Object]"[3], which is simply b.
1+{}'s result is a string "1[object Object]", (1+{})[3] is to get the char of index 3 which is b.
The first example:
[]===[]
Comparing two different objects with ===, so the result is false, whose toString result is "false".
/-/ is a regex object, whose toString result is "/-/"
When you do false + /-/, which will concat using the result of .toString(), so the result will be "false/-/", and the second char is a.
Related
This code is equal to alert(1), but how does it work ? I don't see eval here.
/ㅤ/-[ㅤ=''],ᅠ=!ㅤ+ㅤ,ㅤㅤ=!ᅠ+ㅤ,ㅤᅠ=ㅤ+{},ᅠㅤ=ᅠ[ㅤ++],ᅠᅠ=ᅠ[ᅠㅤㅤ=ㅤ
],ᅠㅤᅠ=++ᅠㅤㅤ+ㅤ,ㅤㅤㅤ=ㅤᅠ[ᅠㅤㅤ+ᅠㅤᅠ],ᅠ[ㅤㅤㅤ+=ㅤᅠ[ㅤ]+(ᅠ.ㅤㅤ+ㅤᅠ)[ㅤ]+ㅤㅤ[ᅠㅤᅠ]+ᅠㅤ+ᅠᅠ+ᅠ
[ᅠㅤㅤ]+ㅤㅤㅤ+ᅠㅤ+ㅤᅠ[ㅤ]+ᅠᅠ][ㅤㅤㅤ](ㅤㅤ[ㅤ]+ㅤㅤ[ᅠㅤㅤ]+ᅠ[ᅠㅤᅠ]+ᅠᅠ+ᅠㅤ+"(ㅤ)")()
This is JSFuck, an esoteric programming language, that is actually valid JavaScript, so you don't need any special interpreter/compiler to run it.
The most popular one involves the use of just 6 characters ([]()!+), but yours is a bit different since it also uses /, =, ", ', ,, {, } and (blank).
It works by taking advantage of some nice features of JavaScript.
For instance, we know that [] is a truthy value, therefore ![] yields false.
With that same logic, we can get true by executing !![].
Numbers can be achieved too. We know that false is equal to 0, so the following expression makes sense: 0 + false == 0, right ? And it does. We know that false can be written as ![], and we know that we can omit the 0 on the left-side of the expression: +![] == 0.
Same can be said with true and 1: +!![]
The number 2 can be achieved by adding up two 1s: (+!![])+(+!![]), and so on.
With logic like these you can do pretty much anything.
For instance, a popular way to get the letter "a" is by producing a NaN result, converting it to string ("NaN"), and then getting the letter at index 1, which is "a".
Ok so.. We know we can get "alert(1)", but how do we execute this?
We can't use eval, because that will require to use characters not allowed on JSFuck.
Well, the way most people do it is like this:
Identify a well-known function of Array.prototype, let's say indexOf
Obtain its constructor instance
Pass in stringified code to this constructor
Execute the result
So, as a summary:
// You can try this on your browser!
[]["indexOf"]["constructor"]("alert(1)")()
We know that we can generate alphabetic characters on JSFuck, and we also know we can generate numbers, so that line of code up there is actually very possible.
I came across some eval code:
eval('[+!+[]+!+[]+!+[]+!+[]+!+[]]');
This code equals the integer 5.
What is this type of thing called? I've tried searching the web but I can't seem to figure out what this is referred to. I find this very interesting and would like to know where/how one learns how to print different things instead of just the integer 5. Letters, symbols and etc. Since I can't pin point a pattern in that code I've had 0 success taking from and adding to it to make different results.
Is this some type of obfuscation?
This type of obfuscation, eval() aside, is known as Non-alphanumeric obfuscation.
To be completely Non-alphanumeric, the eval would have to be performed by Array constructor prototypes functions and subscript notation:
[]["sort"]["constructor"]("string to be evaled");
These strings are then converted to non-alphanumeric form.
AFAIK, it was first proposed by Yosuke Hosogawa around 2009.
If you want to see it in action see this tool: http://www.jsfuck.com/
It is not considered a good type of obfuscation because it is easy to reverse back to the original source code, without even having to run the code (statically). Plus, it increases the file size tremendously.
But its an interesting form of obfuscation that explores JavaScript type coercion. To learn more about it I recommend this presentation, slide 33:
http://www.slideshare.net/auditmark/owasp-eu-tour-2013-lisbon-pedro-fortuna-protecting-java-script-source-code-using-obfuscation
That's called Non-alphanumeric JavaScript and it's possible because of JavaScript type coercion capabilities. There are actually some ways to call eval/Function without having to use alpha characters:
[]["filter"]["constructor"]('[+!+[]+!+[]+!+[]+!+[]+!+[]]')()
After you replace strings "filter" and "constructor" by non-alphanumeric representations you have your full non-alphanumeric JavaScript.
If you want to play around with this, there is a site where you can do it: http://www.jsfuck.com/.
Check this https://github.com/aemkei/jsfuck/blob/master/jsfuck.js for more examples like the following:
'a': '(false+"")[1]',
'b': '(Function("return{}")()+"")[2]',
'c': '([]["filter"]+"")[3]',
...
To get the value as 5, the expression should have been like this
+[!+[] + !+[] + !+[] + !+[] + !+[]]
Let us analyze the common elements first. !+[].
An empty array literal in JavaScript is considered as Falsy.
+ operator applied to an array literal, will try convert it to a number and since it is empty, JavaScript will evaluate it to 0.
! operator converts 0 to true.
So,
console.log(!+[]);
would print true. Now, the expression can be reduced like this
+[true + true + true + true + true]
Since true is treated as 1 in arithmetic expressions, the actual expression becomes
+[ 5 ]
The + operator tries to convert the array ([ 5 ]) to a number and which results in 5. That is why you are getting 5.
I don't know of any term used to describe this type of code, aside from "abusing eval()".
I find this very interesting and would like to know where/how one
learns how to print different things instead of just the integer 5.
Letters, symbols and etc. Since I can't pin point a pattern in that
code I've had 0 success taking from and adding to it to make different
results.
This part I can at least partially answer. The eval() you pasted relies heavily on Javascript's strange type coercion rules. There are a lot of pages on the web describing various strange consequences of the coercion rules, which you can easily search for. But I can't find any reference on type coercion with the specific goal of getting "surprising" output from things like eval(), unless you count this video by Destroy All Software (the Javascript part starts at 1:20). Most of them understandably focus on how to avoid strange bugs in your code. For your purpose, I believe the most useful things I know of are:
The ! operator will convert anything to a boolean.
The unary + operator will convert anything to a number.
The binary + operator will coerce its arguments to either numbers or strings before adding or concatenating them. Normally it will only go with strings if one or the other argument is already a string, but there are exceptions.
The bitwise operators output integers, regardless of input.
Converting to numbers is complicated. Booleans will go to 0 or 1. Strings will attempt to use parseInt(), or produce NaN if that fails. I forget the rest.
Converting an object to a string or number will invoke its "toString" or "toValue" method respectively, if one exists.
You get the idea. thefourtheye's answer walks through exactly how these rules apply to the example you gave. I'm not even going to try summarizing what happens when Dates, Functions, and Regexps are involved.
Is this some type of obfuscation?
Normally you'd simply get obfuscation for free as part of minification, so I have no idea why someone would write that in real production code (assuming that's where you found it).
This question already has answers here:
Why does ++[[]][+[]]+[+[]] return the string "10"?
(10 answers)
Closed 6 years ago.
I have recently seen an expression from a source, which looks something like below -
++[[]][+[]]+[+[]]
Entering this into the Chrome (Windows 7, Version 27.0.1453.94 m) console shows a result of "10".
Can someone explain what's happening here?
JSFiddle.
JavaScript is fairly flexible about converting between data types. The first thing to notice is that +[] evaluates to 0.* That lets us rewrite the expression as:
++[[]][0] + [0]
The next thing to notice is that ++[[]][0] is the preincrement operator applied to the first element of [[]]. Normally you can't apply ++ to an array, but JavaScript kindly converts the first element to 0, so the result is that ++[[]][0] evaluates to 1 (the first element of [[]] having now been incremented). It is kind of like this:
var a = [[]];
var b = ++a[0];
// now a will be [1] and b will be 1
That leaves us with:
1 + [0]
JavaScript now converts the int and the array to strings (since [0] is not a numeric value) and concatenates them together. Done!
* My understanding of how +[] becomes 0 is that it is a two-step process: first, [] is converted to a string primitive, which is the empty string. The empty string then converts to a number, which is zero. Via the same route, [1] evaluates to '1' and then to 1, [2] evaluates to 2, etc. However, [1, 2] evaluates to '1,2' which evaluates to NaN. (The last because the decimal point separator is ., not ,. I don't know what would happen if my locale were different.)
This expression stringifies valid Javascript constructs that yelds NaN, numbers, boolean undefined etc.
e.g.
+[] -> 0 //The unary plus operator is applied to the result of toString applied to an empty array (which is an empty string)
!+[] -> true
You can have a look also at this question,
and at the no alnum cheat sheets.
+[] is a number conversion from array to number which is 0.
and +[0] is also 0.
So the final result can be deduced to (++0) + [0] which is 1+[0].
And for a number adding an array. They are converted to string so the result is actually '10'.
You can log typeof(++[[]][+[]]+[+[]]) to verify.
What is the difference between parseInt(string) and Number(string) in JavaScript has been asked previously.
But the answers basically focused on the radix and the ability of parseInt to take a string like "123htg" and turn it into 123.
What I am asking here is if there is any big difference between the returns of Number(...) and parseFloat(...) when you pass it an actual number string with no radix at all.
The internal workings are not that different, as #James Allardic already answered. There is a difference though. Using parseFloat, a (trimmed) string starting with one or more numeric characters followed by alphanumeric characters can convert to a Number, with Number that will not succeed. As in:
parseFloat('3.23abc'); //=> 3.23
Number('3.23abc'); //=> NaN
In both conversions, the input string is trimmed, by the way:
parseFloat(' 3.23abc '); //=> 3.23
Number(' 3.23 '); //=> 3.23
No. Both will result in the internal ToNumber(string) function being called.
From ES5 section 15.7.1 (The Number Constructor Called as a Function):
When Number is called as a function rather than as a constructor, it performs a type conversion...
Returns a Number value (not a Number object) computed by ToNumber(value) if value was supplied, else returns +0.
From ES5 section 15.1.2.3 (parseFloat (string)):
...
If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral (see 9.3.1)
...
And 9.3.1 is the section titled "ToNumber Applied to the String Type", which is what the first quote is referring to when it says ToNumber(value).
Update (see comments)
By calling the Number constructor with the new operator, you will get an instance of the Number object, rather than a numeric literal. For example:
typeof new Number(10); //object
typeof Number(10); //number
This is defined in section 15.7.2 (The Number Constructor):
When Number is called as part of a new expression it is a constructor: it initialises the newly created object.
Not a whole lot of difference, as long as you're sure there's nothing but digits in your string. If there are, Number will return NaN. Another problem that you might get using the Number constructor is that co-workers might think you forgot the new keyword, and add it later on, causing strict comparisons to fail new Number(123) === 123 --> false whereas Number(123) === 123 --> true.
In general, I prefer to leave the Number constructor for what it is, and just use the shortest syntax there is to cast to an int/float: +numString, or use parse*.
When not using new to create a wrapper object for a numerical value, Number is relegated to simply doing type conversion from string to number.
'parseFloat' on the other hand, as you mentioned, can parse a floating point number from any string that starts with a digit, a decimal, or +/-
So, if you're only working with strings that contain only numerical values, Number(x) and parseFloat(x) will result in the same values
Please excuse me posting yet another answer, but I just got here via a Google search and did not find all of the details that I wanted. Running the following code in Node.js:
var vals = ["1", "1.1", "0", "1.1abc", "", " ", null];
for(var i = 0; i < vals.length; i++){
var ifTest = false;
if(vals[i])
{
ifTest = true;
}
console.log("val=" + vals[i] + ", Number()=" + Number(vals[i])+ ", parseFloat()=" + parseFloat(vals[i]) + ", if()=" + ifTest);
}
gives the following output:
val=1, Number()=1, parseFloat()=1, if()=true
val=1.1, Number()=1.1, parseFloat()=1.1, if()=true
val=0, Number()=0, parseFloat()=0, if()=true
val=1.1abc, Number()=NaN, parseFloat()=1.1, if()=true
val=, Number()=0, parseFloat()=NaN, if()=false
val= , Number()=0, parseFloat()=NaN, if()=true
val=null, Number()=0, parseFloat()=NaN, if()=false
Some noteworthy takeaways:
If protecting with an if(val) before trying to convert to number, then parseFloat() will return a number except in the whitespace case.
Number returns a number in all cases except for non-numeric characters aside from white-space.
Please feel free to add any test cases that I may be missing.
This code outputs D. The question is HOW?
alert([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[+!+[]]](+[]+[+[]])[+!+[]]);
I understand that ![] is evaluated to false or 0 and so on, but how does it execute? And how can I convert this to something humans can understand and not only Jon Skeet?
Can someone break some piece of this code and explain me what's happening?
Well, evaluating the expression in parts, at the end it is equivalent to:
[]['sort']['call']()["btoa"]("00")[1]; // "D"
Which can be simplified to :
btoa("00")[1]; // "D"
How you can "decode it"?
Simply examine the operators used, for example, we can see at first that an array literal is used, then several bracket notation property accesses are done, and a couple of invocations.
How does it work?
The trick is to chain multiple type conversions, for example, to get the f letter:
(![]+[])[+[]]
If we examine the first part, in parentheses, ![]+[], we see a boolean negation, which will return false because an array object is always truthy, and then a concatenation.
That produces the string "false", then, the second part, we see a brackets applied to that string, to access a character, and the expression +[], which results in 0.
+[] gives zero because the Array's toString method returns an empty string, for an empty array like that one, and an empty string produces to zero when it is converted to number (the unary + operator in this example).
There are just tricks like that, things that produce a string, such "true", "false", "null", "undefined", etc... and more tricks to get the numerically.
For example to get a number -to access a character-, they use again cryptic type conversion:
+[]; // 0, equivalent to +""
+!+[]; // 1, equivalent to +true
!+[]+!+[]; // 2, equivalent to +true+true
!+[]+!+[]+!+[]; // 3, equivalent to +true+true+true
It does some tricks with the javascript type conversions. As CMS pointed out, it's equivalent to: []['sort']['call']()["btoa"]("00")[1];
They build the strings by pulling them out of things like false, etc.
For example, to get the s in "sort":
Get a "false": (![]+[]) -- ![] returns false and +[] converts it to a string.
Get the value 3 with: !+[]+!+[]+!+[] - each !+[] returns true, but when you add booleans you get an integer representation. e.g. true + true = 2
Get the s with string index access notation ("false"[3] = 's'): (![]+[]) [!+[]+!+[]+!+[]]
And now you have an s. They keep doing that until they have enough to access whichever method or property they want.
![] is false. ![] + [] evaluates to 'false'. +[] is 0 so !+[] is true, etc. javascript is very strange with its implied type conversions