Skip to content

Instantly share code, notes, and snippets.

@CyanChanges
Last active June 16, 2025 09:35
Show Gist options
  • Select an option

  • Save CyanChanges/d680fe30b2b2c1361d94651117447e5e to your computer and use it in GitHub Desktop.

Select an option

Save CyanChanges/d680fe30b2b2c1361d94651117447e5e to your computer and use it in GitHub Desktop.
Take down `https://www.soraacg.com/` 's devtools detector

Remove the devtools detector on https://www.soraacg.com/.
May works with other site using https://github.com/theajack/disable-devtool/ detector

适用于 https://www.soraacg.com/ 的开发者工具(Devtools)反检测, 也许可以支持其他使用 https://github.com/theajack/disable-devtool/ 检测的网站

查看用法

原因: image

Usage

  1. Install soraacg-killer+default.user.js provide in the gist in your favourite UserScript Manager
  2. And enter the website that detect devtools
  3. Press Ctrl+Shift+I (F12)
  4. The devtools pop up. Have fun!

Not working

EMail soraacg-killer@mail.cyans.me for help

用法

  1. 在您喜欢的用户脚本管理器中安装 soraacg-killer+default.user.js
  2. 打开那个检测开发者工具的站点
  3. 按下 Ctrl+Shift+I (F12)
  4. 弹出开发者工具! 页面不会返回或重定向

如果不起效果

Bypass 版 devtools-detector+bypass.user.js 只绕过不移除

如果有注入 控制台会输出一个签名

[xxx] context signuature ______

let ctx = document[context$_____] 下划线对应填入
即可使用 ctx.dispose() 以清除副作用

Update

v1.1

允许对所有网站进行屏蔽

