
补环境常见检测点与Node.js模拟前言通常我们在进行js逆向的时候会发现js文件它通过检测大量的浏览器环境特征来区分真实浏览器和自动化脚本/模拟环境。本文将分析补环境的关键环境检测点并探讨如何在Node.js环境中进行有效模拟。环境检测点详解1. Window对象属性存在性检测检测含义与目的检测浏览器特有的全局对象和属性是否存在验证环境是否具备完整的浏览器特性集合识别非浏览器环境如Node.js中缺失的浏览器特有属性检测点chromeinwindowwebkitinwindowlocalStorageinwindowsessionStorageinwindowNode.js模拟方案Object.defineProperties(global,{chrome:{value:{runtime:{},loadTimes:()({})},writable:false,configurable:false},webkit:{value:{messageHandlers:{}},writable:false,configurable:false}});classMockStorage{constructor(){this.storenewMap();}getItem(key){returnthis.store.get(key)||null;}setItem(key,value){this.store.set(key,String(value));}removeItem(key){this.store.delete(key);}clear(){this.store.clear();}getlength(){returnthis.store.size;}key(index){returnArray.from(this.store.keys())[index];}}global.localStoragenewMockStorage();global.sessionStoragenewMockStorage();2. 属性描述符检测检测含义与目的验证浏览器内置属性的描述符特征检测环境是否正确实现了属性描述符标准识别通过简单赋值模拟的属性缺少正确的描述符配置检测点Object.getOwnPropertyDescriptor(window,chrome)Object.getOwnPropertyDescriptor(navigator,userAgent)Node.js模拟方案constdefinePropertyWithDescriptor(obj,prop,value){Object.defineProperty(obj,prop,{value,writable:false,enumerable:true,configurable:false});};definePropertyWithDescriptor(global,chrome,{runtime:{},loadTimes:()({})});definePropertyWithDescriptor(global.navigator,userAgent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36);3. Navigator对象硬件信息检测检测含义与目的获取用户设备的硬件配置信息检测环境是否提供合理的硬件参数识别虚拟机或自动化环境中的异常硬件配置检测点navigator.hardwareConcurrency navigator.deviceMemory navigator.webdriverNode.js模拟方案Object.defineProperties(global.navigator,{hardwareConcurrency:{value:8,writable:false,configurable:false},deviceMemory:{value:8,writable:false,configurable:false},webdriver:{value:false,writable:false,configurable:false}});4. Battery API检测检测含义与目的检测设备电池状态API的可用性验证Promise-based API的正确实现识别缺乏硬件相关API的模拟环境检测点navigator.getBattery().then(battery{console.log(battery.level,battery.charging);});Node.js模拟方案constmockBattery{level:0.85,charging:true,chargingTime:1800,dischargingTime:Infinity,onchargingchange:null,onlevelchange:null,onchargingtimechange:null,ondischargingtimechange:null};Object.defineProperty(global.navigator,getBattery,{value:()Promise.resolve(mockBattery),writable:false,configurable:false});5. 插件和MIME类型检测检测含义与目的检测浏览器插件生态系统的完整性验证插件与MIME类型的关联关系识别缺乏常见浏览器插件的自动化环境检测点navigator.plugins navigator.mimeTypesNode.js模拟方案constmockPlugins[{name:Chrome PDF Plugin,filename:internal-pdf-viewer,description:Portable Document Format,length:1}];Object.defineProperty(global.navigator,plugins,{value:mockPlugins,writable:false,configurable:false});constmockMimeTypes[{type:application/pdf,description:Portable Document Format,suffixes:pdf,enabledPlugin:mockPlugins[0]}];Object.defineProperty(global.navigator,mimeTypes,{value:mockMimeTypes,writable:false,configurable:false});6. 屏幕属性检测检测含义与目的获取用户屏幕的物理特性参数检测屏幕配置的合理性和一致性识别异常的屏幕配置如零尺寸或极端值检测点screen.width screen.height screen.colorDepth screen.pixelDepth screen.availWidth screen.availHeightNode.js模拟方案Object.defineProperties(global.screen,{width:{value:1920,writable:false,configurable:false},height:{value:1080,writable:false,configurable:false},colorDepth:{value:24,writable:false,configurable:false},pixelDepth:{value:24,writable:false,configurable:false},availWidth:{value:1920,writable:false,configurable:false},availHeight:{value:1040,writable:false,configurable:false}});7. 原型链toString检测检测含义与目的验证对象内部[[Class]]属性的正确性检测对象原型链的完整性识别通过简单对象模拟的内置对象检测点Object.prototype.toString.call(navigator)Object.prototype.toString.call(screen)Object.prototype.toString.call([])Node.js模拟方案constoriginalToStringObject.prototype.toString;Object.prototype.toStringfunction(){if(thisglobal.navigator)return[object Navigator];if(thisglobal.screen)return[object Screen];if(thisglobal)return[object Window];if(Array.isArray(this))return[object Array];returnoriginalToString.call(this);};8. 时区和语言检测检测含义与目的检测用户的地理位置和语言偏好验证国际化API的正确实现识别配置异常或缺乏国际化支持的环境检测点Intl.DateTimeFormat().resolvedOptions().timeZone navigator.language navigator.languagesNode.js模拟方案Object.defineProperties(global.navigator,{language:{value:zh-CN,writable:false,configurable:false},languages:{value:[zh-CN,zh,en],writable:false,configurable:false}});constoriginalDateTimeFormatIntl.DateTimeFormat;Intl.DateTimeFormatfunction(locales,options){constoptsoptions||{};if(!opts.timeZone){opts.timeZoneAsia/Shanghai;}returnoriginalDateTimeFormat(locales,opts);};9. 媒体能力检测检测含义与目的检测浏览器对多媒体格式的支持能力验证HTMLMediaElement API的正确实现识别缺乏媒体支持或支持异常的自动化环境检测点constvideodocument.createElement(video);video.canPlayType(video/mp4)video.canPlayType(video/webm)Node.js模拟方案global.document{createElement:(tagName){constelement{tagName:tagName.toLowerCase()};if(tagName.toLowerCase()video||tagName.toLowerCase()audio){element.canPlayType(type){constsupportedTypes{video/mp4:probably,video/webm:maybe,audio/mp3:probably,audio/wav:maybe,audio/mpeg:probably};returnsupportedTypes[type]||;};}returnelement;}};10. 字体检测检测含义与目的检测系统字体的可用性和多样性验证CSS Font Loading API的实现识别缺乏字体多样性或字体API异常的环境检测点document.fonts.check(12px Arial)document.fonts.check(12px Microsoft YaHei)Node.js模拟方案Object.defineProperty(global.document,fonts,{value:{check:(fontSpec){constcommonFonts[Arial,Times New Roman,Courier New,Verdana,Microsoft YaHei,SimSun,SimHei,KaiTi];returncommonFonts.some(fontfontSpec.includes(font));},ready:Promise.resolve(),add:(){},delete:(){},clear:(){},load:()Promise.resolve()},writable:false,configurable:false});11. Performance API检测检测含义与目的检测性能时间线的准确性和合理性验证高精度时间API的实现识别性能数据异常或缺乏性能监控的环境检测点performance.now()performance.timing performance.memoryNode.js模拟方案classMockPerformance{constructor(){this.startTimeDate.now();this.timing{navigationStart:this.startTime-1000,loadEventEnd:this.startTime,domainLookupStart:this.startTime-800,domainLookupEnd:this.startTime-700,connectStart:this.startTime-700,connectEnd:this.startTime-600,requestStart:this.startTime-500,responseStart:this.startTime-300,responseEnd:this.startTime-200,domLoading:this.startTime-150,domInteractive:this.startTime-100,domContentLoadedEventStart:this.startTime-50,domContentLoadedEventEnd:this.startTime-40,domComplete:this.startTime-20,loadEventStart:this.startTime-10};}now(){returnDate.now()-this.startTime;}}global.performancenewMockPerformance();if(global.chrome){Object.defineProperty(global.performance,memory,{value:{usedJSHeapSize:10000000,totalJSHeapSize:20000000,jsHeapSizeLimit:400000000},writable:false,configurable:false});}12. WebGL检测检测含义与目的检测图形渲染能力和硬件加速支持验证WebGL API的完整性和正确性识别缺乏图形支持或WebGL实现异常的环境检测点constcanvasdocument.createElement(canvas);constglcanvas.getContext(webgl);gl.getParameter(0x1F00)gl.getParameter(0x1F01)Node.js模拟方案constoriginalCreateElementglobal.document.createElement;global.document.createElementfunction(tagName){constelementoriginalCreateElement.call(this,tagName);if(tagName.toLowerCase()canvas){element.getContext(contextType){if(contextTypewebgl||contextTypeexperimental-webgl){return{getParameter:(param){constparams{0x1F00:Google Inc. (Apple),0x1F01:Apple A15 GPU,0x1F03:WebGL 2.0,0x8B64:WebGL GLSL ES 1.0,0x8B8C:4096};returnparams[param]||null;},getExtension:()null,getSupportedExtensions:()[ANGLE_instanced_arrays,EXT_blend_minmax,EXT_texture_filter_anisotropic],clear:(){},drawArrays:(){}};}returnnull;};}returnelement;};瑞数补环境框架最近本人做了一个瑞数的补环境框架通杀瑞数4\5\6代瑞数有兴趣的可以一起交流一下免责声明本文内容仅供技术研究和学习之用请遵守相关法律法规和网站使用条款不得用于非法用途。