-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathinjection.html
137 lines (122 loc) · 6.12 KB
/
injection.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<script>
(function() {
if(window.disableCNNProxy) return;
window.disableCNNProxy = true; // prevent double wrapping
// Define necessary functions for wrappers later in the code
var domain = window.location.host.split('.').slice(-2).join('.');
function convertURL(url){
try{
var tempURL = url.replace(/^\/\//, 'https://');
var parsedURL = new URL(tempURL);
if(parsedURL.host.split('.').slice(-2).join('.') === domain){
return url;
}
}catch(e){
return url;
}
if(/^https?:\/\/|^\/\//i.test(url)){
return url.replace(/^(http:\/\/|https:\/\/|\/\/)([^\/:]*)(?::(\d+))?/ig,
function(match, protocolCap, bodyURLCap, optionPortCap){ // cap for capture
protocolCap = (protocolCap.toLowerCase()==='//'?window.location.protocol+'//':protocolCap);
return window.location.protocol+'//'+(protocolCap.toLowerCase()==='https://'?'s':'ns')+(optionPortCap ? optionPortCap : '')+'--'+bodyURLCap.replace(/-/g, '_-').replace(/\./g, '--')+'.'+domain;
});
}else if(/^wss?:\/\//i.test(url)){
return url.replace(/^ws(s):\/\/?([^\/:]*)(?::(\d+))?/ig,
function(match, protocolCap, bodyURLCap, optionPortCap){ // cap for capture
return (window.location.protocol === 'https:' ? 'wss:' : 'ws:')+'//'+(protocolCap.toLowerCase()==='s'?'s':'ns')+(optionPortCap ? optionPortCap : '')+'--'+bodyURLCap.replace(/-/g, '_-').replace(/\./g, '--')+'.'+domain;
});
}else{
return url;
}
}
function processElementAttributes(element){
if(element.nodeType !== Node.ELEMENT_NODE) return element;
for(var c = 0; c < element.attributes.length; c++){
element.setAttribute(element.attributes[c].name, convertURL(element.attributes[c].value));
}
return element;
}
// Websocket wrapper
var rWS = WebSocket;
WebSocket = function(url) {
return new(Function.prototype.bind.call(rWS, null, convertURL(url)));
};
// XMLHttpRequest wrapper
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(...args) {
args[1] = convertURL(args[1]);
origOpen.apply(this, args);
};
// fetch wrapper
if(fetch){ // if statement here for handling old browsers without fetch support
var originalFetch = fetch;
originalFetch = function(...args){
if(typeof args[0] === 'string' || args[0] instanceof String) args[0] = convertURL(args[0]);
return new(Function.prototype.bind.call(originalFetch, null, ...args));
};
}
// Request wrapper for fetch
if(Request){
var originalRequest = Request;
Request = function(...args){
args[0] = convertURL(args[0]);
return new(Function.prototype.bind.call(originalRequest, null, ...args));
};
}
// window.open wrapper
var origWinOpen = window.open;
window.open = function(...args){
if(args[0]) args[0] = convertURL(args[0]);
return origWinOpen(...args);
};
// window.postMessage wrapper
var origPostMessage = window.postMessage;
window.postMessage = function(...args){
if(args[1]) args[1] = convertURL(args[1]);
return origPostMessage(...args);
};
// frail attempt at wrapping window.parent.postMessage
// var origParentPostMessage = window.parent.postMessage;
// window.parent.postMessage = function(...args){
// console.log(args);
// if(args[1]) args[1] = convertURL(args[1]);
// return origParentPostMessage(...args);
// };
// The following wrapper is for handling html modifications
// Handles all appending elements. Only run this after the page has loaded... or else it would just... lag
window.addEventListener('load', function(){
var observer = new MutationObserver(function(mutationList){
for(var mutation of mutationList){
if(mutation.type === 'attributes'){
if(mutation.target.nodeType === Node.ELEMENT_NODE){
observer.disconnect(); // MUST DISCONNECT or else it will result in an infinite loop
mutation.target.setAttribute(mutation.attributeName, convertURL(mutation.target.getAttribute(mutation.attributeName)));
observeAgain();
}
}else if(mutation.type === 'childList'){
for(var eachNode of mutation.addedNodes){
observer.disconnect();
processElementAttributes(eachNode);
observeAgain();
}
}
}
});
function observeAgain(){observer.observe(document, {attributes: true, childList: true, subtree: true})}
observeAgain();
});
// The following is of no use since MutationObserver already handles all changes of the DOM
// Leaving this here for educational purposes
// appending functions wrapper
// var originalNodeAppend = Node.prototype.appendChild;
// var originalNodeInsertBefore = Node.prototype.insertBefore;
// Node.prototype.appendChild = function(...args){
// processElementAttributes(args[0]);
// return originalNodeAppend.apply(this, args);
// };
// Node.prototype.insertBefore = function(...args){
// processElementAttributes(args[0]);
// return originalNodeInsertBefore.apply(this, args);
// };
})();
</script>