From 284dd9fc795c992d9259ba4c99edd41c125abc9b Mon Sep 17 00:00:00 2001 From: Hannah Date: Tue, 14 May 2024 06:30:30 -0400 Subject: [PATCH] code cleanup, kinda --- README.md | 7 ++-- xhr-x.js | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ xhrx.js | 50 ----------------------- 3 files changed, 119 insertions(+), 54 deletions(-) create mode 100644 xhr-x.js delete mode 100644 xhrx.js diff --git a/README.md b/README.md index eb0f6c5..7747661 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # XHR eXtensions -Prototype modifications that enable manipulating and listening to XmlHttpRequests throughout their life-cycle. +Prototype modifications enabling manipulation and snooping of XMLHttpRequests. ## Why? -Its primary purpose is for reverse engineering. \ -Used in some of my own projects. +To aid in personal reverse engineering projects. - [winnpixie/socialrip](https://github.com/winnpixie/socialrip) -- [winnpixie/anypin](https://github.com/winnpixie/anypin) (now defunct) \ No newline at end of file +- [winnpixie/anypin](https://github.com/winnpixie/anypin) \ No newline at end of file diff --git a/xhr-x.js b/xhr-x.js new file mode 100644 index 0000000..6fdfed5 --- /dev/null +++ b/xhr-x.js @@ -0,0 +1,116 @@ +(function () { + 'use strict'; + + // BEGIN Event declarations + class XHREvent { + constructor(context) { + this.context = context; + + this.cancelled = false; + } + } + + class XHROpenEvent extends XHREvent { + constructor(context, state) { + super(context); + + this.state = state; + } + } + + class XHRHeaderSetEvent extends XHREvent { + constructor(context, key, value) { + super(context); + + this.key = key; + this.value = value; + } + } + + class XHRSendEvent extends XHREvent { + constructor(context, state) { + super(context); + + this.state = state; + } + } + + class XHRFinishedEvent extends XHREvent { + constructor(context) { + super(context); + } + } + // END Event declarations + + const XHRExt = { + openHandlers: [], + headerSetHandlers: [], + sendHandlers: [], + finishHandlers: [] + }; + window.XHRExt = XHRExt; + + // BEGIN Prototype hacking + const xhr_open = XMLHttpRequest.prototype.open; + XMLHttpRequest.prototype.open = function () { + this.xMethod = arguments[0]; + this.xUrl = arguments[1]; + this.xAsync = arguments[2] || false; + this.xUsername = arguments[3]; + this.xPassword = arguments[4]; + + let xhrEvent = new XHROpenEvent(this, "before"); + XHRExt.openHandlers.forEach(handler => handler.call(null, xhrEvent)); + if (xhrEvent.cancelled) return; + + arguments[0] = this.xMethod; + arguments[1] = this.xUrl; + arguments[2] = this.xAsync; + arguments[3] = this.xUsername; + arguments[4] = this.xPassword; + + xhr_open.apply(this, arguments); + XHRExt.openHandlers.forEach(handler => handler.call(null, new XHROpenEvent(this, "after"))); + }; + + const xhr_setRequestHeader = XMLHttpRequest.prototype.setRequestHeader; + XMLHttpRequest.prototype.setRequestHeader = function () { + if (this.xHeaders == null) this.xHeaders = []; + + this.xHeaders[arguments[0]] = arguments[1]; + + let xhrEvent = new XHRHeaderSetEvent(this, arguments[0], arguments[1]); + XHRExt.headerSetHandlers.forEach(handler => handler.call(null, xhrEvent)); + if (xhrEvent.cancelled) return; + + this.xHeaders[xhrEvent.key] = xhrEvent.value; + arguments[0] = xhrEvent.key; + arguments[1] = xhrEvent.value; + + xhr_setRequestHeader.apply(this, arguments); + }; + + const xhr_send = XMLHttpRequest.prototype.send; + XMLHttpRequest.prototype.send = function () { + this.xBody = arguments[0]; + + let xhrEvent = new XHRSendEvent(this, "before"); + XHRExt.sendHandlers.forEach(handler => handler.call(null, xhrEvent)); + if (xhrEvent.cancelled) return; + + arguments[0] = this.xBody; + + const xhr_onreadystatechange = this.onreadystatechange; + this.onreadystatechange = function () { + if (this.readyState === XMLHttpRequest.DONE) { + XHRExt.finishHandlers.forEach(handler => handler.call(null, new XHRFinishedEvent(this))); + } + + if (xhr_onreadystatechange != null) xhr_onreadystatechange.apply(this, arguments); + }; + + xhr_send.apply(this, arguments); + XHRExt.sendHandlers.forEach(handler => handler.call(null, new XHRSendEvent(this, "after"))); + }; + // END Prototype hacking +})(); \ No newline at end of file diff --git a/xhrx.js b/xhrx.js deleted file mode 100644 index acfb551..0000000 --- a/xhrx.js +++ /dev/null @@ -1,50 +0,0 @@ -(function () { - 'use strict'; - - window.XHRX = { - onBeforeOpen: [], - onAfterOpen: [], - onBeforeSend: [], - onAfterSend: [], - onCompleted: [] - }; - - const xhr_open = XMLHttpRequest.prototype.open; - XMLHttpRequest.prototype.open = function () { - this.xMethod = arguments[0]; - this.xUrl = arguments[1]; - window.XHRX.onBeforeOpen.forEach(action => action(this)); - arguments[0] = this.xMethod; - arguments[1] = this.xUrl; - - xhr_open.apply(this, arguments); - window.XHRX.onAfterOpen.forEach(action => action(this)); - }; - - const xhr_setRequestHeader = XMLHttpRequest.prototype.setRequestHeader; - XMLHttpRequest.prototype.setRequestHeader = function () { - if (this.xHeaders == null) this.xHeaders = []; - - this.xHeaders[arguments[0]] = arguments[1]; - xhr_setRequestHeader.apply(this, arguments); - }; - - const xhr_send = XMLHttpRequest.prototype.send; - XMLHttpRequest.prototype.send = function () { - this.xBody = arguments[0]; - window.XHRX.onBeforeSend.forEach(action => action(this)); - arguments[0] = this.xBody; - - const xhr_onreadystatechange = this.onreadystatechange; - this.onreadystatechange = function () { - if (this.readyState === XMLHttpRequest.DONE) { - window.XHRX.onCompleted.forEach(action => action(this)); - } - - if (xhr_onreadystatechange != null) xhr_onreadystatechange.apply(this, arguments); - }; - - xhr_send.apply(this, arguments); - window.XHRX.onAfterSend.forEach(action => action(this)); - }; -})(); \ No newline at end of file