Home > Software engineering >  Override JavaScript global native Object() constructor
Override JavaScript global native Object() constructor

Time:12-27

I'm trying to override Object() calls in JavaScript, in order to intercept and save all the parameters passed to the object constructor.

I don't have any access to the original code since I am running from an injected code but I do run from the same scope and share the same window of the original code.

I tried this approach:

(function (nativeObject) {
    window.Object = function (value) {
        if (value.magic) {
            window.myMagic = value.magic;
        }
        return nativeObject(value);
    }
})(Object);

as well as saving the original window.Object on window.nativeObject and calling it from within my hook, but in both ways I end up getting:

TypeError: Object.defineProperty is not a function
TypeError: Object.keys is not a function
Uncaught (in promise) TypeError: Object.isExtensible is not a function
Uncaught (in promise) TypeError: Object.create is not a function

Is it because my window.myMagic calls the the Object methods to set the myMagic key in the window object?

Is what I'm trying to do possible?

CodePudding user response:

I'm going to show how to replace the Object constructor with a proxy: we need to implement both the apply and construct traps for invocations of Object without or with new.

(nativeObject => {
    function Object(value) {
        if (value.magic) {
            globalThis.myMagic = value.magic;
        }
        return nativeObject(value);
    }
    globalThis.Object = new Proxy(nativeObject, {
        apply: (target, thisArg, args) => Object(...args),
        construct: (target, args) => Object(...args)
    });
})(Object);

// Test
new Object({ magic: 42 });
console.log(myMagic); // prints 42
Object({ magic: 'foo' });
console.log(myMagic); // prints "foo"
console.log(Object.getOwnPropertyNames(Object)); // prints an array of property names

Just note that this method will not work with any predefined functions, which may require different treatments for apply and construct. The Object function is a special case in that it behaves in the same way with or without new.

CodePudding user response:

You are replacing Object with a function that doesn't have any of the expected static methods on it. Calling Object.defineProperties no longer works, it's nativeObject.defineProperties that would be required.

You can however easily copy those properties from the native function onto your replacement function, to avoid breaking code that relies on them:

(function (nativeObject) {
    window.Object = function (value) {
        if (value.magic) {
            window.myMagic = value.magic;
        }
        return nativeObject(value);
    }
    for (const key of Reflect.ownKeys(nativeObject)) { // names and symbols
        const descriptor = nativeObject.getOwnPropertyDescriptor(nativeObject, key);
        nativeObject.defineProperty(Object, key, descriptor);
    }
})(Object);
  • Related