这篇文章来对evercookie的js源码进行分解下,
因为源码太长,这里发2个个人觉得最有意思的方法出来,顺便做了点小解释
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
BwStore.evercookie_history = function(name, value)
{ // - is special
var baseStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-";
var baseElems = baseStr.split("");
// sorry google.
if (typeof(value) != "undefined")
{
// don't reset this if we already have it set once
// too much data and you can't clear previous values
if (this.hasVisited(url))
return;
this.createIframe(url, 'if');
url = url + '/';
var base = this.encode(value).split("");
for (var i = 0; i < base.length; i++)
{
url = url + base[i];
this.createIframe(url, 'if' + i);
}
// - signifies the end of our data
url = url + '-';
this.createIframe(url, 'if_');
}
else
{
// omg you got csspwn3d
if (this.hasVisited(url))
{
url = url + '/';
var letter = "";
var val = "";
var found = 1;
while (letter != '-' && found == 1)
{
found = 0;
for (var i = 0; i < baseElems.length; i++)
{
if (this.hasVisited(url + baseElems[i]))
{
letter = baseElems[i];
if (letter != '-')
val = val + letter;
url = url + letter;
found = 1;
break;
}
}
}
// lolz
return this.decode(val);
}
}
} |
这个方法算是evercookie最经典的一个方法了
大家都知道,用户访问过一次页面,就会存储在浏览器浏览历史里面,这个方法就是利用浏览器的这个特性。通过新建一个iframe去访问这个页面。
如默认的url是http://www.google.com/evercookie/cache/
那他发送的路径会是加上了name跟value的。这里的name跟value分别是id跟onedear,如
http://www.google.com/evercookie/cache/id/onedear
发送方法为每个字母递增发送,并在最后加个”-“的结束符号
http://www.google.com/evercookie/cache/i
http://www.google.com/evercookie/cache/id
。。。。
http://www.google.com/evercookie/cache/id/onedea
http://www.google.com/evercookie/cache/id/onedear
http://www.google.com/evercookie/cache/id/onedear-
那要相应的name value他是这样获取的。
默认url加上”ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-“。其中一个字符,看看是否存在历史记录里面。不存在则循环查找下一个。如果这里查到i是访问过的。http://www.google.com/evercookie/cache/i ,则继续循环,在i的后面循环检查。继而又查到d是访问过的。http://www.google.com/evercookie/cache/id,一直循环知道出现’-‘符号为止。继而解析获取到的字符串,那name value自然也就解析出来。
但这样做的弊端很大。首先,必须要连续发送n个url,用户体验不好。获取的时候要遍历,也影响了浏览器的性能。
所以不推荐。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
BwStore.evercookie_png = function(name, value)
{ //alert(document.createElement('canvas').getContext);
if (document.createElement('canvas').getContext)
{
if (typeof(value) != "undefined")
{
// make sure we have evercookie session defined first
document.cookie = 'evercookie_png=' + value;
// evercookie_png.php handles the hard part of generating the image
// based off of the http cookie and returning it cached
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_png.php?name=' + name;
}
else
{
_ec.pngData = undefined;
var context = document.createElement('canvas');
context.style.visibility = 'hidden';
context.style.position = 'absolute';
context.width = 200;
context.height = 1;
var ctx = context.getContext('2d');
// interestingly enough, we want to erase our evercookie
// http cookie so the php will force a cached response
var origvalue = this.getFromStr('evercookie_png', document.cookie);
document.cookie = 'evercookie_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_png.php?name=' + name;
img.onload = function()
{
// put our cookie back
document.cookie = 'evercookie_png=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
_ec.pngData = '';
ctx.drawImage(img,0,0);
// get CanvasPixelArray from given coordinates and dimensions
var imgd = ctx.getImageData(0, 0, 200, 1);
var pix = imgd.data;
// loop over each pixel to get the "RGB" values (ignore alpha)
for (var i = 0, n = pix.length; i < n; i += 4)
{
if (pix[i ] == 0) break;
_ec.pngData += String.fromCharCode(pix[i]);
if (pix[i+1] == 0) break;
_ec.pngData += String.fromCharCode(pix[i+1]);
if (pix[i+2] == 0) break;
_ec.pngData += String.fromCharCode(pix[i+2]);
}
}
return _ec.pngData;
}
}
} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$x = 200;
$y = 1;
$gd = imagecreatetruecolor($x, $y);
$data_arr = str_split($_COOKIE["evercookie_png"]);
$x = 0;
$y = 0;
for ($i = 0; $i < count($data_arr); $i += 3)
{ $color = imagecolorallocate($gd, ord($data_arr[$i]), ord($data_arr[$i+1]), ord($data_arr[$i+2]));
imagesetpixel($gd, $x++, $y, $color);
} Ever_cookie_png.php |
服务器创建一个宽100像素高1像素的黑色空白PNG(每个像素的RGB 颜色可存储3个字节,可存储600字节信息),然后将值拆分并按顺序每3个字母生成一个RGB颜色值并且按顺序设置到图片的像素点中,读取的时候取出并且解析还原出来。还原需要用到'canvas'标签,要求浏览器必须支持html5才能用上此方法。ie8,ie9,ff,chrome,safari都是ok的