// ==UserScript==
// @name Bypass devtools detector
// @version 2023-12-28
// @description try to make the detector silent
// @author CyanChanges<contact@cyans.me>
// @match *://*/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant GM_log
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
var doNotFilter = false
var doNotClear = true
let disposables = []
function dispose() {
disposables = disposables.splice(0).filter((dispose) => {
dispose()
})
}
const body = document.body
function lookFor(text) {return body.innerHTML.indexOf(text) !== -1}
if (!lookFor("disable-devtool") && !lookFor("disable-devtool-auto")) doNotFilter = true
if (doNotFilter) console.debug("bypass has been enabled")
const origLog = console.log
const origTable = console.table
const origClear = console.clear
function isConWith(obj, constructor) {
return Object.getPrototypeOf(obj)?.constructor === constructor
}
function sus(obj) {
const isDate = isConWith(obj, Date)
const isEmptyDiv = isConWith(obj, HTMLDivElement) && obj.innerHTML === ''
const isLarge = obj?.length && obj.length >= 10 && Object.keys(obj[0]??{}).length >= 200
const isSusFunction = isConWith(obj, Function) && obj.toString.toString().indexOf('native code') === -1
return !doNotFilter && (isSusFunction || isDate || isEmptyDiv || isLarge)
}
function addConsoleHooks() {
console.log = (o, ...args)=>{
if (sus(o)) return
origLog(o, ...args)
}
console.table = (o, ...args)=>{
if (sus(o)) return
origTable(o, ...args)
}
console.clear = (...args)=>{
if (!doNotClear) origClear(...args)
}
return ()=>{
console.clear = origClear
console.log = origLog
console.table = origTable
}
}
function randomChar() {
return btoa(String.fromCharCode.apply(null, window.crypto.getRandomValues(new Uint8Array(5))))
}
const sign = randomChar()
GM_log("[bypass] context signuature", sign)
Object.defineProperty(window.document, `context$${sign}`, {configurable: false, enumerable: false, value: new Proxy({
name: 'dd-bypass',
dispose,
sus, isConstructedWith: isConWith,
console: {...window.console, log: origLog, table: origTable, clear: origClear}
}, {})})
})();
// ==UserScript==
// @name Soraacg Killer
// @version 1.1+plus
// @description try to take over the disable-devtool
// @author CyanChanges<contact@cyans.me>
// @match *://*/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
let disposables = []
let rjs = null
let origDefine = undefined
let defineHook
function dispose() {
disposables = disposables.splice(0).filter((dispose) => {
dispose()
})
}
Object.defineProperty(window, 'DisableDevtool', {set(value) {throw "You can't use it disable devtools"}})
const detectorSig = 'function(){if(!(o.isSuspend||l||F())){var e,t,n=s($);try{for(n.s();!(e=n.n()).done;){var i=e.value;v(i.type),i.detect(G++)}}catch(e){n.e(e)}finally{n.f()}D(),"function"==typeof w.ondevtoolclose&&(t=d,!q()&&t&&w.ondevtoolclose())}}'
const keyBlockerSig = "function(e){var t=(e=e||n.event).keyCode||e.which;if(t===a||c(e,t)||l(e,t))return ne(n,e)}"
const realIntervaler = window.setInterval
const realAddListener = window.addEventListener
document.addEventListener('onload', function rollback(){ // Dispose side-effects after the disable-devtool has been removed
const body = document.body
function lookFor(text) {return body.innerHTML.indexOf(text) !== -1}
if (!lookFor('disable-devtool') && !lookFor('disable-devtool-auto')) dispose()
else {
setTimeout(dispose, 500)
}
if (!rollback.timed) {
rollback.timed = true
setTimeout(rollback, 200)
}
})
function addFuncHooks() {
window.setInterval = (...args)=>{
if (args[0].toString() == detectorSig) {
console.debug("Detector took down!")
window.setInterval = realIntervaler
return -1
}
return realIntervaler(...args)
}
window.addEventListener = (ev, handler)=>{
if (ev !== 'keydown') realAddListener(ev, handler)
if (handler.toString() == keyBlockerSig) {
console.debug("Key Listener took down!")
window.addEventListener = realAddListener
return
}
realAddListener(ev, handler)
}
return ()=>{
window.setInterval = realIntervaler
window.addEventListener = realAddListener
}
}
disposables.push(addFuncHooks())
function randomChar() {
return btoa(String.fromCharCode.apply(null, window.crypto.getRandomValues(new Uint8Array(5))))
}
const sign = randomChar()
console.log("[killer] context signuature", sign)
Object.defineProperty(window.document, `context${sign}`, {configurable: false, enumerable: false, value: new Proxy({
name: 'sorakiller',
dispose, signuatures: {code: codeSig, detector: detectorSig, listener: keyBlockerSig}
}, {})})
})();
// ==UserScript==
// @name Soraacg Killer
// @version 1.1+plus
// @description try to take over the disable-devtool
// @author CyanChanges<contact@cyans.me>
// @match *://*/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
const codeSig = "me()}function z(e){var t=h();return e(),h()-t}function B(n,i){function e(t){return function(){n&&n();var e=t.apply(void 0,arguments);return i&&i(),e}}var t=window.alert,o=window.confirm,r=window.prompt;try{window.alert=e(t),window.confirm=e(o),window.prompt=e(r)}catch(e){}}var p={iframe:!1,pc:!1,qqBrowser:!1,firefox:!1,macos:!1,edge:!1,oldEdge:!1,ie:!1,iosChrome:!1,iosEdge:!1,chrome:!1,seoBot:!1,m"
let disposables = []
let origDefine = undefined
let defineHook
function dispose() {
disposables = disposables.splice(0).filter((dispose) => {
dispose()
})
}
Object.defineProperty(window, 'DisableDevtool', {set(value) {throw "You can't use it disable devtools"}})
function addDefineHook(){
function removeDefineHook() {
if (!origDefine) delete window.define
else window.define = origDefine
}
console.debug("Killer[+] hook enabled!")
defineHook = window.define = (t, ...args)=>{
if (typeof t === 'function') {
if (t.toString().indexOf(codeSig) !== -1) {
console.debug("fake define caught")
var defineCaught = true
window.define = undefined
delete window.define
return
}
t()
}
return removeDefineHook
}
window.define.amd = true // Make sure disable-devtool use this mocked define
}
new MutationObserver((_, observer) => {
const { body } = document;
if (!body) return;
// Remove this observer, since it's not needed anymore; body exists
observer.disconnect();
function lookFor(text) {return body.innerHTML.indexOf(text) !== -1}
if (!lookFor("disable-devtool") && !lookFor("disable-devtool-auto")) dispose()
disposables.push(addDefineHook())
}).observe(document.documentElement, { childList: true });
const detectorSig = 'function(){if(!(o.isSuspend||l||F())){var e,t,n=s($);try{for(n.s();!(e=n.n()).done;){var i=e.value;v(i.type),i.detect(G++)}}catch(e){n.e(e)}finally{n.f()}D(),"function"==typeof w.ondevtoolclose&&(t=d,!q()&&t&&w.ondevtoolclose())}}'
const keyBlockerSig = "function(e){var t=(e=e||n.event).keyCode||e.which;if(t===a||c(e,t)||l(e,t))return ne(n,e)}"
const realIntervaler = window.setInterval
const realAddListener = window.addEventListener
document.addEventListener('onload', function rollback(){ // Dispose side-effects after the disable-devtool has been removed
const body = document.body
function lookFor(text) {return body.innerHTML.indexOf(text) !== -1}
if (!lookFor('disable-devtool') && !lookFor('disable-devtool-auto')) dispose()
else {
setTimeout(dispose, 500)
}
if (!rollback.timed) {
rollback.timed = true
setTimeout(rollback, 200)
}
})
function addFuncHooks() {
window.setInterval = (...args)=>{
if (args[0].toString() == detectorSig) {
console.debug("Detector took down!")
window.setInterval = realIntervaler
return -1
}
return realIntervaler(...args)
}
window.addEventListener = (ev, handler)=>{
if (ev !== 'keydown') realAddListener(ev, handler)
if (handler.toString() == keyBlockerSig) {
console.debug("Key Listener took down!")
window.addEventListener = realAddListener
return
}
realAddListener(ev, handler)
}
return ()=>{
window.setInterval = realIntervaler
window.addEventListener = realAddListener
}
}
disposables.push(addFuncHooks())
function randomChar() {
return btoa(String.fromCharCode.apply(null, window.crypto.getRandomValues(new Uint8Array(5))))
}
const sign = randomChar()
console.log("[killer] context signuature", sign)
Object.defineProperty(window.document, `context${sign}`, {configurable: false, enumerable: false, value: new Proxy({
name: 'sorakiller',
dispose, signuatures: {code: codeSig, detector: detectorSig, listener: keyBlockerSig}
}, {})})
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment