1 //CREDITS TO 05KONZ FOR THE RUNTIME
2 const toRun
= "global/crashgame";
4 // Blooket developers will be able to detect this easily, so use with caution
5 if (window
.runCheat
) return window
.runCheat(cheat
);
7 let i
= document
.querySelector("iframe");
9 i
= document
.createElement('iframe');
10 document
.body
.append(i
);
11 i
.style
.display
= "none";
13 const alert
= i
.contentWindow
.alert
.bind(window
);
14 const confirm
= i
.contentWindow
.confirm
.bind(window
);
15 const prompt
= i
.contentWindow
.prompt
.bind(window
);
16 const log
= i
.contentWindow
.console
.log
;
18 // by CryptoDude3 or me!
19 if (window
.fetch
.call
.toString() == 'function call() { [native code] }') {
20 const call
= window
.fetch
.call
;
21 window
.fetch
.call = function () {
22 return arguments
[1].includes("s.blooket.com/rc") ? log("Bypassed anti-cheat") : call
.apply(this, arguments
);
26 const nil
= Symbol("null");
27 const This
= Symbol("this");
30 const tokens
= "NumberExpr:number_expr,FloatExpr:float_expr,StringExpr:string_expr,SymbolExpr:symbol_expr,BinaryExpr:binary_expr,PrefixExpr:prefix_expr,SuffixExpr:suffix_expr,AssignmentExpr:assignment_expr,ObjectExpr:object_expr,ArrayExpr:array_expr,CallExpr:call_expr,MemberExpr:member_expr,DynamicMemberExpr:dynamic_member_expr,TernaryExpr:ternary_expr,FuncExpr:func_expr,GroupExpr:group_expr,BlockStmt:block_stmt,ExpressionStmt:expression_stmt,VarDeclStmt:declr_stmt,FuncDeclStmt:func_decl_stmt,WhileStmt:while_stmt,ForStmt:for_stmt,IfStmt:if_stmt,ElseStmt:else_stmt,ReturnStmt:return_stmt,ContinueStmt:continue_stmt,BreakStmt:break_stmt,EndFunc:end_func,EndFor:end_for,EndWhile:end_while,EndIf:end_if,EndElse:end_else,TernaryQue:ternary_que,TernaryCol:ternary_col,EndTernary:end_ternary,ForIncr:for_incr,TypeofExpr:typeof_expr".split(",").map(x
=> x
.trim().split(":"));
31 for (let id
= 0; id
< tokens
.length
; id
++) {
32 Types
[tokens
[id
][0]] = tokens
[id
][1];
33 Types
[tokens
[id
][1]] = id
;
34 Types
[id
] = tokens
[id
][0];
37 constructor(parent
, constants
= {}) {
39 this.constants
= Object
.create(null);
40 this.variables
= Object
.create(null);
41 for (const constant
in constants
) this.declareVar(constant
, constants
[constant
], true);
43 declareVar(name
, value
, constant
) {
44 if (name
in this.variables
) throw new Error(`Cannot declare variable ${name}. As it already is defined.`);
45 if (constant
) this.constants
[name
] = true;
46 return this.variables
[name
] = value
;
48 assignVar(name
, value
) {
49 if (this.constants
[name
]) throw new Error(`Cannot reassign constant variable`);
50 const env
= this.resolve(name
);
51 return env
.variables
[name
] = value
;
54 if (name
in this.variables
) return true;
55 if (this.parent
== undefined) return false;
56 return this.parent
.hasVar(name
);
59 if (name
in this.variables
) return this;
60 if (this.parent
== undefined) throw new Error(`Cannot resolve '${name}' as it does not exist.`);
61 return this.parent
.resolve(name
);
64 const env
= this.resolve(name
);
65 return env
.variables
[name
];
69 function assignment_op(assignee
, operator
, value
) {
72 return assignee
+ value
;
74 return assignee
- value
;
76 return assignee
* value
;
78 return assignee
/ value
;
80 return assignee
% value
;
84 throw new Error(`Unknown assignment operator: ${operator}`);
94 const size
= this.code(this.ind
++);
95 const str
= this.source
.slice(this.ind
, this.ind
+ size
);
100 const size
= this.code(this.ind
++);
102 for (let i
= 0; i
< size
; i
++) {
103 num
+= this.code(this.ind
++) * Math
.pow(65536, i
);
108 return parseFloat(this.StringExpr());
111 return env
.lookupVar(this.StringExpr());
114 const size
= this.code(this.ind
++);
115 for (let i
= 0; i
< size
; i
++) this.evaluate(env
);
118 const name
= this.evaluate(env
);
119 const isConstant
= this.code(this.ind
++) == 1;
120 const value
= this.code(this.ind
++) == 1 ? this.evaluate(env
) : null;
121 return env
.declareVar(name
, value
, isConstant
);
123 ExpressionStmt(env
) {
124 return this.evaluate(env
);
127 const assignee
= this.evaluate(env
);
128 const prop
= this.evaluate(env
);
129 let res
= assignee
?.[prop
];
130 try { res
&& (res
[This
] = assignee
); } catch { };
133 AssignmentExpr(env
) {
135 const type
= Types
[this.code(this.ind
++)];
136 if (type
== "MemberExpr") {
137 let assignee
= this.evaluate(env
);
138 const property
= this.evaluate(env
);
139 return assignee
[property
] = assignment_op(assignee
[property
], this.evaluate(env
), this.evaluate(env
));
141 if (type
== "SymbolExpr") {
142 const str
= this.StringExpr();
143 return env
.assignVar(str
, assignment_op(env
.lookupVar(str
), this.evaluate(env
), this.evaluate(env
)));
145 throw new Error(`Unknown assignment type ${type}`);
148 const operator
= this.evaluate(env
);
151 return -this.evaluate(env
);
153 return !this.evaluate(env
);
155 throw new Error(`Unknown prefix operator: ${operator}`);
159 const size
= this.code(this.ind
++);
160 for (let i
= 0; i
< size
; i
++) {
161 const key
= this.evaluate(env
);
162 obj
[key
] = this.evaluate(env
);
166 static LoopEnv(env
) {
167 const loop_env
= new Env(env
);
168 loop_env
.declareVar("break", nil
);
169 loop_env
.declareVar("continue", nil
);
173 const for_env
= Eval
.LoopEnv(env
);
174 this.evaluate(for_env
);
175 const vars
= { ...for_env
.variables
};
176 const start
= this.ind
;
177 const end
= this.findNext(Types
.for_stmt
, Types
.end_for
);
178 const incr
= this.findNext(Types
.for_stmt
, Types
.for_incr
);
179 while ((this.ind
= start
, this.evaluate(for_env
))) {
180 this.evaluate(for_env
);
181 for_env
.assignVar("continue", nil
);
182 if (for_env
.lookupVar("break") != nil
) break;
184 this.evaluate(for_env
);
185 for (const key
in for_env
.variables
) if (!(key
in vars
)) {
186 delete for_env
.variables
[key
];
187 delete for_env
.constants
[key
];
194 let while_env
= Eval
.LoopEnv(env
);
195 const start
= this.ind
;
196 const end
= this.findNext(Types
.while_stmt
, Types
.end_while
);
197 while ((this.ind
= start
, this.evaluate(while_env
))) {
198 this.evaluate(while_env
);
199 while_env
.assignVar("continue", nil
);
200 if (while_env
.lookupVar("break") != nil
) break;
201 while_env
.variables
= {
205 while_env
.constants
= Object
.create(null);
210 const left
= this.evaluate(env
);
211 const operator
= this.evaluate(env
);
212 const right
= this.evaluate(env
);
229 return left
<= right
;
231 return left
>= right
;
233 return left
== right
;
235 return left
!= right
;
237 return left
|| right
;
239 return left
&& right
;
241 throw new Error(`Unknown binary operator ${operator}`);
244 if (this.code(this.ind
++) == Types
.symbol_expr
) {
245 const assignee
= this.StringExpr(env
);
246 const operator
= this.evaluate(env
);
249 return env
.assignVar(assignee
, env
.lookupVar(assignee
) + 1);
251 return env
.assignVar(assignee
, env
.lookupVar(assignee
) - 1);
253 throw new Error(`Unknown suffix operator: ${operator}`);
255 const assignee
= this.evaluate(env
);
256 const property
= this.evaluate(env
);
257 const operator
= this.evaluate(env
);
260 return assignee
[property
]++;
262 return assignee
[property
]--;
264 throw new Error(`Unknown suffix operator: ${operator}`);
267 const callee
= this.evaluate(env
);
269 const size
= this.code(this.ind
++);
270 for (let i
= 0; i
< size
; i
++)
271 args
.push(this.evaluate(env
));
272 if (typeof callee
== "function") {
274 try { ret
= callee
.apply(callee
[This
], args
); } catch (e
) {
275 i
.contentWindow
.console
.warn(e
);
282 const name
= this.StringExpr(env
);
283 const parameters
= [];
284 const size
= this.code(this.ind
++);
285 for (let i
= 0; i
< size
; i
++) {
287 parameters
.push(this.StringExpr(env
));
290 const here
= this.ind
;
291 this.ind
= this.findNext(Types
.func_expr
, Types
.end_func
);
293 const runtime
= this;
294 const fn = function () {
295 const fn_env
= new Env(env
);
296 fn_env
.declareVar("arguments", arguments
);
297 fn_env
.declareVar("this", this);
298 for (const param
in parameters
) fn_env
.declareVar(parameters
[param
], arguments
[param
]);
299 fn_env
.declareVar("return", nil
);
301 runtime
.evaluateInd(fn_env
, here
);
303 return fn_env
.lookupVar("return");
305 if (name
.length
) env
.declareVar(name
, fn
);
310 const size
= this.code(this.ind
++);
311 for (let i
= 0; i
< size
; i
++) {
312 arr
.push(this.evaluate(env
));
317 const ret
= this.code(this.ind
++) == 1 ? this.evaluate(env
) : null;
318 return env
.assignVar("return", ret
);
321 return env
.assignVar("break", true);
324 return env
.assignVar("continue", true);
327 const elseLoc
= this.findNext(Types
.if_stmt
, Types
.end_if
);
328 const condition
= this.evaluate(env
);
330 this.evaluate(new Env(env
));
332 if (this.code(this.ind
++) == 1) {
333 this.ind
= this.findNext(Types
.else_stmt
, Types
.end_else
);
337 if (this.code(this.ind
++) == 1) {
339 this.evaluate(new Env(env
));
345 const condition
= this.evaluate(env
);
347 const endLoc
= this.findNext(Types
.ternary_expr
, Types
.end_ternary
);
348 const elseLoc
= this.findNext(Types
.ternary_que
, Types
.ternary_col
);
351 val
= this.evaluate(env
);
355 val
= this.evaluate(env
);
362 const size
= this.code(this.ind
++);
363 for (let i
= 0; i
< size
; i
++)
364 last
= this.evaluate(env
);
368 return typeof this.evaluate(env
);
370 findNext(open
, close
) {
372 for (ind
= this.ind
+ 1; ind
< this.source
.length
&& num
> 0; ind
++) {
373 if (this.code(ind
- 1) == 2 && this.code(ind
- 2) != 16) ind
++;
374 if (this.code(ind
) == close
) num
--;
375 else if (this.code(ind
) == open
) num
++;
380 return this.source
.charCodeAt(i
);
383 const type
= Types
[this.code(this.ind
++)];
384 if (env
.hasVar("return") && env
.lookupVar("return") != nil
) return;
385 if (env
.hasVar("break") && env
.lookupVar("break") != nil
) return;
386 if (env
.hasVar("continue") && env
.lookupVar("continue") != nil
) return;
387 if (type
in this) return this[type
](env
);
388 console
.error(new Error(`No eval function for type ${type}`))
389 throw new Error(`No eval function for type ${type}`);
391 evaluateInd(env
, ind
) {
392 const temp
= this.ind
;
394 const value
= this.evaluate(env
);
395 const end
= this.ind
;
401 function addProps(element
, obj
) {
402 for (const prop
in obj
) if (typeof obj
[prop
] == "object") addProps(element
[prop
], obj
[prop
]);
403 else element
[prop
] = obj
[prop
];
406 true: true, false: false, null: null,
407 setVal
: (path
, val
) => constants
.stateNode
.props
.liveGameController
.setVal({ path
, val
}),
408 print
: log
, console
: i
.contentWindow
.console
,
409 window
, alert
, confirm
, prompt
, promptFloat
: (x
) => parseFloat(prompt(x
)), promptNum
: (x
) => parseInt(prompt(x
)),
410 isNaN
, parseFloat
, parseInt
,
411 Date
, Object
, Array
, Math
, Promise
, Number
,
412 queryElement
: document
.querySelector
.bind(document
),
413 queryElementAll
: document
.querySelectorAll
.bind(document
),
414 fetch
: window
.fetch
.bind(window
),
415 elStateNode
: s
=> Object
.values(document
.querySelector(s
))[1].children
._owner
.stateNode
,
416 createElement
: function createElement(type
, props
, ...children
) {
417 const element
= document
.createElement(type
);
418 addProps(element
, props
);
419 for (const child
of children
) element
.append(child
);
423 Object
.defineProperty(constants
, "stateNode", {
424 get: () => Object
.values((function react(r
= document
.querySelector("body>div")) { return Object
.values(r
)[1]?.children
?.[0]?._owner
.stateNode
? r
: react(r
.querySelector(":scope>div")) })())[1].children
[0]._owner
.stateNode
,
427 const env
= new Env(undefined, constants
);
428 (window
.runCheat = function (path
) {
430 img
.src
= "https://raw.githubusercontent.com/DannyDan0167/Blooket-Cheats-Plus/main/csptest/out/" + path
+ ".png?" + Date
.now();
431 img
.crossOrigin
= "Anonymous";
432 img
.onload = function () {
433 const c
= document
.createElement("canvas");
434 const ctx
= c
.getContext("2d");
435 ctx
.drawImage(img
, 0, 0, this.width
, this.height
);
436 let { data
} = ctx
.getImageData(0, 0, this.width
, this.height
), decode
= "";
438 while (i
< data
.length
)
439 decode
+= String
.fromCharCode(data
[i
% 4 == 3 ? (i
++, i
++) : i
++] + data
[i
% 4 == 3 ? (i
++, i
++) : i
++] * 256);
440 new Eval(decode
).evaluate(new Env(env
));
442 img
.onerror
= img
.onabort
= () => {
443 img
.onerror
= img
.onabort
= null;
444 let iframe
= document
.querySelector("iframe");
445 iframe
.contentWindow
.alert("It seems the GitHub is either blocked or down.\n\nIf it's NOT blocked, join the Discord server for updates\nhttps://discord.gg/jHjGrrdXP6");