JavaScript奇技淫巧:Hook与反Hook
作者:专注于JS混淆加密的JShaman
API HOOK技术,在PC时代曾盛行,是高端的技术。在JavaScript编程中,也可以应用API Hook技术实现不寻常的效果。
例,eval hook:
<html>
<script>
//备份原window.eval函数
var _eval = window.eval;
//eval的hook函数
window.eval = function(src){
console.log("eval要执行的代码:",src);
return _eval(src);
}
eval("console.log('eval hook')");
</script>
</html>
运行效果
还有一种写法:Object.defineProperty(object, prop, descript);
此方法会在一个对象上定义一个新属性,或者修改一个对象的现有属性。
参数说明:
object:要添加或者修改属性的目标对象;
prop:要定义或修改属性的名称;
descript:属性描述符,常用get、set、value以获取、设置属性值或赋值。
上面的eval hook改成这种写法:
<html>
<script>
var _eval = window.eval;
Object.defineProperty(window, "eval", {
value:function(src){
console.log("eval要执行的代码:",src);
return _eval(src);
}
});
eval("console.log('eval hook')");
</script>
</html>
Hook有什么用途呢?
比如,可以用于实现cookie加密,代码如下:
<html>
<script>
(function() {
var document_cookie = document.cookie;
Object.defineProperty(document, "cookie", {
get: function() {
console.log("读取到cookie:", document_cookie);
var encode_value = document_cookie.split("").reverse().join("");
console.log("cookie值已解密", document_cookie, "变成", encode_value);
return encode_value;
},
set: function(value) {
console.log("写cookie,原始值:",value );
var encode_value = value.split("").reverse().join("");
console.log("cookie值已加密",value,"变成",encode_value);
document_cookie = value.split("").reverse().join("");
console.log("cookie已写入")
},
});
})();
document.cookie = "jshaman.com";
console.log("cookie加解密测试", document.cookie);
</script>
</html>
运行效果
那么,如何反Hook呢?
代码如下:
<html>
<script>
(function(){
console.log(eval.toString());
//备份原window.eval函数
var _eval = window.eval;
//eval的hook函数
window.eval = function(src){
console.log("eval要执行的代码:",src);
return _eval(src);
}
console.log(eval.toString());
if(eval.toString().indexOf("[native code]") != -1){
eval("console.log('eval hook');");
}else{
console.log("eval 被hook了,不执行正常代码")
}
})();
</script>
</html>
即:正常的eval函数,toString()后,会输出:
function eval() { [native code] }
但如果被Hook,Hook函数必然不是这样的,如本文示例,它会是:
function(src){ console.log("eval要执行的代码:",src); return _eval(src); }
那么当未检测到“[native code]”时,即表示被Hook了。
运行效果:
还有一种方法,代码如下:
<html>
<script>
(function(){
console.log(eval.toString());
//备份原window.eval函数
var _eval = window.eval;
//直接调用原始函数
_eval("console.log('eval hook');");
//eval的hook函数
window.eval = function(src){
console.log("eval要执行的代码:",src);
return _eval(src);
}
console.log(eval.toString());
})();
</script>
</html>
即:直接调用eval函数的备份函数,使hook函数无用武之地。
运行效果: