Skip to content

Instantly share code, notes, and snippets.

@alpgul
Last active May 5, 2025 08:06
Show Gist options
  • Save alpgul/3981930582e282663f0d0632b29b7817 to your computer and use it in GitHub Desktop.
Save alpgul/3981930582e282663f0d0632b29b7817 to your computer and use it in GitHub Desktop.
JavaScript patch script to modify native functions and console methods for enhanced error handling and method remapping. Includes functionality to preserve original implementations and dynamically convert functions to shorthand syntax.
(function () {
'use strict';
/**
* Stores original versions of native functions before patching.
* @type {Map<string, Function>}
* @description Map structure:
* - Key: Original method's name property (e.g., 'log', 'error')
* - Value: Original native function implementation
*/
const savedOriginalMethods = new Map();
/**
* Stores the string conversion of the modified local function together with the original local function.
* @type {Map<string, Function>}
* @description Map structure:
* - Key: String conversion of the modified native function
* - Value: Original native function implementation
*/
const methodRemapDictionary = new Map();
/**
* Converts a function to shorthand method syntax while preserving closure variables
* @param {Function} functionToConvert - Function to convert to shorthand method syntax
* @param {string} functionName - Name to use for the method property
* @returns {Function} Generated function with access to closure variables
* @description
* 1. Extracts function body by removing 'function' declaration
* 2. Creates new method-style function using dynamic evaluation
* 3. Injects closure references (savedOriginalMethods, methodRemapDictionary)
* through immediately-invoked arguments
*/
function convertFunctionToShorthand(standardFunction, functionName) {
const functionBody = standardFunction.toString().replace(new RegExp(`^function([^\\(]*)`), '')
const shorthandFunction = new Function(
`const [savedOriginalMethods, methodRemapDictionary, name]=arguments;return {
${functionName}${functionBody}
}.${functionName};`
)(savedOriginalMethods, methodRemapDictionary, functionName);
return shorthandFunction;
}
/**
* Replaces a native function with a modified proxy function
* @param {string} name - The name of the native function to be modified
* @param {Function} nativeFunction - The original native function implementation
* @param {Function} modifyFunction - The function to modify the native function
* @returns {Function} The shorthand function that replaces the native function
* @description This function stores the original native function in a map,
* converts the modifying function to a shorthand method,
* and returns a shorthand function that maintains a reference
* to the original implementation.
*/
function modifyNativeFunction(name, nativeFunction, modifyFunction) {
methodRemapDictionary.set(name, nativeFunction);
const shorthandModifyFunction = convertFunctionToShorthand(modifyFunction, name);
savedOriginalMethods.set(methodRemapDictionary.get('toString').call(shorthandModifyFunction), nativeFunction);
return shorthandModifyFunction;
}
/**
* A function that handles toString operations with method remapping support.
* It attempts to apply toString on the original method if available in the savedOriginalMethods map.
* If an error occurs, it modifies the error stack trace by removing the third line before rethrowing.
*
* @function toString
* @param {...*} args - Arguments to be passed to the toString method
* @returns {string} The string representation of the object
* @throws {Error} Rethrows any error that occurs during execution with modified stack trace
*/
const toString = function (...args) {
try {
const ret = Reflect.apply(methodRemapDictionary.get("toString"), this, args);
if (savedOriginalMethods.has(ret)) {
return Reflect.apply(methodRemapDictionary.get("toString"), savedOriginalMethods.get(ret), args);
}
return ret;
} catch (error) {
const stackArray = error.stack.split('\n');
stackArray.splice(2, 1);
const modifiedStack = stackArray.join('\n');
error.stack = modifiedStack;
throw error;
}
};
Function.prototype.toString = modifyNativeFunction('toString', Function.prototype.toString, toString);
/**
* Patches console methods to intercept and handle potential errors during argument access.
*
* Iterates through a list of console methods (log, error, info, warn, trace, dir, debug, dirxml, table ...)
* and replaces each with a modified version. The modified version attempts to access specific properties
* of each argument passed to the console method (toString, name, message). If any error occurs during
* this access, the error's stack trace is modified by removing the third line before re-throwing.
* The original console methods are stored and used for the actual logging.
*/
const consoleMethods = ['log','error','info','warn','trace','dir','debug','dirxml','table'];
for (const name of consoleMethods) {
const fn = function (...args) {
try {
for (const arg of args) {
const descriptors=Object.getOwnPropertyDescriptors(arg);
if(arg?.hasOwnProperty('toString')){
arg.toString();
}
if(descriptors?.name?.get){
descriptors?.name?.get();
}
if(descriptors?.message?.get){
descriptors?.message?.get();
}
}
//Reflect.apply(orginalMethodsMap.get(name), this, args);
} catch (error) {
const stackArray = error.stack.split('\n');
stackArray.splice(2, 1);
const modifiedStack = stackArray.join('\n');
error.stack = modifiedStack;
throw error;
}
};
console[name] = modifyNativeFunction(name, console[name], fn);
}
})();

Native Function and Console Method Patcher

This script is a utility for patching native JavaScript functions and console methods. It enhances error handling, enables method remapping, and preserves the original implementations of the patched functions. Additionally, it modifies stack traces to obscure the presence of the modifications, preventing detection of the patch.

Features

  • Native Function Modification: Replace native functions with custom implementations while preserving the original versions.
  • Shorthand Method Conversion: Dynamically convert standard functions into shorthand method syntax, maintaining access to closure variables.
  • Stack Trace Obfuscation: Modifies stack traces to hide the presence of modifications, preventing detection of the patch.
  • Console Method Patching: Intercept console methods (e.g., log, error, warn) to handle potential errors during argument access.

How It Works

1. Original Method Preservation

The script stores the original implementations of native functions in a Map before patching them. This ensures that the original behavior can be restored or referenced if needed.

2. Shorthand Method Conversion

Functions are dynamically converted to shorthand syntax using Function constructors. Closure variables are injected to maintain references to the original methods and remapping dictionary.

3. Stack Trace Obfuscation

Stack traces are modified to remove specific lines that could reveal the presence of the patch. This ensures that the modifications remain undetectable during debugging or error handling.

4. Console Method Patching

Common console methods (e.g., log, error, infowarntracedirdebugdirxmltable) are replaced with modified versions. These versions attempt to access specific properties of arguments (e.g., toString, name, message) and handle any errors that occur during this process.

Patched Console Methods

The following console methods are patched by the script:

  • log
  • error
  • info
  • warn
  • trace
  • dir
  • debug
  • dirxml
  • table

Example Usage

The script is self-contained and automatically patches the relevant functions and methods when executed. Simply include it in your project to enable the enhanced functionality.

// Include the script in your project

// The script will automatically patch native functions and console methods

Notes

  • The script uses Reflect.apply to invoke original methods, ensuring compatibility with the native behavior.
  • Stack trace modifications are specifically designed to obscure the presence of the patch, preventing detection.

Disclaimer

This script modifies native JavaScript behavior, which may have unintended side effects in certain environments. Use with caution and test thoroughly in your application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment