最近在看一个域名被路由劫持的一段JAVASCRIPT代码,有一段实现了数据的解密工作,代码如下,请教大牛解密各个过程的实现原理,该加密算法是何种加密算法?
de = function (n) {
// K貌似是校验字符串,共26个字符
var l = 1,
k = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var c = n.charAt(0) * l;
if (isNaN(c)) return '';
c = n.substr(l, c) * l;
if (isNaN(c)) return '';
var d = n.length,
t = [],
a, f, b, x = String(c).length + l,
m = function (z) {
return k.indexOf(n.charAt(z))
},
i = k.length; // 26
if (d != x + c) return '';
while (x < d) {
a = m(x++);
if (a < 5)
f = a * i + m(x);
else
f = (a - 5) * i * i + m(x) * i + m(x += l);
t[t.length] = String.fromCharCode(f);
x++;
}
return t.join('');
};
// 解密过程
console.log(de("3406ETBIEMEGBICGBIEMEGCJCFBWCBCECFCDBYBYDREADTEHDREIDZBIBSBIENEIBICGBIEKELEODRDUEICJBWBMDUDTEKCJBMEKELEODRELEIEMCJBZBMEBDXCJENEMDYBTCEBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEKELEODRELENDZCACJDNCBBWBSBZBWBWDPBMEKELEODRELENDZBXCJDNEKELEODRELENDZBZBTBXDPBMEKELEODRELENDZBYCJBWBMEBEGEIENEMDGCJDNCBBSBYCBDPBIBSBIENEABICGBIEKELEODRDUEICJBWBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEBDXCJENEMDYBTCEBMEBEGEIENEMDGCJDNCBBSBYCBDPBIEV"));
代码编写有误,已经更新,不好意思。
首先这个代码运行不了啊
另外这种加解密没任何意义 无论什么牛B得算法 执行的结果一定是一段正规的js代码 最多是做了变量混淆 改了某些函数的名字而已
de = function(n) {
var l = 1, k = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var c = n.charAt(0) * l;//取字符串中的 第一个字符 3
if (isNaN(c)) return '';
c = n.substr(l, c) * l;//取字符串中 1 到 3 的内容 406
if (isNaN(c)) return '';
var d = n.length,//字符串长度
t = [],
a, f, b,
x = String(c).length + l, //x = 3 + 1 = 4
m = function(z) {
return k.indexOf(n.charAt(z));//获取字符 n 中指定的字符,在 字符串k中的位置
},
i = k.length; // 26
if (d != x + c) return ''; //检测 前四个字节所标记的 长度是否正确 d 字符串的长度, x + c == 4 + 406 = 410
while (x < d) {//遍历后面的字符
console.log('当前字符:', n.charAt(x), '在k中的位置:', m(x));
a = m(x++);//得到当前字符在 字符串k 中的位置
if (a < 5){//如果位置小于5
f = a * i + m(x);// (当前的位置 * 26) + 下一个字符在字符k中的位置
}else{//如果是大于等于5的
f = (a - 5) * i * i + m(x) * i + m(x += l);
//(位置减5)*26*26 + 下一个字符在k中的位置*26 + 下下一个字符在k中的位置
}
t[t.length] = String.fromCharCode(f);//将ASCII码转换为对应的字符, 保存到数组 t 里面
x++
}
return t.join('')
}
// 解密过程
console.log(de("3406ETBIEMEGBICGBIEMEGCJCFBWCBCECFCDBYBYDREADTEHDREIDZBIBSBIENEIBICGBIEKELEODRDUEICJBWBMDUDTEKCJBMEKELEODRELEIEMCJBZBMEBDXCJENEMDYBTCEBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEKELEODRELENDZCACJDNCBBWBSBZBWBWDPBMEKELEODRELENDZBXCJDNEKELEODRELENDZBZBTBXDPBMEKELEODRELENDZBYCJBWBMEBEGEIENEMDGCJDNCBBSBYCBDPBIBSBIENEABICGBIEKELEODRDUEICJBWBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEBDXCJENEMDYBTCEBMEBEGEIENEMDGCJDNCBBSBYCBDPBIEV"));
运行结果:
当前字符: E 在k中的位置: 4
当前字符: B 在k中的位置: 1
当前字符: E 在k中的位置: 4
当前字符: E 在k中的位置: 4
当前字符: B 在k中的位置: 1
当前字符: C 在k中的位置: 2
当前字符: B 在k中的位置: 1
当前字符: E 在k中的位置: 4
当前字符: E 在k中的位置: 4
....中间太多省略掉........
当前字符: C 在k中的位置: 2
当前字符: D 在k中的位置: 3
当前字符: B 在k中的位置: 1
当前字符: E 在k中的位置: 4
{"tn":"tn=90589722_hao_pg","up":"rsv_bp=0&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=[4,30]&rsv_sug4=[50,300]&rsv_sug1=[rsv_sug3-1]&rsv_sug2=0&inputT=[5,25]","uh":"rsv_bp=0&rsv_sug3=[4,30]&ie=utf-8&inputT=[5,25]"}
下面为加密算法(暂未处理ASCII码大于等于130的数据):
var data = "3406ETBIEMEGBICGBIEMEGCJCFBWCBCECFCDBYBYDREADTEHDREIDZBIBSBIENEIBICGBIEKELEODRDUEICJBWBMDUDTEKCJBMEKELEODRELEIEMCJBZBMEBDXCJENEMDYBTCEBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEKELEODRELENDZCACJDNCBBWBSBZBWBWDPBMEKELEODRELENDZBXCJDNEKELEODRELENDZBZBTBXDPBMEKELEODRELENDZBYCJBWBMEBEGEIENEMDGCJDNCBBSBYCBDPBIBSBIENEABICGBIEKELEODRDUEICJBWBMEKELEODRELENDZBZCJDNCABSBZBWDPBMEBDXCJENEMDYBTCEBMEBEGEIENEMDGCJDNCBBSBYCBDPBIEV";//楼主提供的数据
var r = '{"tn":"tn=90589722_hao_pg","up":"rsv_bp=0&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=[4,30]&rsv_sug4=[50,300]&rsv_sug1=[rsv_sug3-1]&rsv_sug2=0&inputT=[5,25]","uh":"rsv_bp=0&rsv_sug3=[4,30]&ie=utf-8&inputT=[5,25]"}';//用解密算法还原出来的数据
en = function(v){//加密算法
var k = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var ret = [], a, b, c, d;
for(var i=0,j=v.length; i<j; i++){
a = v.charCodeAt(i);//取当前字符的ASCII码
b = Math.floor(a / k.length);//得到商
c = a % k.length;//取余
if(b < 5){
ret.push(k[b]);//将商对应的那个字符保存起来
ret.push(k[c]);//将余数对应的那个字符保存起来
//这样, 这两个合在一起就可以还原当前的字符了
}else{
//暂不实现 ^_^
}
}
d = ret.length + '';//计算数据的长度
return d.length + d + ret.join('');//表示长度的长度 + 数据长度 + 数据
}
console.log(en(r) === data);//对数据进行加密 并比较结果是否与 楼主提供的数据相同
更新一下加密算法(完整版):
en = function(v){
var k = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var ret = [], a, b, c, d, e, f;
for(var i=0,j=v.length; i<j; i++){
a = v.charCodeAt(i);//取当前字符的ASCII码
b = parseInt(a / k.length);//得到商
c = a % k.length;//取余
if(a > 14195){
throw new Error('该字符编码不了!!!');
}
if(b < 5){
ret.push(k[b]);//将商对应的那个字符保存起来
ret.push(k[c]);//将余数对应的那个字符保存起来
//这样, 这两个合在一起就可以还原当前的字符了
}else{
d = parseInt(b / k.length);
ret.push(k[d + 5]);
ret.push(k[b % k.length]);
ret.push(k[c]);
}
}
d = ret.length + '';//计算数据的长度
return d.length + d + ret.join('');//表示长度的长度 + 数据长度 + 数据
}
不过根据它解密算法中的代码, 发现该算法在进行加密的时候,对字符的支持有一些小问题(如果没有中文的话, 该加/解密算法没有问题).
根据解密算法可知, 该算法中对字符进行编码时, 最大只支持使用 三位
编码后的内容来表示原字符,
而所使用的三位
字符所能承受的最大值为 ZZZ
. 即该算法在进行加密的时候不支持超过 14195
这个数值的字符.
下面为测试代码:
var data, mm, nn;
for(var i=0x0; i<0xffff; i++){
data = String.fromCharCode(i);
mm = en(data);//加密
nn = de(mm);//解密
console.log(i, mm, nn, nn === data);
if(nn !== data){//加密 与 解密的结果不同时, 退出
break;
}
}