酷壳上的一段js代码分析
2011-02-01 17:02
369 查看
From Cool Shell I saw"一段javascript代码", a confused code snipped, originates from here blackhat .
the author of Cool Shell had analyzed it. but the analysis is fairly rough, besides, it's incorrect at the last part of it, as what @Atry pointed out at the comment part of the article. here i'm gonna analyze it as well.
firstly, I substitute variable names in order to make them easy to read, as this:
outline its structure as this
but first thing first , let's look at the sequence of how the exp get evaluated. thanks for my colleage 陈超 to remind me this problem.
basically exp were evaluated from left to right by using a stack. so the sequence of evaluate this exp is approximately ① -> ② -> a=[①][②] ->()() -> [③]. etc(some are omitted). so be clear that ③ exp is evaluated only after the exp precede it evaluated, in this particular example, notice the variable a 's value.
①:
a is assigned as empty array; at this point, pay highly attention to the outermost a in exp
② : ② is really a complex exp
js integer is a 32bit int, tilde 0 convert all bit 0 to 1, the sign bit is 1, so js compiler would regard it as negative number and it value, as complementary code, we can know it's -1. so
Next piece of code in ② :
According to analysis above , we have:
so ② :
being at this phase. js compiler start to try to evaluate
in js,through what reference to call a method is very important to the result. the object that own the reference(as its property) become the this value in that function.so that js function invocation is really sending message between 2 objects(the object that own the reference and the function object). the function, as a method who provides the behavior, and the caller provides the identity meaning who perform the action.the result could vary from one to another calling objects. see below example
we call toString() binded to Object.prototype object by using 2 different ref, one is the original ref, the other is as the window's property, we get different output. it's all due to the
sort method return
part ③:
so the whole exp:
when i took a first glance at this code snipped and get to know it 's a alet(1), i really feel astonished. how can it done without the characters alert's emerging? but after this analysis, i found it's nothing special, but of course we shouldn't coding like this unless we purposely do some confusing work.
thought it's nothing weired. still i think there are several points that i should take as notes, which really broaden my horizon. before seeing this code, at least i never thought code can be written like this.
so finally summery the skills used in this example:
one skill used in this code snipped is to get string through implicit cast, in order to do this, we need to be very familiar to some characteristic of some certain operator and its operand, as well as some objects. we abstract some certain char in a string, then piece them up.
the other point with a generic meaning is how to get the window object in this sort of confused code.as long as we get the window, we can do whatever we want with the DOM api. unlike the way we get properties of some object, (we can piece them up using the associated-array-alike form, in which way we can do arithmetic on the string representing the property) we cant piece up characters to get the reference to window. in code above we get the window reference by invocation to a function, at this partically case, sort().
finally , we should pay highly attention to th sequence of evaluation to a exp.to know its correct order of evaluating is first thing first.
list points as below:
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+ ($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__ [_+~$]+$_[_]+$$](_/_)
the author of Cool Shell had analyzed it. but the analysis is fairly rough, besides, it's incorrect at the last part of it, as what @Atry pointed out at the comment part of the article. here i'm gonna analyze it as well.
firstly, I substitute variable names in order to make them easy to read, as this:
(a=[a=[]][(d=!a+a)[e=-~-~-~a]+({}+a)[e/e]+ (b=(c=!''+a)[e/e]+c[+a])])()[d[e/e]+d [e+~a]+c[e]+b](e/e)
outline its structure as this
(a=[①][②])()[③](), i found there are roughly 3 exp that are fairly complex.
but first thing first , let's look at the sequence of how the exp get evaluated. thanks for my colleage 陈超 to remind me this problem.
basically exp were evaluated from left to right by using a stack. so the sequence of evaluate this exp is approximately ① -> ② -> a=[①][②] ->()() -> [③]. etc(some are omitted). so be clear that ③ exp is evaluated only after the exp precede it evaluated, in this particular example, notice the variable a 's value.
①:
a=[]
a is assigned as empty array; at this point, pay highly attention to the outermost a in exp
(a=[a=[]][...]),this outermost
avalue can only be judged after evaluation of exp [a=[]][②], as far as the assignment of exp ①, a is [], notice the priority of exp
② : ② is really a complex exp
(d=!a + a): a is [], ! op needs a boolean object as operand, so it's boolean context, from !a we get false boolean object, notice any object implicitly convert to true in boolean context. for the 2nd a, the toString() method of a get called, what we get is a empty string, combined with + op make the preceded boolean object false convert to string , so the whole exp is a string "false".
e=-~-~-~a, ~a, ~'s operand need to be a number, so operand
ashould convert to a number value implicitly. An object's converting to number depends on valueOf() or toString(), what we get is a number or NaN. see example below
console.log(Number([])); //0 console.log(Number([1]);//1 console.log(Number([1,2]); //NaN console.log(parseInt([1,2])) //1 console.log(~[]); //-1
js integer is a 32bit int, tilde 0 convert all bit 0 to 1, the sign bit is 1, so js compiler would regard it as negative number and it value, as complementary code, we can know it's -1. so
~a ->-1, -~a -> 1, ~1 -> -2, ~2 -> -3, -(-3) -> 3;, so
(d=!a+a)[e=-~-~-~a] -> "false"[3] -> "s";
Next piece of code in ② :
({}+a)[e/e]:{} and a both in + exp both convert to string then do concatenation. so it's string "[object Object]". e is 3, so ("[object Object]")[1] is "o";
According to analysis above , we have:
b=(c=!''+ a)[e/e]+c[+a]: !'' -> boolean object true, ! operand needs to be boolean, boolean context; c=!''+a => "true", a is empty array, we get empty string, c is string "true"; +[] -> 0, Number context, we get 0, similar to +"",so that,
("true")[1] + "true"[0] -> "rt"
so ② :
[(d=!a+a)[e=-~-~-~a]+({}+a)[e/e]+ b=(c=!''+a)[e/e]+c[+a])]->
["s" + "o" + "rt"] ->["sort"]
being at this phase. js compiler start to try to evaluate
(a=[a=[]["sort"]), and then
(a=[a=[]["sort"])(). the sequence contains 2 steps here. first we assign the Array.prototype.sort method to
aas property of window. then call that method using
arather than a array object.
in js,through what reference to call a method is very important to the result. the object that own the reference(as its property) become the this value in that function.so that js function invocation is really sending message between 2 objects(the object that own the reference and the function object). the function, as a method who provides the behavior, and the caller provides the identity meaning who perform the action.the result could vary from one to another calling objects. see below example
var a = Object.prototype.toString; console.log(Object.prototype.toString()); // [object Object] console.log(a()); //[object Window]; a is a property of window. this in method refer to window
we call toString() binded to Object.prototype object by using 2 different ref, one is the original ref, the other is as the window's property, we get different output. it's all due to the
thisvalue!
sort method return
this, so when call it as a property of window, what get returned is window. notice that at this moment, variable
abecome the sort method rather than a empty array;
part ③:
d[e/e]+d[e+~a]+c[e]+b. according to analysis before ③ become:
["false"[1] + "false"[3-1] + "true"[3] + "rt" ](1), notice that,
~a, converting a function object to number, we get NaN, ~NaN happen to be same as ~0, we get -1;
so the whole exp:
(a=[a=[]]["sort"])()["alert"](1)->
window["alert"](1);
when i took a first glance at this code snipped and get to know it 's a alet(1), i really feel astonished. how can it done without the characters alert's emerging? but after this analysis, i found it's nothing special, but of course we shouldn't coding like this unless we purposely do some confusing work.
thought it's nothing weired. still i think there are several points that i should take as notes, which really broaden my horizon. before seeing this code, at least i never thought code can be written like this.
so finally summery the skills used in this example:
one skill used in this code snipped is to get string through implicit cast, in order to do this, we need to be very familiar to some characteristic of some certain operator and its operand, as well as some objects. we abstract some certain char in a string, then piece them up.
the other point with a generic meaning is how to get the window object in this sort of confused code.as long as we get the window, we can do whatever we want with the DOM api. unlike the way we get properties of some object, (we can piece them up using the associated-array-alike form, in which way we can do arithmetic on the string representing the property) we cant piece up characters to get the reference to window. in code above we get the window reference by invocation to a function, at this partically case, sort().
finally , we should pay highly attention to th sequence of evaluation to a exp.to know its correct order of evaluating is first thing first.
list points as below:
~a , +a: arithmetic op, number context , convert it to number:
!a , !'': logical op, boolean context; convert to boolean object
a = ![] + [];: object 's toString(), boolean object + "" get a string;
(a=[].sort)(): get window. to get window has a generic meaning in confuse code work.
相关文章推荐
- 一段js代码的分析
- 分析一段JS 动态织入代码
- 一段js代码的分析
- js中闭包来实现bind函数的一段代码的分析
- 一段和弹出窗口有关的JS代码
- 一段代码清晰性分析
- 写一段最短的代码,用上js所有关键字
- js代码分析
- 通过一段代码简单说js中的this的使用
- 通过一段代码简单说js中的this
- 通过一段代码简单说js中的this的使用
- 题型:编写一段JS代码提取URL中的各个GET参数,并按Key_Value的形式返回到一个对象中(如:Json结构)
- 一段checkbox全选或钱取消的js代码
- 多线程程序一段问题代码分析(生产者消费者)
- 一段要研究的JS代码
- 我用JS写的一段创建TABLE,添加行,模糊匹配,根据CHECKBOX删除内容,创建标题的代码(删除完再添加行有计数器的BUG)
- 使用JS编写一段面向对象的代码
- 传说中,技术大牛博客中的一段JS代码
- JS代码放在head和body中的区别分析
- 一段非常不错的控制文本框输入文字长度的JS代码