Question

This is a small piece of JavaScript code that alerts "Hello world":

゚ω゚ノ=/`m´)ノ~┻━┻//*´∇`*/['_'];o=(゚ー゚)=_=3;c=(゚Θ゚)=(゚ー゚)-(゚ー゚);(゚Д゚)=(゚Θ゚)=(o^_^o)/(o^_^o);(゚Д゚)={゚Θ゚:'_',゚ω゚ノ:((゚ω゚ノ==3)+'_')[゚Θ゚],゚ー゚ノ:(゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],゚Д゚ノ:((゚ー゚==3)+'_')[゚ー゚]};(゚Д゚)[゚Θ゚]=((゚ω゚ノ==3)+'_')[c^_^o];(゚Д゚)['c']=((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];(゚Д゚)['o']=((゚Д゚)+'_')[゚Θ゚];(゚o゚)=(゚Д゚)['c']+(゚Д゚)['o']+(゚ω゚ノ+'_')[゚Θ゚]+((゚ω゚ノ==3)+'_')[゚ー゚]+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[゚Θ゚]+((゚ー゚==3)+'_')[(゚ー゚)-(゚Θ゚)]+(゚Д゚)['c']+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+(゚Д゚)['o']+((゚ー゚==3)+'_')[゚Θ゚];(゚Д゚)['_']=(o^_^o)[゚o゚][゚o゚];(゚ε゚)=((゚ー゚==3)+'_')[゚Θ゚]+(゚Д゚).゚Д゚ノ+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[o^_^o-゚Θ゚]+((゚ー゚==3)+'_')[゚Θ゚]+(゚ω゚ノ+'_')[゚Θ゚];(゚ー゚)+=(゚Θ゚);(゚Д゚)[゚ε゚]='\\';(゚Д゚).゚Θ゚ノ=(゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ+'_')[c^_^o];(゚Д゚)[゚o゚]='\"';(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_');

A good looking version:

゚ω゚ノ = /`m´)ノ~┻━┻//*´∇`*/['_'];
o = (゚ー゚) = _ = 3;
c = (゚Θ゚) = (゚ー゚) - (゚ー゚);
(゚Д゚) = (゚Θ゚) = (o^_^o)/(o^_^o);
(゚Д゚) = {
  ゚Θ゚:  '_',
  ゚ω゚ノ: ((゚ω゚ノ==3)+'_')[゚Θ゚],
  ゚ー゚ノ: (゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],
  ゚Д゚ノ: ((゚ー゚==3)+'_')[゚ー゚]
};
(゚Д゚)[゚Θ゚] = ((゚ω゚ノ==3)+'_')[c^_^o];
(゚Д゚)['c'] = ((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];
(゚Д゚)['o'] = ((゚Д゚)+'_')[゚Θ゚];
(゚o゚)=(゚Д゚)['c'] + (゚Д゚)['o'] + (゚ω゚ノ + '_')[゚Θ゚] + ((゚ω゚ノ==3) + '_')[゚ー゚] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[゚Θ゚] + ((゚ー゚==3) + '_')[(゚ー゚) - (゚Θ゚)] + (゚Д゚)['c'] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + (゚Д゚)['o'] + ((゚ー゚==3) + '_')[゚Θ゚];
(゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚];
(゚ε゚) = ((゚ー゚==3) + '_')[゚Θ゚] + (゚Д゚).゚Д゚ノ + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[o^_^o-゚Θ゚] + ((゚ー゚==3) + '_')[゚Θ゚] + (゚ω゚ノ+'_')[゚Θ゚];
(゚ー゚) += (゚Θ゚);
(゚Д゚)[゚ε゚] = '\\';
(゚Д゚).゚Θ゚ノ = (゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];
(o゚ー゚o) = (゚ω゚ノ+'_')[c^_^o];
(゚Д゚)[゚o゚] = '\"';
(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_');

JSFiddle

It is taken from here: https://codegolf.stackexchange.com/questions/23975/obfuscation-challenge/24041#24041

How does it work? I don't even see the alert in that code.

Was it helpful?

Solution

Before looking closer at the code, you have to know that since JavaScript 1.5 identifiers are allowed to contain not just ASCII characters but also Unicode characters.

In this case many of these funny sequences are just identifiers. After exchanging these identifiers by simpler identifiers and removing unnecessary comments and parenthesis, the code looks as follows:

a = /`m´)ノ~┻━┻/['_'];
o = b = _ = 3;
c = d = b-b;
e = d = o^_^o/o^_^o;
e = {
  d: '_',
  a: ((a==3)+'_')[d],
  h: (a+'_')[o^_^o-d],
  i: ((b==3)+'_')[b]
};
e[d]   = ((a==3)+'_')[c^_^o];
e['c'] = (e+'_')[b+b-d];
e['o'] = (e+'_')[d];
f      = e['c']+e['o']+(a+'_')[d]+((a==3)+'_')[b]+(e+'_')[b+b]+((b==3)+'_')[d]+((b==3)+'_')[b-d]+e['c']+(e+'_')[b+b]+e['o']+((b==3)+'_')[d];
e['_'] = (o^_^o)[f][f];
g      = ((b==3)+'_')[d]+e.i+(e+'_')[b+b]+((b==3)+'_')[o^_^o-d]+((b==3)+'_')[d]+(a+'_')[d];
b      += d;
e[g]   = '\\';
e.j    = (e+b)[o^_^o-d];
obo    = (a+'_')[c^_^o];
e[f]   = '\"';
e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');

Now we’re able to evaluate each statement at a time:

  • a = /`m´)ノ~┻━┻/['_'] evaluates to a = undefined
  • o = b = _ = 3 assigns o, b, and _ the integer 3
  • c = d = b-b assigns c and d the integer 0
  • e = d = o^_^o/o^_^o assigns e and d the integer 1 (o^_^o evaluates to 3 XOR 3 XOR 3, which yields 3)
  • e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^o-d], i: ((b==3)+'_')[b] } assigns e the object { d: '_', a: 'a', h: 'd', i: 'e' }
  • e[d] = ((a==3)+'_')[c^_^o] assigns e[1] the string 'f'
  • e['c'] = (e+'_')[b+b-d] assigns e['c'] the string 'c'
  • e['o'] = (e+'_')[d] assigns e['o'] the string 'o'

This was all just the setup and the following variables are set:

a = undefined
b = 3
c = 0
d = 1
e = {
    1: "f",
    a: "a",
    c: "c",
    d: "_",
    h: "d",
    i: "e",
    o: "o"
}

The next statement is the first that constructs something:

f = e['c'] +             // => "c"
    e['o'] +             // => "o"
    (a+'_')[d] +         // => "undefined_"[1] = "n"
    ((a==3)+'_')[b] +    // => "false_"[3]     = "s"
    (e+'_')[b+b] +       // => "object_"[6]    = "t"
    ((b==3)+'_')[d] +    // => "true_"[1]      = "r"
    ((b==3)+'_')[b-d] +  // => "true_"[2]      = "s"
    e['c'] +             // => "c"
    (e+'_')[b+b] +       // => "object_"[6]    = "t"
    e['o'] +             // => "o"
    ((b==3)+'_')[d];     // => "true"[1]       = "r"

So f = "constructor". In the next statement this "constructor" is used to retrieve a function:

e['_'] = (o^_^o)[f][f]

This is equivalent to (3).constructor.constructor, which yields the function Function, so:

e['_'] = Function

This Function function is special as one can construct functions dynamically by passing it the function body code via parameter:

f = Function("alert(1)")
// equivalent to
f = function() { alert(1) }

I’ll skip the next few statements and just write the resulting variables and values:

a = undefined
b = 4
c = 0
d = 1
e = {
    1: "f",
    _: Function,
    a: "a",
    c: "c",
    constructor: "\"",
    d: "_",
    h: "d",
    i: "e",
    j: "b",
    o: "o",
    return: "\\"
}
f = "constructor"
obo = "u"

The last statement does the final work:

e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');

This is equivalent to:

Function(Function( … )(1))('_')

The long expression builds the following string:

return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"

The escaped string evaluates:

alert("Hello World")

This return code is passed to Function, which creates an anonymous function like:

function anonymous() {
    return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51";
}

Which, we know, is equivalent to:

function anonymous() {
    return"alert(\"Hello World\")";
}

This function is then executed with 1 as parameter, which returns the resulting string:

alert("Hello World")

This is then passed to Function again, which creates a new anonymous function:

function anonymous() {
    alert("Hello World");
}

Finally, this function is also invoked with '_' as parameter.

OTHER TIPS

There is a lot of stuff in here. Parentheses around variables are non-functional.

Basically he constructs this string:

return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"

Which is an escaped version of

return "alert(\"Hello World\")"

And finally does this:

Function(Function('return "alert(\\"Hello World\\")"')())()

The double Function seems like an arbitrary thing to do, but it's not. Function() interprets backslashes in the string as escape characters. So the first call decodes, and the second executes.

Function("return '\\110\\145\\154\\154\\157'")()
// => "Hello"

This is the same code, better formatted, and with "normal" variable names;

var1=/`m´)ノ~┻━┻//*´∇`*/['_'];
three=(threeThenFour)=_=3;
c=(one)=(threeThenFour)-(threeThenFour);
(anObject)=(one)=(three)/(three);
(anObject)={
  one:'_',
  var1:((var1==3)+'_')[one],
  var2ノ:(var1+'_')[three-(one)],
  var4ノ:((threeThenFour==3)+'_')[threeThenFour]
};
(anObject)[one]=((var1==3)+'_')[c ^ _ ^ three];
(anObject)['c']=((anObject)+'_')[(threeThenFour)+(threeThenFour)-(one)];
(anObject)['three']=((anObject)+'_')[one];
(theConstructor)=(anObject)['c']+
  (anObject)['three']+
  (var1+'_')[one]+
  ((var1==3)+'_')[threeThenFour]+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  ((threeThenFour==3)+'_')[one]+
  ((threeThenFour==3)+'_')[(threeThenFour)-(one)]+
  (anObject)['c']+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  (anObject)['three']+
  ((threeThenFour==3)+'_')[one];

// theConstructor => "constructor" 

(anObject)['_']=(three)[theConstructor][theConstructor];
(theReturn)=((threeThenFour==3)+'_')[one]+
  (anObject).var4ノ+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  ((threeThenFour==3)+'_')[three-one]+
  ((threeThenFour==3)+'_')[one]+
  (var1+'_')[one];

// theReturn => "return"

(threeThenFour)+=(one);
(anObject)[theReturn]='\\';
(anObject).var3ノ=(anObject+threeThenFour)[three-(one)];
(ovar2o)=(var1+'_')[c ^ _ ^ three];
(anObject)[theConstructor]='\"';

// (anObject)['_'] => Function

(anObject)['_'](
  (anObject)['_'](theReturn+
                 (anObject)[theConstructor]+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 (one)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+(
                   threeThenFour)+
                 ((threeThenFour)+(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 ((threeThenFour)+(one))+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (threeThenFour)+((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+(one)+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 ((threeThenFour)+(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (threeThenFour)+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)-(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (threeThenFour)+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 ((threeThenFour)+(one))+
                 (one)+
                 (anObject)[theConstructor]
                )
  (one)
)('_');

Let me explain the key steps:

The code creates an object named Д and then adds a property '_' that has a value of magic JavaScript Function constructor. In JavaScript, you can execute any string as code by passing it to Function constructor.

How does (゚Д゚)['_'] contain Function constructor? It's clever technique done by following line:

(゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚];

Here o and _ is set to 3. So o^_^o returns to 3. Obviously author could have just used o because o^_^o returns the same value but I guess he has good taste for obfuscation :). So the above expression now becomes (3)[゚o゚][゚o゚].

The value of ゚o゚ in square bracket is set to the string "constructor" that was built by concatenation in previous statement. It uses a very clever way to build the string "constructor" by plucking away individual characters from built-in JavaScript strings like "object", "true", "false" and "undefined" which are generated from JavaScript expressions converted to string. Apparently author couldn't find character "c" to pluck away from these built-in strings so he had to write that one explicitly. Note that the character in square bracket is ゚o゚ which is Unicode character, not the simple o used in round brackets although both looks very similar. When you do (3)("constructor") it returns the Number constructor function. The constructor of Number constructor is the Function constructor. So by doing (3)("constructor")("constructor") you get Function constructor which now you can finally pass an arbitrary string to execute it.

The last line builds the string "alert(\"Hello World\")" and passes it to the Function constructor to execute.

Question is how do we get that string "alert(\"Hello World\")" without typing actual alphabet? The clever technique is to use \xxx where xxx is octal number and translates to a character. To get this string the numbers you need are 0, 1, 2, 3, 4, 5, 6, 7 and 8. But you actually don't need all of these, instead you can produce them by simple arithmetic with three numbers 0, 1 and 4. So for example, to produce the character 'a' in "alert", you need ASCII decimal 97 or octal 141, i.e., \141. If you have only 0, 1 and 4 stored in some property of above object, you can concatenate them to produce 'a'. This way you can generate any string even if all that you have is 0, 1 and 4 stored in some properties of Д object. Clever? You bet!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top