skull emoji

This commit is contained in:
velzie 2024-10-28 19:42:34 -04:00
parent 85aa136fe0
commit e0a16f1c60
No known key found for this signature in database
GPG key ID: AA51AEFB0A1F3820
13 changed files with 153 additions and 92 deletions

View file

@ -139,6 +139,7 @@ fn create_rewriter_output(
#[wasm_bindgen] #[wasm_bindgen]
pub fn rewrite_js( pub fn rewrite_js(
js: String, js: String,
module: bool,
url: &str, url: &str,
script_url: String, script_url: String,
scramjet: &Object, scramjet: &Object,
@ -149,7 +150,7 @@ pub fn rewrite_js(
} }
let before = Instant::now(); let before = Instant::now();
let out = rewrite(&js, Url::from_str(url)?, get_config(scramjet, url)?)?; let out = rewrite(&js, module, Url::from_str(url)?, get_config(scramjet, url)?)?;
let after = Instant::now(); let after = Instant::now();
create_rewriter_output(out, script_url, js, after - before) create_rewriter_output(out, script_url, js, after - before)
@ -158,6 +159,7 @@ pub fn rewrite_js(
#[wasm_bindgen] #[wasm_bindgen]
pub fn rewrite_js_from_arraybuffer( pub fn rewrite_js_from_arraybuffer(
js: Vec<u8>, js: Vec<u8>,
module: bool,
url: &str, url: &str,
script_url: String, script_url: String,
scramjet: &Object, scramjet: &Object,
@ -171,7 +173,7 @@ pub fn rewrite_js_from_arraybuffer(
let js = unsafe { String::from_utf8_unchecked(js) }; let js = unsafe { String::from_utf8_unchecked(js) };
let before = Instant::now(); let before = Instant::now();
let out = rewrite(&js, Url::from_str(url)?, get_config(scramjet, url)?)?; let out = rewrite(&js, module, Url::from_str(url)?, get_config(scramjet, url)?)?;
let after = Instant::now(); let after = Instant::now();
create_rewriter_output(out, script_url, js, after - before) create_rewriter_output(out, script_url, js, after - before)

View file

@ -113,6 +113,7 @@ fn dorewrite(source_text: &str) -> Result<String> {
Ok(from_utf8( Ok(from_utf8(
rewrite( rewrite(
source_text, source_text,
false,
Url::from_str("https://google.com/glorngle/si.js").unwrap(), Url::from_str("https://google.com/glorngle/si.js").unwrap(),
Config { Config {
prefix: "/scrammedjet/".to_string(), prefix: "/scrammedjet/".to_string(),

View file

@ -5,6 +5,7 @@ use oxc_allocator::Allocator;
use oxc_ast::{ use oxc_ast::{
ast::{ ast::{
AssignmentTarget, Expression, IdentifierReference, MemberExpression, ObjectPropertyKind, AssignmentTarget, Expression, IdentifierReference, MemberExpression, ObjectPropertyKind,
Statement, VariableDeclaration,
}, },
visit::walk, visit::walk,
Visit, Visit,
@ -65,7 +66,7 @@ impl Rewriter {
let urlencoded = (self.config.encode)(url.to_string()); let urlencoded = (self.config.encode)(url.to_string());
format!("\"{}{}\"", self.config.prefix, urlencoded) format!("\"{}{}?type=module\"", self.config.prefix, urlencoded)
} }
fn rewrite_ident(&mut self, name: &Atom, span: Span) { fn rewrite_ident(&mut self, name: &Atom, span: Span) {
@ -106,20 +107,23 @@ impl<'a> Visit<'a> for Rewriter {
// ), // ),
// }); // });
// } else { // } else {
if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) { // if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) {
self.jschanges.push(JsChange::GenericChange { // self.jschanges.push(JsChange::GenericChange {
span: it.span, // span: it.span,
text: format!("{}({})", self.config.wrapfn, it.name), // text: format!("{}({})", self.config.wrapfn, it.name),
}); // });
} // }
// } // }
} }
// fn visit_program(&mut self, it: &oxc_ast::ast::Program<'a>) {
// it.directives[0].
// }
// we need to rewrite `new Something` to `new (wrapfn(Something))` instead of `new wrapfn(Something)`, that's why there's weird extra code here // we need to rewrite `new Something` to `new (wrapfn(Something))` instead of `new wrapfn(Something)`, that's why there's weird extra code here
fn visit_new_expression(&mut self, it: &oxc_ast::ast::NewExpression<'a>) { // fn visit_new_expression(&mut self, it: &oxc_ast::ast::NewExpression<'a>) {
self.walk_member_expression(&it.callee); // // self.walk_member_expression(&it.callee);
walk::walk_arguments(self, &it.arguments); // walk::walk_arguments(self, &it.arguments);
} // }
fn visit_member_expression(&mut self, it: &oxc_ast::ast::MemberExpression<'a>) { fn visit_member_expression(&mut self, it: &oxc_ast::ast::MemberExpression<'a>) {
match it { match it {
MemberExpression::StaticMemberExpression(s) => { MemberExpression::StaticMemberExpression(s) => {
@ -133,18 +137,6 @@ impl<'a> Visit<'a> for Rewriter {
return; // unwise to walk the rest of the tree return; // unwise to walk the rest of the tree
} }
if !self.config.strict_rewrites
&& !UNSAFE_GLOBALS.contains(&s.property.name.as_str())
{
if let Expression::Identifier(_) = &s.object {
// cull tree - this should be safe
return;
}
if let Expression::ThisExpression(_) = &s.object {
return;
}
}
if self.config.scramitize if self.config.scramitize
&& !matches!(s.object, Expression::MetaProperty(_)) && !matches!(s.object, Expression::MetaProperty(_))
&& !matches!(s.object, Expression::Super(_)) && !matches!(s.object, Expression::Super(_))
@ -170,12 +162,12 @@ impl<'a> Visit<'a> for Rewriter {
walk::walk_member_expression(self, it); walk::walk_member_expression(self, it);
} }
fn visit_this_expression(&mut self, it: &oxc_ast::ast::ThisExpression) { // fn visit_this_expression(&mut self, it: &oxc_ast::ast::ThisExpression) {
self.jschanges.push(JsChange::GenericChange { // self.jschanges.push(JsChange::GenericChange {
span: it.span, // span: it.span,
text: format!("{}(this)", self.config.wrapthisfn), // text: format!("{}(this)", self.config.wrapthisfn),
}); // });
} // }
fn visit_debugger_statement(&mut self, it: &oxc_ast::ast::DebuggerStatement) { fn visit_debugger_statement(&mut self, it: &oxc_ast::ast::DebuggerStatement) {
// delete debugger statements entirely. some sites will spam debugger as an anti-debugging measure, and we don't want that! // delete debugger statements entirely. some sites will spam debugger as an anti-debugging measure, and we don't want that!
@ -276,28 +268,28 @@ impl<'a> Visit<'a> for Rewriter {
walk::walk_try_statement(self, it); walk::walk_try_statement(self, it);
} }
fn visit_object_expression(&mut self, it: &oxc_ast::ast::ObjectExpression<'a>) { // fn visit_object_expression(&mut self, it: &oxc_ast::ast::ObjectExpression<'a>) {
for prop in &it.properties { // for prop in &it.properties {
#[allow(clippy::single_match)] // #[allow(clippy::single_match)]
match prop { // match prop {
ObjectPropertyKind::ObjectProperty(p) => match &p.value { // ObjectPropertyKind::ObjectProperty(p) => match &p.value {
Expression::Identifier(s) => { // Expression::Identifier(s) => {
if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) && p.shorthand { // if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) && p.shorthand {
self.jschanges.push(JsChange::GenericChange { // self.jschanges.push(JsChange::GenericChange {
span: s.span, // span: s.span,
text: format!("{}: ({}({}))", s.name, self.config.wrapfn, s.name), // text: format!("{}: ({}({}))", s.name, self.config.wrapfn, s.name),
}); // });
return; // return;
} // }
} // }
_ => {} // _ => {}
}, // },
_ => {} // _ => {}
} // }
} // }
//
walk::walk_object_expression(self, it); // walk::walk_object_expression(self, it);
} // }
fn visit_function_body(&mut self, it: &oxc_ast::ast::FunctionBody<'a>) { fn visit_function_body(&mut self, it: &oxc_ast::ast::FunctionBody<'a>) {
// tag function for use in sourcemaps // tag function for use in sourcemaps
@ -411,7 +403,12 @@ fn random_string() -> String {
.to_string() .to_string()
} }
pub fn rewrite(js: &str, url: Url, config: Config) -> Result<(Vec<u8>, Vec<OxcDiagnostic>)> { pub fn rewrite(
js: &str,
module: bool,
url: Url,
config: Config,
) -> Result<(Vec<u8>, Vec<OxcDiagnostic>)> {
let allocator = Allocator::default(); let allocator = Allocator::default();
let source_type = SourceType::default(); let source_type = SourceType::default();
let ret = Parser::new(&allocator, js, source_type).parse(); let ret = Parser::new(&allocator, js, source_type).parse();
@ -426,8 +423,29 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Result<(Vec<u8>, Vec<OxcDi
config, config,
}; };
// dbg!(&program);
ast_pass.visit_program(&program); ast_pass.visit_program(&program);
if !module {
for s in &program.body {
if let Statement::VariableDeclaration(it) = s {
if !it.kind.is_var() {
continue;
}
ast_pass.jschanges.push(JsChange::GenericChange {
span: Span::new(it.span.start, it.declarations[0].span.start),
text: String::new(),
});
for d in &it.declarations {
ast_pass.jschanges.push(JsChange::GenericChange {
span: Span::new(d.id.span().start, d.id.span().start),
text: "fakeVars.".to_string(),
});
}
}
}
}
// sorrt changse // sorrt changse
ast_pass.jschanges.sort_by(|a, b| { ast_pass.jschanges.sort_by(|a, b| {
let a = match a { let a = match a {

View file

@ -202,7 +202,7 @@ export default function (client: ScramjetClient, self: typeof window) {
set(ctx, value: string) { set(ctx, value: string) {
let newval; let newval;
if (ctx.this instanceof self.HTMLScriptElement) { if (ctx.this instanceof self.HTMLScriptElement) {
newval = rewriteJs(value, client.meta); newval = rewriteJs(value, false, client.meta);
} else if (ctx.this instanceof self.HTMLStyleElement) { } else if (ctx.this instanceof self.HTMLStyleElement) {
newval = rewriteCss(value, client.meta); newval = rewriteCss(value, client.meta);
} else { } else {

View file

@ -8,7 +8,7 @@ export default function (client: ScramjetClient, self: Self) {
value: function (js: any) { value: function (js: any) {
if (typeof js !== "string") return js; if (typeof js !== "string") return js;
const rewritten = rewriteJs(js, client.meta); const rewritten = rewriteJs(js, false, client.meta);
return rewritten; return rewritten;
}, },
@ -23,5 +23,5 @@ export function indirectEval(this: ScramjetClient, js: any) {
const indirection = this.global.eval; const indirection = this.global.eval;
return indirection(rewriteJs(js, this.meta) as string); return indirection(rewriteJs(js, false, this.meta) as string);
} }

View file

@ -4,7 +4,11 @@ import { rewriteJs } from "../../shared";
function rewriteFunction(ctx: ProxyCtx, client: ScramjetClient) { function rewriteFunction(ctx: ProxyCtx, client: ScramjetClient) {
const stringifiedFunction = ctx.call().toString(); const stringifiedFunction = ctx.call().toString();
const content = rewriteJs(`return ${stringifiedFunction}`, client.meta); const content = rewriteJs(
`return ${stringifiedFunction}`,
false,
client.meta
);
ctx.return(ctx.fn(content)()); ctx.return(ctx.fn(content)());
} }

View file

@ -10,7 +10,7 @@ export default function (client: ScramjetClient, self: Self) {
const resolved = new URL(url, base).href; const resolved = new URL(url, base).href;
return Function( return Function(
`return import("${rewriteUrl(resolved, client.meta)}")` `return import("${rewriteUrl(resolved, client.meta)}?type=module")`
)(); )();
}; };
}; };

View file

@ -55,6 +55,21 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
writable: false, writable: false,
configurable: false, configurable: false,
}); });
Object.defineProperty(self, "fakeVars", {
writable: false,
configurable: false,
value: new Proxy(
{},
{
set(t, p, v) {
console.log(p, v);
self[p] = v;
return true;
},
}
),
});
Object.defineProperty(self, config.globals.wrapthisfn, { Object.defineProperty(self, config.globals.wrapthisfn, {
value: function (i) { value: function (i) {
if (i === self) return client.globalProxy; if (i === self) return client.globalProxy;

View file

@ -113,16 +113,7 @@ export const htmlRules: {
}, },
// url rewrites // url rewrites
src: [ src: ["embed", "img", "image", "iframe", "source", "input", "track"],
"embed",
"script",
"img",
"image",
"iframe",
"source",
"input",
"track",
],
href: ["a", "link", "area"], href: ["a", "link", "area"],
data: ["object"], data: ["object"],
action: ["form"], action: ["form"],
@ -227,17 +218,28 @@ function traverseParsedHtml(
node.name === "script" && node.name === "script" &&
/(application|text)\/javascript|module|importmap|undefined/.test( /(application|text)\/javascript|module|importmap|undefined/.test(
node.attribs.type node.attribs.type
) && )
node.children[0] !== undefined
) { ) {
let js = node.children[0].data; if (node.children[0] !== undefined) {
// node.attribs[`data-scramjet-script-source-src`] = btoa(js); let js = node.children[0].data;
node.attribs["data-scramjet-script-source-src"] = bytesToBase64( // node.attribs[`data-scramjet-script-source-src`] = btoa(js);
new TextEncoder().encode(js) node.attribs["data-scramjet-script-source-src"] = bytesToBase64(
); new TextEncoder().encode(js)
const htmlcomment = /<!--[\s\S]*?-->/g; );
js = js.replace(htmlcomment, ""); const htmlcomment = /<!--[\s\S]*?-->/g;
node.children[0].data = rewriteJs(js, meta); js = js.replace(htmlcomment, "");
node.children[0].data = rewriteJs(
js,
node.attribs["type"] === "module",
meta
);
} else if (node.attribs["src"]) {
let url = rewriteUrl(node.attribs["src"], meta);
if (node.attribs["type"] === "module") url += "?type=module";
node.attribs["data-scramjet-src"] = node.attribs["src"];
node.attribs["src"] = url;
}
} }
if (node.name === "meta" && node.attribs["http-equiv"] != undefined) { if (node.name === "meta" && node.attribs["http-equiv"] != undefined) {

View file

@ -24,12 +24,14 @@ const decoder = new TextDecoder();
function rewriteJsWrapper( function rewriteJsWrapper(
input: string | ArrayBuffer, input: string | ArrayBuffer,
module: boolean,
meta: URLMeta meta: URLMeta
): string | ArrayBuffer { ): string | ArrayBuffer {
let out: RewriterOutput; let out: RewriterOutput;
if (typeof input === "string") { if (typeof input === "string") {
out = rewrite_js( out = rewrite_js(
input, input,
module,
meta.base.href, meta.base.href,
"PERCS_PLEASE_FILL_THIS_IN.js", "PERCS_PLEASE_FILL_THIS_IN.js",
$scramjet $scramjet
@ -37,6 +39,7 @@ function rewriteJsWrapper(
} else { } else {
out = rewrite_js_from_arraybuffer( out = rewrite_js_from_arraybuffer(
new Uint8Array(input), new Uint8Array(input),
module,
meta.base.href, meta.base.href,
"PERCS_PLEASE_FILL_THIS_IN.js", "PERCS_PLEASE_FILL_THIS_IN.js",
$scramjet $scramjet
@ -67,17 +70,27 @@ function rewriteJsWrapper(
return typeof input === "string" ? decoder.decode(js) : js; return typeof input === "string" ? decoder.decode(js) : js;
} }
export function rewriteJs(js: string | ArrayBuffer, meta: URLMeta) { export function rewriteJs(
if (flagEnabled("naiiveRewriter", meta.origin)) { js: string | ArrayBuffer,
const text = typeof js === "string" ? js : new TextDecoder().decode(js); module: boolean,
meta: URLMeta
) {
const j = rewriteJsWrapper(js, module, meta);
console.log("naiive"); const text = typeof j === "string" ? j : new TextDecoder().decode(j);
if (module) {
js = `
let location = $scramjet$wrap(self.location);
let window = $scramjet$wrap(self.window);
let globalThis = $scramjet$wrap(self.globalThis);
return rewriteJsNaiive(text); ${text}
`;
} else {
js = `(function(window, location, globalThis) {
${text}
}).call($scramjet$wrap(this), $scramjet$wrap(window), $scramjet$wrap(location), $scramjet$wrap(globalThis))`;
} }
js = rewriteJsWrapper(js, meta);
return js; return js;
} }
@ -93,10 +106,10 @@ export function rewriteJsNaiive(js: string | ArrayBuffer) {
} }
return ` return `
with (${$scramjet.config.globals.wrapfn}(globalThis)) { with (${$scramjet.config.globals.wrapfn} (globalThis)) {
${js} ${js}
} }
`; `;
} }

View file

@ -32,7 +32,9 @@ export function rewriteUrl(url: string | URL, meta: URLMeta) {
} }
if (url.startsWith("javascript:")) { if (url.startsWith("javascript:")) {
return "javascript:" + rewriteJs(url.slice("javascript:".length), meta); return (
"javascript:" + rewriteJs(url.slice("javascript:".length), false, meta)
);
} else if (url.startsWith("blob:")) { } else if (url.startsWith("blob:")) {
return location.origin + $scramjet.config.prefix + url; return location.origin + $scramjet.config.prefix + url;
} else if (url.startsWith("data:")) { } else if (url.startsWith("data:")) {

View file

@ -24,7 +24,7 @@ export function rewriteWorkers(
script("client"); script("client");
console.log(str); console.log(str);
let rewritten = rewriteJs(js, meta); let rewritten = rewriteJs(js, type === "module", meta);
if (rewritten instanceof Uint8Array) { if (rewritten instanceof Uint8Array) {
rewritten = new TextDecoder().decode(rewritten); rewritten = new TextDecoder().decode(rewritten);
} }

View file

@ -300,7 +300,11 @@ async function rewriteBody(
return response.body; return response.body;
} }
case "script": case "script":
return rewriteJs(await response.arrayBuffer(), meta); return rewriteJs(
await response.arrayBuffer(),
workertype === "module",
meta
);
case "style": case "style":
return rewriteCss(await response.text(), meta); return rewriteCss(await response.text(), meta);
case "sharedworker": case "sharedworker":