Greasy Fork is available in English.
Production-grade GameDistribution SDK bypass with comprehensive hooks
// ==UserScript==
// @name ZeroAd: GameDistribution
// @namespace https://greasyfork.org/users/zeroadv4
// @version 4.0.0
// @description Production-grade GameDistribution SDK bypass with comprehensive hooks
// @author ZeroAd Team
// @match *://*.gamedistribution.com/*
// @match *://gamedistribution.com/*
// @grant none
// @run-at document-start
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ═══════════════════════════════════════════════════════════════
// CONFIGURATION
// ═══════════════════════════════════════════════════════════════
const CONFIG = {
DEBUG: true,
REWARD_DELAY_MIN_MS: 10,
REWARD_DELAY_MAX_MS: 350,
MAX_RETRIES: 3,
RETRY_DELAYS: [50, 150, 450]
};
const METRICS = {
hooksInstalled: 0,
interceptedCalls: 0,
failedHooks: 0,
rewardsGranted: 0
};
// ═══════════════════════════════════════════════════════════════
// UTILITY LAYER
// ═══════════════════════════════════════════════════════════════
const log = (...args) => CONFIG.DEBUG && console.log('[ZeroAd:GameDist]', ...args);
const warn = (...args) => CONFIG.DEBUG && console.warn('[ZeroAd:GameDist]', ...args);
const error = (...args) => console.error('[ZeroAd:GameDist]', ...args);
function randomDelay(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function safeDispatchEvent(target, eventName) {
try {
target.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
} catch (e) {
warn('Event dispatch failed:', eventName, e);
}
}
function safeCallback(fn, ...args) {
if (typeof fn === 'function') {
try {
fn(...args);
} catch (e) {
warn('Callback execution failed:', e);
}
}
}
// ═══════════════════════════════════════════════════════════════
// HOOK LAYER
// ═══════════════════════════════════════════════════════════════
let hookState = {
GDSdk: false,
gdsdk: false,
gdApi: false
};
/**
* Hook GameDistribution SDK
* Targets: GDSdk, gdsdk, gdApi (all variants observed)
*/
function hookGDSdk(sdkName) {
const sdk = window[sdkName];
if (!sdk || sdk.__zaWrapped) {
return false;
}
try {
sdk.__zaWrapped = true;
// Hook showAd method
if (typeof sdk.showAd === 'function') {
const originalShowAd = sdk.showAd;
sdk.showAd = function(type, ...args) {
log(`${sdkName}.showAd("${type}") intercepted`);
METRICS.interceptedCalls++;
const isRewarded = type === 'rewarded' ||
type === 'reward' ||
type === 'rewardedVideo';
if (isRewarded) {
const delay = randomDelay(
CONFIG.REWARD_DELAY_MIN_MS,
CONFIG.REWARD_DELAY_MAX_MS
);
setTimeout(() => {
METRICS.rewardsGranted++;
safeDispatchEvent(window, 'rewardedComplete');
safeDispatchEvent(window, 'rewardGranted');
safeDispatchEvent(window, 'adComplete');
log(`✅ Reward granted (${delay}ms delay)`);
}, delay);
}
// Always resolve immediately
return Promise.resolve(true);
};
log(`✓ ${sdkName}.showAd hooked`);
}
// Hook requestAd (if exists)
if (typeof sdk.requestAd === 'function') {
const originalRequestAd = sdk.requestAd;
sdk.requestAd = function(type, ...args) {
log(`${sdkName}.requestAd("${type}") intercepted`);
METRICS.interceptedCalls++;
// Extract callbacks from various argument patterns
let callbacks = null;
for (const arg of args) {
if (arg && typeof arg === 'object') {
callbacks = arg;
break;
}
}
// Trigger callbacks immediately
if (callbacks) {
if (typeof callbacks.onStart === 'function') {
safeCallback(callbacks.onStart);
}
setTimeout(() => {
if (typeof callbacks.onComplete === 'function') {
safeCallback(callbacks.onComplete, true);
}
if (typeof callbacks.onReward === 'function') {
safeCallback(callbacks.onReward);
}
METRICS.rewardsGranted++;
safeDispatchEvent(window, 'rewardedComplete');
}, randomDelay(CONFIG.REWARD_DELAY_MIN_MS, CONFIG.REWARD_DELAY_MAX_MS));
}
return Promise.resolve({ success: true });
};
log(`✓ ${sdkName}.requestAd hooked`);
}
// Hook displayAd (if exists)
if (typeof sdk.displayAd === 'function') {
sdk.displayAd = function(type, ...args) {
log(`${sdkName}.displayAd("${type}") intercepted`);
METRICS.interceptedCalls++;
return Promise.resolve(true);
};
}
// Hook hasAdblock to always return false
if (typeof sdk.hasAdblock === 'function') {
sdk.hasAdblock = async function() {
log(`${sdkName}.hasAdblock() → false`);
return false;
};
}
// Hook play method (some games use this)
if (typeof sdk.play === 'function') {
const originalPlay = sdk.play;
sdk.play = function() {
log(`${sdkName}.play() called`);
try {
return originalPlay.apply(this, arguments);
} catch (e) {
return Promise.resolve();
}
};
}
hookState[sdkName] = true;
METRICS.hooksInstalled++;
return true;
} catch (e) {
error(`Failed to hook ${sdkName}:`, e);
METRICS.failedHooks++;
return false;
}
}
/**
* Attempt to hook all SDK variants
*/
function hookAllVariants() {
const variants = ['GDSdk', 'gdsdk', 'gdApi'];
let anyHooked = false;
variants.forEach(variant => {
if (window[variant] && !hookState[variant]) {
if (hookGDSdk(variant)) {
anyHooked = true;
}
}
});
return anyHooked;
}
/**
* Install property traps for late SDK initialization
*/
function installTraps() {
const variants = ['GDSdk', 'gdsdk', 'gdApi'];
variants.forEach(sdkName => {
let _sdk = window[sdkName];
Object.defineProperty(window, sdkName, {
configurable: true,
enumerable: true,
get() {
return _sdk;
},
set(newValue) {
log(`${sdkName} assigned`);
_sdk = newValue;
if (newValue && !hookState[sdkName]) {
hookGDSdk(sdkName);
}
}
});
});
log('✓ Property traps installed for all variants');
}
// ═══════════════════════════════════════════════════════════════
// ORCHESTRATION LAYER
// ═══════════════════════════════════════════════════════════════
let retryCount = 0;
function attemptHooks() {
const hooked = hookAllVariants();
if (hooked) {
log('✅ SDK hooked successfully');
return true;
}
if (retryCount < CONFIG.MAX_RETRIES) {
const delay = CONFIG.RETRY_DELAYS[retryCount];
retryCount++;
log(`Retry ${retryCount}/${CONFIG.MAX_RETRIES} in ${delay}ms`);
setTimeout(attemptHooks, delay);
} else {
log('⚠ Max retries reached. Traps remain active.');
}
return false;
}
/**
* Setup mutation observer for SDK script detection
*/
function setupMutationObserver() {
const 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('gamedistribution') || src.includes('gdsdk')) {
log('GD SDK script detected:', src.substring(0, 80));
node.addEventListener('load', () => {
log('SDK loaded, re-attempting hooks');
setTimeout(attemptHooks, 50);
});
}
}
}
}
});
if (document.documentElement) {
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
log('✓ MutationObserver active');
}
// ═══════════════════════════════════════════════════════════════
// INITIALIZATION
// ═══════════════════════════════════════════════════════════════
function initialize() {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
log('ZeroAd: GameDistribution v4.0.0');
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
installTraps();
attemptHooks();
setupMutationObserver();
// Expose metrics
window._zaMetrics = window._zaMetrics || {};
window._zaMetrics.gamedistribution = METRICS;
// Status report
setTimeout(() => {
log('━━━ Status Report ━━━');
log('Hook state:', hookState);
log('Metrics:', METRICS);
log('━━━━━━━━━━━━━━━━━━━━━');
}, 5000);
}
// Run immediately
initialize();
// Defensive: re-run on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attemptHooks);
}
})();