|
// ==UserScript== |
|
// @name Bypass DevTools Detection |
|
// @namespace http://tampermonkey.net/ |
|
// @version 1.0 |
|
// @description Try to run before the site code |
|
// @author You |
|
// @match https://example.com/* |
|
// @run-at document-start |
|
// @grant none |
|
// ==/UserScript== |
|
|
|
/** |
|
* === Bypass DevTools Detection Script === |
|
* |
|
* מטרת הסקריפט: |
|
* לאפשר שימוש בכלי המפתחים (Developer Tools) באתר read.e-vrit.co.il מבלי להיחסם. |
|
* האתר משתמש בספריית זיהוי המבצעת "מתקפות ביצועים" ובדיקות אחרות כדי לזהות אם הכלים פתוחים. |
|
* |
|
* איך זה עובד? |
|
* הסקריפט משתמש ב-Proxy כדי לעטוף את אובייקט ה-console ולנטרל את בדיקות הזיהוי בזמן אמת. |
|
* |
|
* מנגנוני הגנה (Strategies): |
|
* 1. Console Proxy: יירוט כל הקריאות לקונסולה. |
|
* - חסימה מלאה: פונקציות כמו profile, table, clear מנוטרלות לחלוטין. |
|
* - סינון ארגומנטים: הסרת אובייקטים חשודים (RegExp, Functions, Large Arrays) שמשמשים לזיהוי. |
|
* 2. Rate Limiting (חסימת הצפות): |
|
* - מנגנון אוטומטי שמזהה סקריפטים המדפיסים בכמות חריגה (מעל 10 בשנייה). |
|
* - סקריפט מציף מזוהה כ-Spammer ונחסם לחלוטין (חוסך את ה-Lag שנגרם ממתקפת הביצועים). |
|
* 3. Stack Trace Analysis: |
|
* - זיהוי קובץ המקור של כל הדפסה והצגתו בלוגים (לצורך דיבוג וחסימה עתידית). |
|
* 4. Global Object Neutralization: |
|
* - יצירת אובייקט דמי (Dummy) בשם DevtoolsDetector והקפאתו, כדי למנוע מהספרייה המקורית להיטען. |
|
*/ |
|
|
|
(function () { |
|
"use strict"; |
|
// הקוד שלך כאן ירוץ ראשון, עוד לפני שה-HEAD נטען במלואו |
|
console.log("Tampermonkey script started!"); |
|
|
|
// הפעלת האסטרטגיות |
|
bypassConsole(); |
|
bypassGlobalDetector(); |
|
|
|
// --- אסטרטגיה 1: נטרול בדיקות דרך הקונסול (Proxy) --- |
|
function bypassConsole() { |
|
const handler = { |
|
get: function (target, prop, receiver) { |
|
// רשימת פונקציות שאנחנו רוצים לנטרל לחלוטין |
|
if (["profile", "profileEnd", "table", "clear"].includes(prop)) { |
|
return function () {}; |
|
} |
|
|
|
if (["log", "info", "warn", "debug"].includes(prop)) { |
|
return function (...args) { |
|
const fileName = getCallerFile(); |
|
|
|
// בדיקת חסימה (Rate Limiting) |
|
if (isBlockedByRateLimit(fileName, target)) { |
|
return; |
|
} |
|
|
|
// סינון ארגומנטים (Large Array / RegExp) |
|
const safeArgs = sanitizeArguments(args); |
|
|
|
// הדפסה עם שם המקור |
|
return target[prop].apply(this, [ |
|
`[Source: ${fileName}]`, |
|
...safeArgs, |
|
]); |
|
}; |
|
} |
|
|
|
return Reflect.get(target, prop, receiver); |
|
}, |
|
}; |
|
|
|
try { |
|
const originalConsole = window.console; |
|
window.console = new Proxy(originalConsole, handler); |
|
console.log("Strategy 1 (Console Proxy + Stack Check): Active"); |
|
} catch (e) { |
|
console.log("Strategy 1 Failed: " + e.message); |
|
} |
|
} |
|
|
|
// --- אסטרטגיה 2: נטרול האובייקט הגלובלי --- |
|
function bypassGlobalDetector() { |
|
try { |
|
window.DevtoolsDetector = { isLaunch: false, launch: function () {} }; |
|
Object.freeze(window.DevtoolsDetector); // מניעת דריסה |
|
console.log("Strategy 2 (Global Detector): Active"); |
|
} catch (e) { |
|
console.log("Strategy 2 Failed: " + e.message); |
|
} |
|
} |
|
|
|
// --- פונקציות עזר (Helpers) --- |
|
|
|
function getCallerFile() { |
|
const stack = new Error().stack || ""; |
|
// הזזה בשל פונקציית העזר: |
|
// 0: Error |
|
// 1: getCallerFile |
|
// 2: Proxy Trap (anonymous) |
|
// 3: The actual caller <--- This is what we want |
|
|
|
// ננסה לקחת שורה 3 או 4 ליתר ביטחון (תלוי דפדפן), אבל 3 היא הסבירה ביותר במבנה הנוכחי |
|
const callerLine = |
|
stack.split("\n")[3] || stack.split("\n")[2] || "Unknown"; |
|
const match = callerLine.match(/(?:https?:\/\/.*\/)([^:]+)/); |
|
|
|
if (match) { |
|
return match[1]; |
|
} |
|
|
|
// אם לא הצלחנו לחלץ שם קובץ, נחזיר את השורה המלאה ללא ה-at |
|
return callerLine.replace(/^\s*at\s+/, "").trim(); |
|
} |
|
|
|
function isBlockedByRateLimit(fileName, originalConsoleTarget) { |
|
if (window.blockedScripts && window.blockedScripts.has(fileName)) { |
|
return true; |
|
} |
|
|
|
if (!window.logCounters) { |
|
window.logCounters = {}; |
|
window.blockedScripts = new Set(); |
|
setInterval(() => { |
|
window.logCounters = {}; |
|
}, 1000); |
|
} |
|
|
|
window.logCounters[fileName] = (window.logCounters[fileName] || 0) + 1; |
|
|
|
if (window.logCounters[fileName] > 10) { |
|
if (!window.blockedScripts.has(fileName)) { |
|
window.blockedScripts.add(fileName); |
|
const msg = `[Bypass System] Blocking script due to spam (${window.logCounters[fileName]}+ logs/sec): ${fileName}`; |
|
originalConsoleTarget.warn.call(originalConsoleTarget, msg); // Use .call to ensure 'this' context if needed, though 'warn' is usually fine without it. |
|
} |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
function sanitizeArguments(args) { |
|
return args.map((arg) => { |
|
// זיהוי מתקפת מערכים |
|
if (Array.isArray(arg) && arg.length > 20) { |
|
// בדיקה שטחית אם זה מערך של אובייקטים כבדים |
|
if (typeof arg[0] === "object") { |
|
return "[Blocked Large Array - Performance Attack]"; |
|
} |
|
} |
|
// זיהוי בדיקות toString |
|
if (arg instanceof RegExp || typeof arg === "function") { |
|
return "[Redacted by Bypass]"; |
|
} |
|
return arg; |
|
}); |
|
} |
|
})(); |