Ad bypass with deep hooks, stateful ad simulation & race condition handling
// ==UserScript==
// @name ZeroAd: CrazyGames
// @namespace https://greasyfork.org/users/YOUR_USER_ID
// @version 4.1.0
// @description Ad bypass with deep hooks, stateful ad simulation & race condition handling
// @author ZeroAd Team
// @match *://*.crazygames.com/*
// @match *://crazygames.com/*
// @grant none
// @run-at document-start
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Prevent double execution
if (window.__zeroAdInstalled) return;
window.__zeroAdInstalled = true;
// ═══════════════════════════════════════════════════════════════
// CONFIGURATION
// ═══════════════════════════════════════════════════════════════
const CONFIG = {
DEBUG: true,
REWARD_DELAY_MS: 10,
MAX_HOOK_ATTEMPTS: 100,
HOOK_RETRY_INTERVAL_MS: 200,
MUTATION_OBSERVER_ENABLED: true,
AD_PLAYING_DURATION_MS: 5 // how long isAdPlaying stays true (ms)
};
const log = (...args) => CONFIG.DEBUG && console.log('[ZeroAd]', ...args);
const warn = (...args) => CONFIG.DEBUG && console.warn('[ZeroAd]', ...args);
const hookState = {
crazyGamesSDK: false,
constructSDK: false,
crazygamesAds: false,
interceptedCalls: 0
};
// ═══════════════════════════════════════════════════════════════
// FAKE AD MODULE (stateful isAdPlaying)
// ═══════════════════════════════════════════════════════════════
function createFakeAdModule() {
let _adPlaying = false;
let _playingTimer = null;
// Dispatch common reward events
function dispatchRewardEvents() {
const events = [
'rewardedComplete', 'rewardGranted', 'adComplete',
'crazy_ad_finished', 'adReward', 'adFinished'
];
events.forEach(ev => {
try { window.dispatchEvent(new CustomEvent(ev)); } catch (e) {}
});
}
const module = {
get isAdPlaying() {
log(`isAdPlaying checked → ${_adPlaying}`);
return _adPlaying;
},
get requestInProgress() {
log('requestInProgress checked → false');
return false;
},
get hasAdblock() {
log('hasAdblock checked → false');
return false;
},
async prefetchAd(type) {
hookState.interceptedCalls++;
log(`✓ INTERCEPTED: prefetchAd("${type}")`);
return Promise.resolve();
},
async requestAd(type, callbacks = {}) {
hookState.interceptedCalls++;
log(`✓ INTERCEPTED: requestAd("${type}")`);
// Set ad playing state
_adPlaying = true;
if (_playingTimer) clearTimeout(_playingTimer);
_playingTimer = setTimeout(() => { _adPlaying = false; }, CONFIG.AD_PLAYING_DURATION_MS);
// adStarted callback
if (typeof callbacks.adStarted === 'function') {
try {
callbacks.adStarted();
log(' → adStarted() called');
} catch(e) {
warn('adStarted error:', e);
}
}
// Resolve after reward delay
return new Promise(resolve => {
setTimeout(() => {
_adPlaying = false;
if (_playingTimer) {
clearTimeout(_playingTimer);
_playingTimer = null;
}
if (typeof callbacks.adFinished === 'function') {
try {
callbacks.adFinished();
log(' → adFinished() called');
} catch(e) {
warn('adFinished error:', e);
}
}
dispatchRewardEvents();
log(` → ✅ Reward granted for "${type}"`);
resolve();
}, CONFIG.REWARD_DELAY_MS);
});
},
async hasAdblockEnabled() {
hookState.interceptedCalls++;
log('✓ INTERCEPTED: hasAdblockEnabled() → false');
return false;
},
addAdblockPopupListener() { log('addAdblockPopupListener (stub)'); },
removeAdblockPopupListener() { log('removeAdblockPopupListener (stub)'); }
};
return module;
}
// ═══════════════════════════════════════════════════════════════
// HOOK: CrazyGames.SDK.ad
// ═══════════════════════════════════════════════════════════════
function hookCrazyGamesSDK() {
if (hookState.crazyGamesSDK) return true;
try {
if (window.CrazyGames?.SDK) {
const fakeAd = createFakeAdModule();
Object.defineProperty(window.CrazyGames.SDK, 'ad', {
configurable: true,
enumerable: true,
get: () => {
log('SDK.ad accessed (getter)');
return fakeAd;
}
});
hookState.crazyGamesSDK = true;
log('✓✓ CrazyGames.SDK.ad HOOKED (existing)');
return true;
}
let _crazyGames = window.CrazyGames;
Object.defineProperty(window, 'CrazyGames', {
configurable: true,
enumerable: true,
get() { return _crazyGames; },
set(newValue) {
log('CrazyGames object assigned');
_crazyGames = newValue;
if (newValue?.SDK && !hookState.crazyGamesSDK) {
const fakeAd = createFakeAdModule();
Object.defineProperty(newValue.SDK, 'ad', {
configurable: true,
enumerable: true,
get: () => fakeAd
});
hookState.crazyGamesSDK = true;
log('✓✓ CrazyGames.SDK.ad HOOKED (deferred)');
}
}
});
log('✓ CrazyGames trap installed');
return false;
} catch (error) {
warn('Failed to hook CrazyGames.SDK:', error);
return false;
}
}
// ═══════════════════════════════════════════════════════════════
// HOOK: ConstructCrazySDK.ad
// ═══════════════════════════════════════════════════════════════
function hookConstructSDK() {
if (hookState.constructSDK) return true;
try {
if (window.ConstructCrazySDK) {
const fakeAd = createFakeAdModule();
Object.defineProperty(window.ConstructCrazySDK, 'ad', {
configurable: true,
enumerable: true,
get: () => fakeAd
});
hookState.constructSDK = true;
log('✓✓ ConstructCrazySDK.ad HOOKED (existing)');
return true;
}
let _construct = window.ConstructCrazySDK;
Object.defineProperty(window, 'ConstructCrazySDK', {
configurable: true,
enumerable: true,
get() { return _construct; },
set(newValue) {
log('ConstructCrazySDK object assigned');
_construct = newValue;
if (newValue && !hookState.constructSDK) {
const fakeAd = createFakeAdModule();
Object.defineProperty(newValue, 'ad', {
configurable: true,
enumerable: true,
get: () => fakeAd
});
hookState.constructSDK = true;
log('✓✓ ConstructCrazySDK.ad HOOKED (deferred)');
}
}
});
log('✓ ConstructCrazySDK trap installed');
return false;
} catch (error) {
warn('Failed to hook ConstructCrazySDK:', error);
return false;
}
}
// ═══════════════════════════════════════════════════════════════
// HOOK: CrazygamesAds (Proxy with improved adblock matching)
// ═══════════════════════════════════════════════════════════════
function hookCrazygamesAds() {
if (hookState.crazygamesAds) return true;
const AD_METHODS = [
'requestAd', 'requestAds', 'showAd', 'showRewardedAd',
'displayAd', 'displayRewardedAd', 'displayMidrollAd',
'requestRewardedAd', 'showRewardedVideo', 'requestRewardedVideo',
'showInterstitial', 'requestOnly', 'render', 'preloadAd'
];
function isAdMethod(prop) {
return AD_METHODS.includes(prop);
}
function isAdblockMethod(prop) {
// case-insensitive match for variations
const lower = prop.toLowerCase();
return lower === 'hasadblock' || lower === 'hasadblockenabled' || lower === 'isadblockactive';
}
function createAdsProxy(target) {
if (!target || target.__zaProxied) return target;
const handler = {
get(obj, prop) {
const original = obj[prop];
if (isAdMethod(prop) && typeof original === 'function') {
return function(...args) {
hookState.interceptedCalls++;
log(`✓ INTERCEPTED: CrazygamesAds.${prop}()`);
let onStarted = null;
let onFinished = null;
for (const arg of args) {
if (arg && typeof arg === 'object') {
onStarted = arg.adStarted || arg.onAdStarted || arg.onStart;
onFinished = arg.adFinished || arg.onAdFinished || arg.onComplete || arg.onReward;
}
}
if (typeof onStarted === 'function') {
try { onStarted(); } catch(e) { warn('onStarted error:', e); }
}
if (prop === 'requestOnly' || prop === 'preloadAd') {
return Promise.resolve({ success: true });
}
return new Promise(resolve => {
setTimeout(() => {
if (typeof onFinished === 'function') {
try { onFinished(); } catch(e) { warn('onFinished error:', e); }
}
// Dispatch events
const events = [
'rewardedComplete', 'adComplete', 'crazy_ad_finished'
];
events.forEach(ev => {
try { window.dispatchEvent(new CustomEvent(ev)); } catch(e) {}
});
resolve({ success: true, completed: true });
}, CONFIG.REWARD_DELAY_MS);
});
};
}
if (isAdblockMethod(prop) && typeof original === 'function') {
return async () => {
log(`✓ INTERCEPTED: CrazygamesAds.${prop}() → false`);
return false;
};
}
return original;
}
};
const proxied = new Proxy(target, handler);
proxied.__zaProxied = true;
return proxied;
}
try {
if (window.CrazygamesAds) {
window.CrazygamesAds = createAdsProxy(window.CrazygamesAds);
hookState.crazygamesAds = true;
log('✓✓ CrazygamesAds HOOKED (existing)');
return true;
}
let _ads = window.CrazygamesAds;
Object.defineProperty(window, 'CrazygamesAds', {
configurable: true,
enumerable: true,
get() { return _ads; },
set(newValue) {
log('CrazygamesAds object assigned');
_ads = newValue ? createAdsProxy(newValue) : newValue;
if (_ads && !hookState.crazygamesAds) {
hookState.crazygamesAds = true;
log('✓✓ CrazygamesAds HOOKED (deferred)');
}
}
});
log('✓ CrazygamesAds trap installed');
return false;
} catch (error) {
warn('Failed to hook CrazygamesAds:', error);
return false;
}
}
// ═══════════════════════════════════════════════════════════════
// ORCHESTRATION & RETRY LOGIC
// ═══════════════════════════════════════════════════════════════
let hookAttempts = 0;
let retryTimer = null;
let observer = null;
function allHooksInstalled() {
return hookState.crazyGamesSDK && hookState.constructSDK && hookState.crazygamesAds;
}
function attemptHooks() {
hookAttempts++;
hookCrazyGamesSDK();
hookConstructSDK();
hookCrazygamesAds();
if (allHooksInstalled()) {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
log('✅ ALL HOOKS INSTALLED SUCCESSFULLY');
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
cleanup();
return true;
}
if (hookAttempts >= CONFIG.MAX_HOOK_ATTEMPTS) {
warn('⚠️ Hook installation incomplete after max attempts');
warn('Hooked:', hookState);
cleanup();
return false;
}
return false;
}
function cleanup() {
if (retryTimer) {
clearInterval(retryTimer);
retryTimer = null;
}
if (observer) {
observer.disconnect();
observer = null;
log('✓ MutationObserver disconnected');
}
}
// ═══════════════════════════════════════════════════════════════
// MUTATION OBSERVER: Watch for SDK script injection
// ═══════════════════════════════════════════════════════════════
function setupMutationObserver() {
if (!CONFIG.MUTATION_OBSERVER_ENABLED) return;
observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.tagName === 'SCRIPT') {
const src = node.src || '';
if (src.includes('crazygames') || src.includes('sdk')) {
log(`Script detected: ${src.substring(0, 80)}...`);
node.addEventListener('load', () => {
log('SDK script loaded, re-attempting hooks');
setTimeout(attemptHooks, 50);
});
}
}
}
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
log('✓ MutationObserver watching for SDK scripts');
}
// ═══════════════════════════════════════════════════════════════
// INITIALIZATION
// ═══════════════════════════════════════════════════════════════
function initialize() {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
log('ZeroAd v4.1.0 - Fixed & Enhanced');
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
attemptHooks();
setupMutationObserver();
retryTimer = setInterval(() => {
if (!allHooksInstalled() && hookAttempts < CONFIG.MAX_HOOK_ATTEMPTS) {
attemptHooks();
log(`Hook attempt ${hookAttempts}/${CONFIG.MAX_HOOK_ATTEMPTS}`);
} else {
cleanup();
}
}, CONFIG.HOOK_RETRY_INTERVAL_MS);
setTimeout(() => {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
log('Status Report:');
log(' Hooks installed:', hookState);
log(' Intercepted calls:', hookState.interceptedCalls);
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
}, 5000);
}
// Run immediately
initialize();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attemptHooks);
}
})();