forked from Exaphis/mutube
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
152 lines (131 loc) · 4.65 KB
/
Copy pathmain.js
File metadata and controls
152 lines (131 loc) · 4.65 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
const MODULE = "YouTubeUnstable";
const base = Process.getModuleByName(MODULE).base;
function jsStringToNative(str) {
// convert a JavaScript string to a char* buffer
// make sure string is ASCII only so we don't have to deal with length issues related to UTF-8
const vals = [];
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i);
if (charCode < 0 || charCode > 255) {
throw new Error("Prefix contains non-ASCII character at index " + i);
}
vals.push(str.charCodeAt(i));
}
vals.push(0); // null terminator
const tmpBuf = Memory.alloc(vals.length);
tmpBuf.writeByteArray(vals);
return tmpBuf;
}
const libcpp = Process.getModuleByName('libc++.1.dylib');
const insertPtr = libcpp.findExportByName(
"_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKcm"
);
const insertFn = new NativeFunction(insertPtr, "pointer", [
"pointer", // std::string this
"ulong", // size_t pos
"pointer", // const char* s
"ulong", // size_t n
]);
function prepend(strPtr, prefix) {
const tmpBuf = jsStringToNative(prefix);
insertFn(strPtr, 0, tmpBuf, prefix.length);
}
function readStdString(str) {
// std::string layout:
// short strings just have the last byte as length, rest is for data
// long strings:
// 0x00: data pointer
// 0x08: length
// 0x0c: capacity (upper bit set to 1)
const capacity = str.add(16).readU64();
const topBit = capacity.shr(63);
if (topBit.toNumber() !== 0) {
// long string
const chars = str.readPointer();
const length = str.add(8).readU32();
const res = chars.readUtf8String(length);
return { length, capacity: capacity.xor(uint64(1).shl(63)), res };
} else {
// short string optimization
// length is just the upper byte
const length = capacity.shr(64 - 8);
const chars = str.readUtf8String(length);
return { length, capacity: length, res: chars };
}
}
// unused for now, but useful for debugging by modifying existing JS.
const replacePtr = libcpp.findExportByName(
"_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKc"
);
const replaceFn = new NativeFunction(replacePtr, "pointer", [
"pointer", // std::string this
"ulong", // size_t pos
"ulong", // size_t len
"pointer", // const char* s
]);
function replace(str, substr, newStr) {
// replace a substring in a std::string with a new string
// replaces the first occurrence of substr with newStr only
const strData = readStdString(str);
// find first occurrence of substr in strData.res
const index = strData.res.indexOf(substr);
if (index === -1) {
return false; // substring not found, nothing to replace
}
const tmpBuf = jsStringToNative(newStr);
replaceFn(
str,
index, // position to start replacing
substr.length, // length of the substring to replace
tmpBuf // new string to insert
);
return true;
}
// Add TizenTube script to the page. Don't inject more than once.
//
// Restore 4k support by hooking window.MediaSource.isTypeSupported to remove the height/width parameters.
// I am not actually sure why this works since isTypeSupported still returns false for VP09 codecs.
// YouTube does detect spoofing by checking nonsensical values for height/width so maybe that affects something?
// HDR still does not work, but at least 4k works now.
const injectedContent = `
(function () {
if (document.mutube) return;
document.mutube = true;
var script = document.createElement('script');
script.src = "https://cdn.jsdelivr.net/npm/@foxreis/tizentube/dist/userScript.js";
script.async = true;
document.head.appendChild(script);
const originalIsTypeSupported = window.MediaSource.isTypeSupported.bind(window.MediaSource);
window.MediaSource.isTypeSupported = function(mimeType) {
const parts = mimeType
.split(';')
.map(part => part.trim())
.filter(part => part);
const filtered = parts.filter(part => {
return !(part.startsWith('width=') || part.startsWith('height='));
});
const cleaned = filtered.join('; ');
return originalIsTypeSupported(cleaned);
};
})();
`;
// HTMLScriptElement::Execute
// https://cobalt.googlesource.com/cobalt/+/19.lts.1+/src/cobalt/dom/html_script_element.cc#593
Interceptor.attach(base.add(0xed5270), {
onEnter(args) {
const content = args[1];
if (readStdString(content).res.includes("yttv")) {
prepend(content, injectedContent);
}
},
});
// DirectiveList::AddDirective
// https://cobalt.googlesource.com/cobalt/+/19.lts.1+/src/cobalt/csp/directive_list.cc#834
Interceptor.attach(base.add(0x152d508), {
onEnter(args) {
prepend(
args[2],
"sponsorblock.inf.re sponsor.ajay.app dearrow-thumb.ajay.app cdn.jsdelivr.net "
);
},
});