@fanboynz/network-scanner 2.0.14 → 2.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/fingerprint.js +234 -14
- package/nwss.js +32 -3
- package/package.json +2 -2
package/lib/fingerprint.js
CHANGED
|
@@ -16,17 +16,17 @@ const BUILT_IN_PROPERTIES = new Set([
|
|
|
16
16
|
// User agent collections with latest versions
|
|
17
17
|
const USER_AGENT_COLLECTIONS = {
|
|
18
18
|
chrome: [
|
|
19
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
20
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
21
|
-
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
19
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
20
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
21
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
|
|
22
22
|
],
|
|
23
23
|
firefox: [
|
|
24
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:
|
|
25
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:
|
|
26
|
-
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:
|
|
24
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0",
|
|
25
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:143.0) Gecko/20100101 Firefox/143.0",
|
|
26
|
+
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0"
|
|
27
27
|
],
|
|
28
28
|
safari: [
|
|
29
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.
|
|
29
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15",
|
|
30
30
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15"
|
|
31
31
|
]
|
|
32
32
|
};
|
|
@@ -387,6 +387,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
// Remove webdriver properties
|
|
390
|
+
//
|
|
390
391
|
safeExecute(() => {
|
|
391
392
|
try {
|
|
392
393
|
delete navigator.webdriver;
|
|
@@ -395,6 +396,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
395
396
|
}, 'webdriver removal');
|
|
396
397
|
|
|
397
398
|
// Remove automation properties
|
|
399
|
+
//
|
|
398
400
|
safeExecute(() => {
|
|
399
401
|
const automationProps = [
|
|
400
402
|
'callPhantom', '_phantom', '__nightmare', '_selenium', '__selenium_unwrapped',
|
|
@@ -417,6 +419,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
417
419
|
}, 'automation properties removal');
|
|
418
420
|
|
|
419
421
|
// Simulate Chrome runtime
|
|
422
|
+
//
|
|
420
423
|
safeExecute(() => {
|
|
421
424
|
if (!window.chrome?.runtime) {
|
|
422
425
|
window.chrome = {
|
|
@@ -449,6 +452,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
449
452
|
}, 'Chrome runtime simulation');
|
|
450
453
|
|
|
451
454
|
// Spoof plugins based on user agent
|
|
455
|
+
//
|
|
452
456
|
safeExecute(() => {
|
|
453
457
|
let plugins = [];
|
|
454
458
|
if (userAgent.includes('Chrome')) {
|
|
@@ -482,12 +486,25 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
482
486
|
// Safari typically has no plugins in modern versions
|
|
483
487
|
plugins = [];
|
|
484
488
|
}
|
|
485
|
-
// Create array-like object with length
|
|
486
|
-
const pluginsArray =
|
|
489
|
+
// Create proper array-like object with enumerable indices and length
|
|
490
|
+
const pluginsArray = {};
|
|
491
|
+
plugins.forEach((plugin, index) => {
|
|
492
|
+
pluginsArray[index] = plugin;
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
// Ensure length property is properly defined
|
|
496
|
+
Object.defineProperty(pluginsArray, 'length', {
|
|
497
|
+
value: plugins.length,
|
|
498
|
+
writable: false,
|
|
499
|
+
enumerable: false,
|
|
500
|
+
configurable: false
|
|
501
|
+
});
|
|
502
|
+
|
|
487
503
|
safeDefinePropertyLocal(navigator, 'plugins', { get: () => pluginsArray });
|
|
488
504
|
}, 'plugins spoofing');
|
|
489
505
|
|
|
490
506
|
// Spoof languages
|
|
507
|
+
//
|
|
491
508
|
safeExecute(() => {
|
|
492
509
|
const languages = ['en-US', 'en'];
|
|
493
510
|
safeDefinePropertyLocal(navigator, 'languages', { get: () => languages });
|
|
@@ -495,6 +512,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
495
512
|
}, 'language spoofing');
|
|
496
513
|
|
|
497
514
|
// Spoof vendor information
|
|
515
|
+
//
|
|
498
516
|
safeExecute(() => {
|
|
499
517
|
let vendor = 'Google Inc.';
|
|
500
518
|
let product = 'Gecko';
|
|
@@ -510,6 +528,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
510
528
|
}, 'vendor/product spoofing');
|
|
511
529
|
|
|
512
530
|
// Enhanced OS fingerprinting protection based on actual user agent content
|
|
531
|
+
//
|
|
513
532
|
safeExecute(() => {
|
|
514
533
|
let osType = 'windows';
|
|
515
534
|
let browserType = 'chrome';
|
|
@@ -552,7 +571,15 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
552
571
|
}
|
|
553
572
|
}, 'enhanced OS fingerprinting protection');
|
|
554
573
|
|
|
574
|
+
// Hardware concurrency spoofing (universal coverage)
|
|
575
|
+
//
|
|
576
|
+
safeExecute(() => {
|
|
577
|
+
safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => [4, 6, 8, 12][Math.floor(Math.random() * 4)] });
|
|
578
|
+
}, 'hardware concurrency spoofing');
|
|
579
|
+
|
|
580
|
+
|
|
555
581
|
// Screen resolution fingerprinting protection
|
|
582
|
+
//
|
|
556
583
|
safeExecute(() => {
|
|
557
584
|
// Common realistic resolutions to avoid fingerprinting
|
|
558
585
|
const commonResolutions = [
|
|
@@ -573,6 +600,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
573
600
|
}, 'screen resolution protection');
|
|
574
601
|
|
|
575
602
|
// Spoof MIME types
|
|
603
|
+
//
|
|
576
604
|
safeExecute(() => {
|
|
577
605
|
let mimeTypes = [];
|
|
578
606
|
if (userAgent.includes('Chrome')) {
|
|
@@ -646,28 +674,118 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
646
674
|
}, 'fingerprinting mocks');
|
|
647
675
|
|
|
648
676
|
// WebGL spoofing
|
|
677
|
+
//
|
|
649
678
|
safeExecute(() => {
|
|
679
|
+
// Enhanced WebGL fingerprinting protection
|
|
680
|
+
const webglParams = {
|
|
681
|
+
37445: 'Intel Inc.', // VENDOR
|
|
682
|
+
37446: 'Intel(R) UHD Graphics 630', // RENDERER (more realistic)
|
|
683
|
+
7936: 'WebGL 1.0 (OpenGL ES 2.0 Chromium)', // VERSION
|
|
684
|
+
35724: 'WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.00 Chromium)', // SHADING_LANGUAGE_VERSION
|
|
685
|
+
34076: 16384, // MAX_TEXTURE_SIZE
|
|
686
|
+
34024: 16384, // MAX_CUBE_MAP_TEXTURE_SIZE
|
|
687
|
+
34930: new Float32Array([1, 1]), // ALIASED_LINE_WIDTH_RANGE
|
|
688
|
+
33901: new Float32Array([0, 1]), // ALIASED_POINT_SIZE_RANGE
|
|
689
|
+
35660: 16, // MAX_VERTEX_ATTRIBS
|
|
690
|
+
35661: 16, // MAX_VERTEX_UNIFORM_VECTORS
|
|
691
|
+
35659: 16, // MAX_VARYING_VECTORS
|
|
692
|
+
35663: 16, // MAX_FRAGMENT_UNIFORM_VECTORS
|
|
693
|
+
36347: 4096, // MAX_RENDERBUFFER_SIZE
|
|
694
|
+
34852: 32, // MAX_COMBINED_TEXTURE_IMAGE_UNITS
|
|
695
|
+
2978: new Int32Array([0, 0, 1920, 1080]), // VIEWPORT
|
|
696
|
+
3379: new Int32Array([0, 0, 1920, 1080]) // SCISSOR_BOX
|
|
697
|
+
};
|
|
698
|
+
|
|
650
699
|
if (window.WebGLRenderingContext) {
|
|
651
700
|
const getParameter = WebGLRenderingContext.prototype.getParameter;
|
|
652
701
|
WebGLRenderingContext.prototype.getParameter = function(parameter) {
|
|
653
|
-
if (parameter
|
|
654
|
-
|
|
702
|
+
if (webglParams.hasOwnProperty(parameter)) {
|
|
703
|
+
return webglParams[parameter];
|
|
704
|
+
}
|
|
655
705
|
return getParameter.call(this, parameter);
|
|
656
706
|
};
|
|
707
|
+
// Spoof supported extensions
|
|
708
|
+
const getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;
|
|
709
|
+
WebGLRenderingContext.prototype.getSupportedExtensions = function() {
|
|
710
|
+
return [
|
|
711
|
+
'ANGLE_instanced_arrays',
|
|
712
|
+
'EXT_blend_minmax',
|
|
713
|
+
'EXT_color_buffer_half_float',
|
|
714
|
+
'EXT_disjoint_timer_query',
|
|
715
|
+
'EXT_float_blend',
|
|
716
|
+
'EXT_frag_depth',
|
|
717
|
+
'EXT_shader_texture_lod',
|
|
718
|
+
'EXT_texture_compression_rgtc',
|
|
719
|
+
'EXT_texture_filter_anisotropic',
|
|
720
|
+
'WEBKIT_EXT_texture_filter_anisotropic',
|
|
721
|
+
'EXT_sRGB',
|
|
722
|
+
'OES_element_index_uint',
|
|
723
|
+
'OES_fbo_render_mipmap',
|
|
724
|
+
'OES_standard_derivatives',
|
|
725
|
+
'OES_texture_float',
|
|
726
|
+
'OES_texture_float_linear',
|
|
727
|
+
'OES_texture_half_float',
|
|
728
|
+
'OES_texture_half_float_linear',
|
|
729
|
+
'OES_vertex_array_object',
|
|
730
|
+
'WEBGL_color_buffer_float',
|
|
731
|
+
'WEBGL_compressed_texture_s3tc',
|
|
732
|
+
'WEBGL_debug_renderer_info',
|
|
733
|
+
'WEBGL_debug_shaders',
|
|
734
|
+
'WEBGL_depth_texture',
|
|
735
|
+
'WEBGL_draw_buffers',
|
|
736
|
+
'WEBGL_lose_context'
|
|
737
|
+
];
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
// Also handle WebGL2 context
|
|
741
|
+
if (window.WebGL2RenderingContext) {
|
|
742
|
+
const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
|
|
743
|
+
WebGL2RenderingContext.prototype.getParameter = function(parameter) {
|
|
744
|
+
if (webglParams.hasOwnProperty(parameter)) {
|
|
745
|
+
return webglParams[parameter];
|
|
746
|
+
}
|
|
747
|
+
return getParameter2.call(this, parameter);
|
|
748
|
+
};
|
|
657
749
|
}
|
|
658
750
|
}, 'WebGL spoofing');
|
|
659
751
|
|
|
660
752
|
// Permissions API spoofing
|
|
753
|
+
//
|
|
661
754
|
safeExecute(() => {
|
|
662
755
|
if (navigator.permissions?.query) {
|
|
663
756
|
const originalQuery = navigator.permissions.query;
|
|
664
757
|
navigator.permissions.query = function(descriptor) {
|
|
665
|
-
|
|
758
|
+
// More realistic permission states based on permission type
|
|
759
|
+
const permissionName = descriptor.name || descriptor;
|
|
760
|
+
let state = 'prompt'; // Default state
|
|
761
|
+
|
|
762
|
+
// Common permissions that are usually granted
|
|
763
|
+
if (['notifications', 'persistent-storage'].includes(permissionName)) {
|
|
764
|
+
state = Math.random() > 0.3 ? 'granted' : 'prompt';
|
|
765
|
+
}
|
|
766
|
+
// Privacy-sensitive permissions that are usually denied/prompt
|
|
767
|
+
else if (['camera', 'microphone', 'geolocation'].includes(permissionName)) {
|
|
768
|
+
state = Math.random() > 0.8 ? 'granted' : 'prompt';
|
|
769
|
+
}
|
|
770
|
+
// Other permissions random
|
|
771
|
+
else {
|
|
772
|
+
state = Math.random() > 0.5 ? 'granted' : 'prompt';
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
return Promise.resolve({
|
|
776
|
+
state: state,
|
|
777
|
+
onchange: null
|
|
778
|
+
});
|
|
666
779
|
};
|
|
667
780
|
}
|
|
781
|
+
// Block permission prompts from actually appearing
|
|
782
|
+
if (window.Notification && Notification.requestPermission) {
|
|
783
|
+
Notification.requestPermission = () => Promise.resolve('default');
|
|
784
|
+
}
|
|
668
785
|
}, 'permissions API spoofing');
|
|
669
786
|
|
|
670
787
|
// Media Device Spoofing
|
|
788
|
+
//
|
|
671
789
|
safeExecute(() => {
|
|
672
790
|
if (navigator.mediaDevices?.enumerateDevices) {
|
|
673
791
|
navigator.mediaDevices.enumerateDevices = function() {
|
|
@@ -681,6 +799,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
681
799
|
}, 'media device spoofing');
|
|
682
800
|
|
|
683
801
|
// Fetch Request Headers Normalization
|
|
802
|
+
//
|
|
684
803
|
safeExecute(() => {
|
|
685
804
|
const originalFetch = window.fetch;
|
|
686
805
|
window.fetch = function(url, options = {}) {
|
|
@@ -702,6 +821,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
702
821
|
}, 'fetch headers normalization');
|
|
703
822
|
|
|
704
823
|
// Image Loading Pattern Obfuscation
|
|
824
|
+
//
|
|
705
825
|
safeExecute(() => {
|
|
706
826
|
const originalImageSrc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
|
|
707
827
|
if (originalImageSrc) {
|
|
@@ -719,6 +839,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
719
839
|
}, 'image loading obfuscation');
|
|
720
840
|
|
|
721
841
|
// CSS Media Query Spoofing
|
|
842
|
+
//
|
|
722
843
|
safeExecute(() => {
|
|
723
844
|
const originalMatchMedia = window.matchMedia;
|
|
724
845
|
window.matchMedia = function(query) {
|
|
@@ -736,6 +857,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
736
857
|
}, 'CSS media query spoofing');
|
|
737
858
|
|
|
738
859
|
// Enhanced WebRTC Spoofing
|
|
860
|
+
//
|
|
739
861
|
safeExecute(() => {
|
|
740
862
|
if (window.RTCPeerConnection) {
|
|
741
863
|
const OriginalRTC = window.RTCPeerConnection;
|
|
@@ -752,6 +874,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
752
874
|
}, 'WebRTC spoofing');
|
|
753
875
|
|
|
754
876
|
// Font fingerprinting protection
|
|
877
|
+
//
|
|
755
878
|
safeExecute(() => {
|
|
756
879
|
// Standardize available fonts to common system fonts
|
|
757
880
|
const standardFonts = [
|
|
@@ -760,7 +883,100 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
760
883
|
'Trebuchet MS', 'Arial Black', 'Impact', 'Tahoma', 'Lucida Console'
|
|
761
884
|
];
|
|
762
885
|
|
|
886
|
+
// Intercept font availability detection
|
|
887
|
+
if (document.fonts && document.fonts.check) {
|
|
888
|
+
const originalCheck = document.fonts.check;
|
|
889
|
+
document.fonts.check = function(fontSpec) {
|
|
890
|
+
// Always return true for standard fonts, false for others
|
|
891
|
+
const fontFamily = fontSpec.match(/['"]([^'"]+)['"]/)?.[1] || fontSpec.split(' ').pop();
|
|
892
|
+
return standardFonts.some(font => fontFamily.includes(font));
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Prevent font loading detection
|
|
897
|
+
if (document.fonts && document.fonts.load) {
|
|
898
|
+
document.fonts.load = function() {
|
|
899
|
+
return Promise.resolve([]);
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// Canvas-based font fingerprinting protection
|
|
904
|
+
//
|
|
905
|
+
const originalFillText = CanvasRenderingContext2D.prototype.fillText;
|
|
906
|
+
const originalStrokeText = CanvasRenderingContext2D.prototype.strokeText;
|
|
907
|
+
const originalMeasureText = CanvasRenderingContext2D.prototype.measureText;
|
|
908
|
+
|
|
909
|
+
CanvasRenderingContext2D.prototype.fillText = function(text, x, y, maxWidth) {
|
|
910
|
+
// Normalize font to standard before drawing
|
|
911
|
+
const currentFont = this.font;
|
|
912
|
+
if (currentFont && !standardFonts.some(font => currentFont.includes(font))) {
|
|
913
|
+
this.font = currentFont.replace(/['"]?[^'"]*['"]?/, '"Arial"');
|
|
914
|
+
}
|
|
915
|
+
return originalFillText.call(this, text, x, y, maxWidth);
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
CanvasRenderingContext2D.prototype.strokeText = function(text, x, y, maxWidth) {
|
|
919
|
+
const currentFont = this.font;
|
|
920
|
+
if (currentFont && !standardFonts.some(font => currentFont.includes(font))) {
|
|
921
|
+
this.font = currentFont.replace(/['"]?[^'"]*['"]?/, '"Arial"');
|
|
922
|
+
}
|
|
923
|
+
return originalStrokeText.call(this, text, x, y, maxWidth);
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
CanvasRenderingContext2D.prototype.measureText = function(text) {
|
|
927
|
+
const result = originalMeasureText.call(this, text);
|
|
928
|
+
// Add slight noise to text measurements to prevent precise fingerprinting
|
|
929
|
+
result.width += (Math.random() - 0.5) * 0.1;
|
|
930
|
+
return result;
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
// Comprehensive canvas fingerprinting protection
|
|
934
|
+
//
|
|
935
|
+
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
|
|
936
|
+
CanvasRenderingContext2D.prototype.getImageData = function(sx, sy, sw, sh) {
|
|
937
|
+
const imageData = originalGetImageData.call(this, sx, sy, sw, sh);
|
|
938
|
+
// Add subtle noise to pixel data
|
|
939
|
+
for (let i = 0; i < imageData.data.length; i += 4) {
|
|
940
|
+
if (Math.random() < 0.1) { // 10% chance to modify each pixel
|
|
941
|
+
imageData.data[i] = Math.max(0, Math.min(255, imageData.data[i] + Math.floor(Math.random() * 3) - 1));
|
|
942
|
+
imageData.data[i + 1] = Math.max(0, Math.min(255, imageData.data[i + 1] + Math.floor(Math.random() * 3) - 1));
|
|
943
|
+
imageData.data[i + 2] = Math.max(0, Math.min(255, imageData.data[i + 2] + Math.floor(Math.random() * 3) - 1));
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return imageData;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
// WebGL canvas context fingerprinting
|
|
950
|
+
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
|
951
|
+
HTMLCanvasElement.prototype.getContext = function(contextType, contextAttributes) {
|
|
952
|
+
const context = originalGetContext.call(this, contextType, contextAttributes);
|
|
953
|
+
|
|
954
|
+
if (contextType === 'webgl' || contextType === 'webgl2' || contextType === 'experimental-webgl') {
|
|
955
|
+
// Override WebGL-specific fingerprinting methods
|
|
956
|
+
const originalGetShaderPrecisionFormat = context.getShaderPrecisionFormat;
|
|
957
|
+
context.getShaderPrecisionFormat = function(shaderType, precisionType) {
|
|
958
|
+
return {
|
|
959
|
+
rangeMin: 127,
|
|
960
|
+
rangeMax: 127,
|
|
961
|
+
precision: 23
|
|
962
|
+
};
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
const originalGetExtension = context.getExtension;
|
|
966
|
+
context.getExtension = function(name) {
|
|
967
|
+
// Block access to fingerprinting-sensitive extensions
|
|
968
|
+
if (name === 'WEBGL_debug_renderer_info') {
|
|
969
|
+
return null;
|
|
970
|
+
}
|
|
971
|
+
return originalGetExtension.call(this, name);
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
return context;
|
|
976
|
+
};
|
|
977
|
+
|
|
763
978
|
// Override font detection methods
|
|
979
|
+
//
|
|
764
980
|
const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
|
|
765
981
|
const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
|
|
766
982
|
|
|
@@ -778,6 +994,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
778
994
|
}, 'font fingerprinting protection');
|
|
779
995
|
|
|
780
996
|
// Performance timing obfuscation
|
|
997
|
+
//
|
|
781
998
|
safeExecute(() => {
|
|
782
999
|
const originalNow = performance.now;
|
|
783
1000
|
performance.now = function() {
|
|
@@ -786,6 +1003,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
786
1003
|
}, 'performance timing obfuscation');
|
|
787
1004
|
|
|
788
1005
|
// Canvas fingerprinting protection
|
|
1006
|
+
//
|
|
789
1007
|
safeExecute(() => {
|
|
790
1008
|
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
791
1009
|
HTMLCanvasElement.prototype.toDataURL = function(...args) {
|
|
@@ -802,6 +1020,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
802
1020
|
}, 'canvas fingerprinting protection');
|
|
803
1021
|
|
|
804
1022
|
// Battery API spoofing
|
|
1023
|
+
//
|
|
805
1024
|
safeExecute(() => {
|
|
806
1025
|
if (navigator.getBattery) {
|
|
807
1026
|
navigator.getBattery = function() {
|
|
@@ -815,9 +1034,8 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
815
1034
|
}
|
|
816
1035
|
}, 'battery API spoofing');
|
|
817
1036
|
|
|
818
|
-
// Suppress common console errors
|
|
819
|
-
|
|
820
1037
|
// Enhanced Mouse/Pointer Spoofing
|
|
1038
|
+
//
|
|
821
1039
|
safeExecute(() => {
|
|
822
1040
|
// Spoof pointer capabilities
|
|
823
1041
|
if (navigator.maxTouchPoints !== undefined) {
|
|
@@ -841,6 +1059,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
841
1059
|
};
|
|
842
1060
|
|
|
843
1061
|
// Spoof PointerEvent if available
|
|
1062
|
+
//
|
|
844
1063
|
if (window.PointerEvent) {
|
|
845
1064
|
const OriginalPointerEvent = window.PointerEvent;
|
|
846
1065
|
window.PointerEvent = function(type, eventInitDict = {}) {
|
|
@@ -870,6 +1089,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
870
1089
|
}
|
|
871
1090
|
|
|
872
1091
|
// Spoof mouse wheel behavior
|
|
1092
|
+
//
|
|
873
1093
|
const originalWheelEvent = window.WheelEvent;
|
|
874
1094
|
if (originalWheelEvent) {
|
|
875
1095
|
window.WheelEvent = function(type, eventInitDict = {}) {
|
package/nwss.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// === Network scanner script (nwss.js) v2.0.
|
|
1
|
+
// === Network scanner script (nwss.js) v2.0.16 ===
|
|
2
2
|
|
|
3
3
|
// puppeteer for browser automation, fs for file system operations, psl for domain parsing.
|
|
4
4
|
// const pLimit = require('p-limit'); // Will be dynamically imported
|
|
@@ -130,7 +130,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
|
|
|
130
130
|
const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
|
|
131
131
|
|
|
132
132
|
// --- Script Configuration & Constants ---
|
|
133
|
-
const VERSION = '2.0.
|
|
133
|
+
const VERSION = '2.0.16'; // Script version
|
|
134
134
|
|
|
135
135
|
// get startTime
|
|
136
136
|
const startTime = Date.now();
|
|
@@ -1335,6 +1335,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1335
1335
|
'--memory-pressure-off',
|
|
1336
1336
|
'--max_old_space_size=2048',
|
|
1337
1337
|
'--no-first-run',
|
|
1338
|
+
'--disable-prompt-on-repost', // Fixes form popup on page reload
|
|
1338
1339
|
'--disable-default-apps',
|
|
1339
1340
|
'--disable-component-extensions-with-background-pages',
|
|
1340
1341
|
'--disable-background-networking',
|
|
@@ -1994,6 +1995,34 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1994
1995
|
// --- Apply all fingerprint spoofing (user agent, Brave, fingerprint protection) ---
|
|
1995
1996
|
try {
|
|
1996
1997
|
await applyAllFingerprintSpoofing(page, siteConfig, forceDebug, currentUrl);
|
|
1998
|
+
|
|
1999
|
+
// Client Hints protection for Chrome user agents
|
|
2000
|
+
if (siteConfig.userAgent && siteConfig.userAgent.toLowerCase().includes('chrome')) {
|
|
2001
|
+
let platform = 'Windows';
|
|
2002
|
+
let platformVersion = '15.0.0';
|
|
2003
|
+
let arch = 'x86';
|
|
2004
|
+
|
|
2005
|
+
if (siteConfig.userAgent.toLowerCase() === 'chrome_mac') {
|
|
2006
|
+
platform = 'macOS';
|
|
2007
|
+
platformVersion = '13.5.0';
|
|
2008
|
+
arch = 'arm';
|
|
2009
|
+
} else if (siteConfig.userAgent.toLowerCase() === 'chrome_linux') {
|
|
2010
|
+
platform = 'Linux';
|
|
2011
|
+
platformVersion = '6.5.0';
|
|
2012
|
+
arch = 'x86';
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
await page.setExtraHTTPHeaders({
|
|
2016
|
+
'Sec-CH-UA': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"',
|
|
2017
|
+
'Sec-CH-UA-Platform': `"${platform}"`,
|
|
2018
|
+
'Sec-CH-UA-Platform-Version': `"${platformVersion}"`,
|
|
2019
|
+
'Sec-CH-UA-Mobile': '?0',
|
|
2020
|
+
'Sec-CH-UA-Arch': `"${arch}"`,
|
|
2021
|
+
'Sec-CH-UA-Bitness': '"64"',
|
|
2022
|
+
'Sec-CH-UA-Full-Version': '"140.0.7339.208"',
|
|
2023
|
+
'Sec-CH-UA-Full-Version-List': '"Chromium";v="140.0.7339.208", "Not=A?Brand";v="24.0.0.0", "Google Chrome";v="140.0.7339.208"'
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
1997
2026
|
} catch (fingerprintErr) {
|
|
1998
2027
|
if (fingerprintErr.message.includes('Session closed') ||
|
|
1999
2028
|
fingerprintErr.message.includes('Protocol error') ||
|
|
@@ -4002,4 +4031,4 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
4002
4031
|
if (forceDebug) console.log(formatLogMessage('debug', `About to exit process...`));
|
|
4003
4032
|
process.exit(0);
|
|
4004
4033
|
|
|
4005
|
-
})();
|
|
4034
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanboynz/network-scanner",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
4
4
|
"description": "A Puppeteer-based network scanner for analyzing web traffic, generating adblock filter rules, and identifying third-party requests. Features include fingerprint spoofing, Cloudflare bypass, content analysis with curl/grep, and multiple output formats.",
|
|
5
5
|
"main": "nwss.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"puppeteer": ">=20.0.0"
|
|
17
17
|
},
|
|
18
18
|
"overrides": {
|
|
19
|
-
"tar-fs": "3.1.
|
|
19
|
+
"tar-fs": "3.1.1",
|
|
20
20
|
"ws": "8.18.3"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|