# VMP 介绍
"索引j", j,"索引O", O, " 值:", JSON.stringify(S, function(key, value) {if (value == window) {return undefined} return value}) |
# jsvmp
# 签名分析
签名参数:
_02B4Z6wo00101loNtfAAAIDDhHvtVmvJQOZaCbFAAPQYwzYkMBmMy0OIRqJQNqhou0eH.DJLTigPioA7TAwBj3B7N1HhHxmv5dJlR1wA5ViS1rIJXRF.2jx88ty4qN9zJEh5kPLfJLRpsdxx14
根据插桩日志,可以将上述分为 8 部分
sign1:loNtf
sign2:AAAID
sign3:DhHvtV
sign4:mvJQO
sign5:ZaCbF
sign6:AAPQY
sign7: wzYk
sign8: MBmMy0OIRqJQNqhou0eH.DJLTigPioA7TAwBj3B7N1HhHxmv5dJlR1wA5ViS1rIJXRF.2jx88ty4qN9zJEh5kPLfJLRpsdxx
最后在对整体的拼接计算一个尾缀
# 字符索引修改
function move_char_calc(num){ | |
if(0 <= num && num < 26){ | |
return num + 65 | |
}else if(26 <= num && num < 52){ | |
return num + 71 | |
}else if(num == 62 || num == 63){ | |
return num - 17 | |
}else{ | |
return num - 4 | |
} | |
} |
根据插桩日志的分析,发现在每一个签名计算的过程中,在最后都会进行一个计算,这个值主要是用于修改字符的索引,将不存在的剔除出去
# 魔改 sdbm
function sdbmhash(strurl, hash) { | |
for(let i=0; i<32; i++){ | |
hash = ((hash * 65599) >>> 0) + strurl.charCodeAt(hash % strurl.length); | |
} | |
return hash; | |
}; | |
function sdbmhash2(strurl, hash) { | |
for(let i=0; i<strurl.length; i++){ | |
hash = (hash ^ strurl.charCodeAt(i)) * 65599 >>> 0; | |
} | |
return hash; | |
}; | |
function sdbmhash3(strurl, hash) { | |
for(let i=0; i<strurl.length; i++){ | |
hash = (hash * 65599 + strurl.charCodeAt(i)) >>> 0; | |
} | |
return hash; | |
}; |
这里包含了三种 sdbm 算法的魔改,主要用于计算不同的 hash 值用于后续计算
# sign1
this.offset1 = [24, 18, 12, 6, 0]; | |
get_signature1(){ | |
let now_str = ''; | |
for(let index in this.offset1){ | |
let charnum = this.nownumble >> 2 >> this.offset1[index] & 63; | |
now_str += String.fromCharCode(move_char_calc(charnum)); | |
} | |
console.log('sign1:'+now_str); | |
return now_str; | |
}; |
这里的 this.nownumble 是由长数字计算出来,长数字是由浏览器 reference, 时间戳,canves 指纹计算得到
其他 sign 大同小异
# sign4
sign4,sign5,sign6 都还使用了别的参数进行计算.
sign4 的参数包含 url 修改后的参数拼接计算以及浏览器 user-agent 的 sdbm 计算
# sign8
sign8 的计算主要涉及到一个 18 数组的初始化,以及八次变化,同时包含了 cookie 中的 sec_id (AES 加密)