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);