Ad bypass with singleton SDK instance, event, and Unity support
// ==UserScript==
// @name ZeroAd: CrazyGames SDK
// @namespace https://greasyfork.org/users/YOUR_USER_ID
// @version 4.4.1
// @description Ad bypass with singleton SDK instance, event, and Unity support
// @author ZeroAd Team
// @match *://*.crazygames.com/*
// @match *://crazygames.com/*
// @grant none
// @run-at document-start
// @license MIT
// ==/UserScript==
(function() {
'use strict';
if (window.__zeroAdInstalled) return;
window.__zeroAdInstalled = true;
const CONFIG = {
DEBUG: true,
REWARD_DELAY_MS: 500, // Half a second feels natural
MAX_HOOK_ATTEMPTS: 100,
HOOK_RETRY_INTERVAL_MS: 200,
AD_PLAYING_DURATION_MS: 5,
SIMULATE_AD_ERROR: false
};
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,
unityGameInstance: false,
genericCrazySDK: false,
crazySDKInstance: false,
interceptedCalls: 0
};
// Singleton fake instance (created once)
let fakeCrazySDKInstance = null;
// ═══════════════════════════════════════════════════════════════
// Fake CrazySDK Instance (singleton)
// ═══════════════════════════════════════════════════════════════
function createFakeCrazySDKInstance() {
const listeners = {};
let initCalled = false;
let requestInProgress = false;
function fireEvent(eventName, data = {}) {
if (listeners[eventName]) {
listeners[eventName].forEach(cb => {
try { cb(data); } catch (e) { warn(`Error in ${eventName} listener:`, e); }
});
}
}
return {
init() {
log('CrazySDK instance: init()');
initCalled = true;
setTimeout(() => {
fireEvent('initialized', {
userInfo: {
countryCode: "US",
browser: { name: "Chrome", version: "120" },
os: { name: "Windows", version: "10" },
device: { type: "desktop" }
}
});
}, 50);
},
addEventListener(event, callback) {
if (!listeners[event]) listeners[event] = [];
listeners[event].push(callback);
log(`CrazySDK instance: added listener for "${event}"`);
if (event === 'initialized' && initCalled) {
setTimeout(() => callback({
userInfo: {
countryCode: "US",
browser: { name: "Chrome", version: "120" },
os: { name: "Windows", version: "10" },
device: { type: "desktop" }
}
}), 10);
}
},
removeEventListener(event, callback) {
if (listeners[event]) {
listeners[event] = listeners[event].filter(cb => cb !== callback);
}
},
async requestAd(type = "midgame") {
hookState.interceptedCalls++;
log(`✓ INTERCEPTED: CrazySDK.requestAd("${type}")`);
if (CONFIG.SIMULATE_AD_ERROR) {
fireEvent('adError', { error: 'Simulated error' });
return;
}
requestInProgress = true;
fireEvent('adStarted', { adType: type });
log(' → adStarted fired');
return new Promise(resolve => {
setTimeout(() => {
requestInProgress = false;
fireEvent('adFinished', { adType: type });
log(' → adFinished fired');
log(` → ✅ Reward granted for "${type}"`);
resolve();
}, CONFIG.REWARD_DELAY_MS);
});
},
gameplayStart() { log('CrazySDK instance: gameplayStart() (stub)'); },
gameplayStop() { log('CrazySDK instance: gameplayStop() (stub)'); },
happytime() { log('CrazySDK instance: happytime() (stub)'); },
sdkGameLoadingStart() { log('CrazySDK instance: sdkGameLoadingStart() (stub)'); },
sdkGameLoadingStop() { log('CrazySDK instance: sdkGameLoadingStop() (stub)'); },
async requestBanner(containers) {
log('CrazySDK instance: requestBanner() (stub)', containers);
if (Array.isArray(containers)) {
containers.forEach(c => {
setTimeout(() => fireEvent('bannerRendered', { containerId: c.containerId }), 50);
});
}
},
async requestResponsiveBanner(containers) {
log('CrazySDK instance: requestResponsiveBanner() (stub)', containers);
if (Array.isArray(containers)) {
containers.forEach(c => {
setTimeout(() => fireEvent('bannerRendered', { containerId: c.id || c.containerId }), 50);
});
}
},
clearBanner(containerId) { log(`CrazySDK instance: clearBanner("${containerId}") (stub)`); },
clearAllBanners() { log('CrazySDK instance: clearAllBanners() (stub)'); },
get hasAdblock() { return false; },
adblockDetectionExecuted: true,
inviteLink(params = {}) {
log('CrazySDK instance: inviteLink() (stub)');
const baseUrl = window.location.href.split('?')[0];
const queryParams = new URLSearchParams(params);
return `${baseUrl}?czy_invite=true&utm_source=invite&${queryParams.toString()}`;
},
get requestInProgress() { return requestInProgress; },
set requestInProgress(val) { requestInProgress = val; }
};
}
// ═══════════════════════════════════════════════════════════════
// HOOK: CrazyGames.CrazySDK.getInstance() – SINGLETON FIX
// ═══════════════════════════════════════════════════════════════
function hookCrazySDKInstance() {
if (hookState.crazySDKInstance) return true;
// Create the singleton instance immediately
fakeCrazySDKInstance = createFakeCrazySDKInstance();
try {
if (window.CrazyGames?.CrazySDK?.getInstance) {
const originalGetInstance = window.CrazyGames.CrazySDK.getInstance;
window.CrazyGames.CrazySDK.getInstance = function() {
log('✓ INTERCEPTED: CrazyGames.CrazySDK.getInstance()');
return fakeCrazySDKInstance;
};
hookState.crazySDKInstance = true;
log('✓✓ CrazySDK.getInstance() HOOKED (existing singleton)');
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?.CrazySDK?.getInstance && !hookState.crazySDKInstance) {
const originalGetInstance = newValue.CrazySDK.getInstance;
newValue.CrazySDK.getInstance = function() {
log('✓ INTERCEPTED: CrazyGames.CrazySDK.getInstance() (deferred)');
return fakeCrazySDKInstance;
};
hookState.crazySDKInstance = true;
log('✓✓ CrazySDK.getInstance() HOOKED (deferred singleton)');
}
}
});
log('✓ CrazySDK.getInstance() singleton trap installed');
return false;
} catch (error) {
warn('Failed to hook CrazySDK.getInstance():', error);
return false;
}
}
// ═══════════════════════════════════════════════════════════════
// Legacy hooks (unchanged, kept for compatibility)
// ═══════════════════════════════════════════════════════════════
function createFakeAdModule() {
let _adPlaying = false;
let _playingTimer = null;
function dispatchRewardEvents() {
const events = [
'rewardedComplete', 'rewardGranted', 'adComplete',
'crazy_ad_finished', 'adReward', 'adFinished'
];
events.forEach(ev => {
try { window.dispatchEvent(new CustomEvent(ev)); } catch (e) {}
});
}
return {
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}")`);
_adPlaying = true;
if (_playingTimer) clearTimeout(_playingTimer);
_playingTimer = setTimeout(() => { _adPlaying = false; }, CONFIG.AD_PLAYING_DURATION_MS);
if (CONFIG.SIMULATE_AD_ERROR && typeof callbacks.adError === 'function') {
try { callbacks.adError({ code: 'INTERNAL_ERROR', message: 'Simulated error' }); log(' → adError() called'); } catch(e) {}
_adPlaying = false; clearTimeout(_playingTimer); return;
}
if (typeof callbacks.adStarted === 'function') { try { callbacks.adStarted(); log(' → adStarted() called'); } catch(e) {} }
return new Promise(resolve => {
setTimeout(() => {
_adPlaying = false; clearTimeout(_playingTimer);
if (typeof callbacks.adFinished === 'function') { try { callbacks.adFinished(); log(' → adFinished() called'); } catch(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)'); }
};
}
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: () => 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) { _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; }
}
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) { _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; }
}
function hookGenericCrazySDK() {
if (hookState.genericCrazySDK) return true;
const target = window.CrazySDK || window.crazysdk;
if (target) {
const fakeAd = createFakeAdModule();
if (target.ad) { Object.defineProperty(target, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); log('✓✓ CrazySDK.ad HOOKED'); }
if (target.Ad) { Object.defineProperty(target, 'Ad', { configurable: true, enumerable: true, get: () => fakeAd }); log('✓✓ CrazySDK.Ad HOOKED'); }
hookState.genericCrazySDK = true; return true;
}
['CrazySDK', 'crazysdk'].forEach(propName => {
if (hookState.genericCrazySDK) return;
let _val = window[propName];
Object.defineProperty(window, propName, {
configurable: true, enumerable: true, get() { return _val; },
set(newValue) { _val = newValue; if (newValue && !hookState.genericCrazySDK) { const fakeAd = createFakeAdModule(); if (newValue.ad) Object.defineProperty(newValue, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); if (newValue.Ad) Object.defineProperty(newValue, 'Ad', { configurable: true, enumerable: true, get: () => fakeAd }); hookState.genericCrazySDK = true; log(`✓✓ ${propName} HOOKED (deferred)`); } }
});
});
log('✓ Generic CrazySDK trap installed'); return false;
}
function hookUnitySendMessage() {
if (hookState.unityGameInstance) return true;
const candidates = Object.keys(window).filter(key => { try { const val = window[key]; return val && typeof val === 'object' && typeof val.SendMessage === 'function'; } catch(e) { return false; } });
for (const key of candidates) {
const instance = window[key]; if (instance.__zaHooked) continue;
const originalSend = instance.SendMessage;
instance.SendMessage = function(gameObject, method, param) {
if (method === 'AdEvent' && (param === 'adStarted' || param === 'adFinished' || param === 'adError')) { log(`✓ INTERCEPTED: Unity SendMessage`); hookState.interceptedCalls++; if (param === 'adStarted') { setTimeout(() => { try { originalSend.call(this, gameObject, method, 'adFinished'); } catch(e) {} }, CONFIG.REWARD_DELAY_MS); } return; }
return originalSend.apply(this, arguments);
};
instance.__zaHooked = true; hookState.unityGameInstance = true; log(`✓✓ Unity SendMessage HOOKED`); return true;
}
return false;
}
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) {
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, 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); } }
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
// ═══════════════════════════════════════════════════════════════
let hookAttempts = 0;
let retryTimer = null;
let observer = null;
function allHooksInstalled() {
return hookState.crazySDKInstance ||
(hookState.crazyGamesSDK && hookState.constructSDK && hookState.crazygamesAds &&
hookState.genericCrazySDK && hookState.unityGameInstance);
}
function attemptHooks() {
hookAttempts++;
// NEW: Primary hook for the event-listener pattern
hookCrazySDKInstance();
// Legacy hooks
hookCrazyGamesSDK();
hookConstructSDK();
hookCrazygamesAds();
hookGenericCrazySDK();
hookUnitySendMessage();
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'); }
}
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');
}
function initialize() {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
log('ZeroAd v4.4.0 - Full CrazySDK Instance & Event Support');
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);
}
initialize();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attemptHooks);
}
})();