您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Partially deobfuscate the code
- // ==UserScript==
- // @name Bonk Deobfuscator
- // @version 0.2
- // @description Partially deobfuscate the code
- // @author KOOKY WARRIOR
- // @license MIT
- // @match https://bonk.io/gameframe-release.html
- // @require https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.7/beautify.min.js
- // @grant none
- // @run-at document-end
- // @namespace https://greasyfork.org/users/999838
- // ==/UserScript==
- /*
- This code can only **PARTIALLY** deobfuscate the alpha2.js and save as a .js file
- **TIPS: Disable this userscript once you have obtained the deobfuscated code**
- */
- function log(text) {
- console.log(`[Bonk Deobfuscator] ${text}`)
- }
- const url = "https://bonk.io/js/alpha2s.js"
- log("Fetching " + url)
- fetch(url)
- .then((response) => response.text())
- .then((response) => {
- log("Deobfuscation started")
- function noDuplicate(array) {
- return [...new Set(array)]
- }
- function escapeRegExp(string) {
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
- }
- let tmp
- log("Unminifing the code")
- const splitedText = js_beautify(response, { e4x: true }).split("requirejs")
- log("Setting up main variables")
- const MAINFUNCTION = splitedText[0].match(/[^\[]+/)[0]
- const MAINARRAY = splitedText[0].match(/^var ([^=^\s]+);/m)[1]
- log(`eval ${MAINFUNCTION} function`)
- eval(`var ${MAINFUNCTION};${response.split("requestjs")[0]}`)
- let returncode = `requirejs${splitedText[1]}`
- log(`Replacing "var a = ${MAINFUNCTION}; a.bcd(123)" to "${MAINFUNCTION}.bcd(123)"`)
- tmp = returncode.match(new RegExp(`var (\\S+) = ${escapeRegExp(MAINFUNCTION)};`, ""))[1]
- returncode = returncode.replaceAll(`${tmp}.`, `${MAINFUNCTION}.`)
- log(`Replacing all duplicate functions`)
- tmp = [...splitedText[0].matchAll(new RegExp(`(?<v>${escapeRegExp(MAINFUNCTION)}\\.[\\S]+) = (?<f>function\\(\\) \\{.+?};)`, "gs"))]
- let VARIABLES = tmp.map((m) => m.groups.v)
- let FUNCTIONS = tmp.map((m) => m.groups.f)
- let indices = {}
- for (let i = 0; i < FUNCTIONS.length; i++) {
- if (!indices[FUNCTIONS[i]]) {
- indices[FUNCTIONS[i]] = []
- }
- indices[FUNCTIONS[i]].push(i)
- }
- for (const key in indices) {
- const element = indices[key]
- for (let i = 0; i < element.length; i++) {
- splitedText[0] = splitedText[0].replaceAll(VARIABLES[element[i]], VARIABLES[element[0]])
- returncode = returncode.replaceAll(VARIABLES[element[i]], VARIABLES[element[0]])
- }
- }
- log(`Replacing math operation`)
- const OPERATIONEQUALVARIABLE = /case 0:\n\s+(\S+) = .+\n.+break;/gm.exec(splitedText[0])[1]
- tmp = new RegExp(
- `return {\\s+(\\S+): function\\(\\) {\\s+var ${escapeRegExp(OPERATIONEQUALVARIABLE)}, (.+) = arguments;\\s+switch \\((.+)\\)`,
- "gm"
- ).exec(splitedText[0])
- const OPERATIONFUNCTION = new RegExp(`(${escapeRegExp(MAINFUNCTION)}\\....) = function\\(\\) {\\s+return.+${tmp[1]}`, "gm").exec(splitedText[0])[1]
- const OPERATIONFUNCTIONSETTER = new RegExp(
- `(${escapeRegExp(MAINFUNCTION)}\\....) = function\\(\\) {\\s+return.+${escapeRegExp(
- new RegExp(`,\\s+(\\S+): function.+\\s+${escapeRegExp(tmp[3])} =`, "gm").exec(splitedText[0])[1]
- )}`,
- "gm"
- ).exec(splitedText[0])[1]
- const OPERATIONARGUMENTVARIABLE = escapeRegExp(tmp[2])
- tmp = returncode.match(
- new RegExp(
- `${escapeRegExp(OPERATIONFUNCTION)}\\((?:[^)(]|\\((?:[^)(]|\\((?:[^)(]|\\([^)(]*\\))*\\))*\\))*\\)|${escapeRegExp(
- OPERATIONFUNCTIONSETTER
- )}\\(\\d+\\)`,
- "g"
- )
- )
- // FUNCTION\((?:[^)(]|\((?:[^)(]|\((?:[^)(]|\([^)(]*\))*\))*\))*\)
- var OPERATIONFUNCTIONSETTERVALUE = 0
- for (let i = 0; i < tmp.length; i++) {
- const element = tmp[i]
- if (element.includes(OPERATIONFUNCTION)) {
- const args = element.replace(`${OPERATIONFUNCTION}(`, "").replace(/.$/, "").replace(/\s/g, "").split(",")
- if (args[args.length - 1].includes(OPERATIONFUNCTIONSETTER)) {
- OPERATIONFUNCTIONSETTERVALUE = parseInt(new RegExp(`${escapeRegExp(OPERATIONFUNCTIONSETTER)}\\((\\d+)\\)`).exec(args[args.length - 1])[1])
- args.pop()
- }
- var value = new RegExp(`case ${OPERATIONFUNCTIONSETTERVALUE}:\\n\\s+${escapeRegExp(OPERATIONEQUALVARIABLE)} = (.+);\\n.+break;`, "gm").exec(
- splitedText[0]
- )[1]
- for (let j = 0; j < args.length; j++) {
- value = value.replaceAll(`${OPERATIONARGUMENTVARIABLE}[${j}]`, args[j])
- }
- try {
- value = eval(value)
- } catch (error) {
- } finally {
- returncode = returncode.replace(element, value)
- }
- } else {
- OPERATIONFUNCTIONSETTERVALUE = parseInt(new RegExp(`${escapeRegExp(OPERATIONFUNCTIONSETTER)}\\((\\d+)\\)`).exec(element)[1])
- }
- }
- const ARRAYFUNCTION = new RegExp(`${escapeRegExp(MAINARRAY)} = .+?(${escapeRegExp(MAINFUNCTION)}\\....)`, "").exec(splitedText[0])[1]
- log(`Replacing "${ARRAYFUNCTION}(123)" to "real data"`)
- tmp = noDuplicate(returncode.match(new RegExp(`${escapeRegExp(ARRAYFUNCTION)}\\((?:[^)(]|\\((?:[^)(]|\\((?:[^)(]|\\([^)(]*\\))*\\))*\\))*\\)`, "g")))
- for (let i = 0; i < tmp.length; i++) {
- const element = tmp[i]
- try {
- returncode = returncode.replaceAll(element, `"${eval(element).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/"/g, '\\"')}"`)
- } catch (error) {
- const args = element.replace(`${ARRAYFUNCTION}(`, "").replace(/.$/, "")
- const value = parseInt(new RegExp(`${escapeRegExp(args)} = (\\d+)`).exec(returncode)[1])
- returncode = returncode.replaceAll(
- element,
- `"${eval(`${ARRAYFUNCTION}(${value})`).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/"/g, '\\"')}"`
- )
- }
- }
- log(`Replacing "var a = ${MAINARRAY}; a[123]" to "${MAINARRAY}[123]"`)
- tmp = [...returncode.matchAll(new RegExp(`\\s+(?<v>\\S+) = ${escapeRegExp(MAINARRAY)}.*$`, "gm"))].map((m) => m.groups.v)
- for (let i = 0; i < tmp.length; i++) {
- returncode = returncode.replaceAll(tmp[i], MAINARRAY)
- }
- log(`Replacing "${MAINARRAY}[123]" to "real data"`)
- tmp = noDuplicate(
- returncode.match(new RegExp(`${escapeRegExp(MAINARRAY)}\\[(?:[^\\]\\[]|\\[(?:[^\\]\\[]|\\[(?:[^\\]\\[]|\\[[^\\]\\[]*\\])*\\])*\\])*\\]`, "g"))
- )
- // ARRAY\[(?:[^\]\[]|\[(?:[^\]\[]|\[(?:[^\]\[]|\[[^\]\[]*\])*\])*\])*\]
- for (let i = 0; i < tmp.length; i++) {
- const element = tmp[i]
- try {
- returncode = returncode.replaceAll(element, `"${eval(element).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/"/g, '\\"')}"`)
- } catch (error) {
- try {
- const args = element.replace(`${MAINARRAY}[`, "").replace(/.$/, "")
- const value = parseInt(new RegExp(`${escapeRegExp(args)} = (\\d+)`).exec(returncode)[1])
- returncode = returncode.replaceAll(element, `"${eval(`${MAINARRAY}[${value}]`).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/"/g, '\\"')}"`)
- } catch (err) {}
- }
- }
- log("Saving deobfuscated code")
- const filename = `BonkDeobfuscated_${Date.now()}`
- const blob = new Blob([splitedText[0] + returncode], { type: "text/javascript;charset=utf-8;" })
- if (window.navigator.msSaveOrOpenBlob) {
- window.navigator.msSaveBlob(blob, filename)
- } else {
- const elem = window.document.createElement("a")
- elem.href = window.URL.createObjectURL(blob)
- elem.download = filename
- document.body.appendChild(elem)
- elem.click()
- document.body.removeChild(elem)
- }
- })
- .catch((err) => console.log(err))