1 异常在识别中的使用
爬虫在抓取浏览器数据时,常会用到代码js代码执行的工具。为了识别,会利用函数栈来进行判断。
如下是一个简单的例子来描述问题。如果是在代码执行器中执行就可以暴露出执行器方法名及行列等信息。因此将这些信息上报给后台,与实际信息进行比较,分析判断即可识别出是否是爬虫。
(function(){
try{
throw new Error("test");
}catch(err) {
console.log(err.stack);
}
})();
VM754:5 Error: test
at <anonymous>:3:11
at <anonymous>:7:3
2 一些常见反异常识别
根据这个识别方式,如果依然通过代码执行器抓取。显然会考虑改变这些信息。常用的方式如下:
- 函数拦截:在字符串检测识别绕过这篇中介绍了常见的拦截函数修改返回结果的形式。
- 重定义异常:此外我们将异常信息进行简单改变,根据重定义异常的方式[1]来阻碍识别方判断。
Object.defineProperty(Error,"stackTraceLimit",{
set:function(value) {
let obj = Error;
return (function(){
throw new UserError("异常信息");
})();
}
});
function UserError(message) {
this.message = message || '默认信息';
this.name = 'UserError';
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
UserError.prototype.stack = `VM696:1 Uncaught Error: 自定义异常
at <anonymous>:1:7`;
try {
Error.stackTraceLimit = 100
} catch(err) {
console.log(err.stack);
}
- 重定义执行代码:通过执行器执行的方式,通常会传入字符串代码。这时候就可以考虑对代码进行变换,使其抛出我们需要的异常信息。
3 总结
这些问题都可以归结为将一串信息改变为我们期望的形式。因此关键就在于找到一个合适的修改点。可以是函数拦截、代码修改、甚至修改浏览器代码。在抛出过程中有些信息是动态变化的,因此可以结合一些动态请求,配合调整输出即可。
4 参考
[1]错误处理机制,https://javascript.ruanyifeng.com/grammar/error.html#toc0