Update to 134

This commit is contained in:
gijs 2023-09-22 14:37:29 +02:00
commit e42d7f9c47
3 changed files with 1294 additions and 0 deletions

199
index.js Normal file
View File

@ -0,0 +1,199 @@
const fs = require("fs");
const https = require("https");
const { parse: parseHtml } = require('node-html-parser');
const { parseScript } = require('esprima');
const { exec, execSync } = require("child_process");
const FLYFF_URL = "https://universe.flyff.com/play";
const OUTPUT_DIR = "./out/";
const { edit } = require("@webassemblyjs/wasm-edit");
const IMPORT_NAMESPACE = "flyff";
if (!fs.existsSync(OUTPUT_DIR))
fs.mkdirSync(OUTPUT_DIR);
download(FLYFF_URL, main);
function main(html) {
const root = parseHtml(html);
const launcherScript = (() => {
for(const script of root.querySelectorAll("script[type='text/javascript']")) {
if(script.innerText.indexOf("FilemapVersion") > 0) {
return script;
}
}
})();
const launcherJs = launcherScript.innerText;
if(launcherJs.length == 0) {
console.error("Unable to get launcher javascript.");
}
const version = (() => {
// Figure out which FilemapVersion the client currently uses.
// HACKY:
// - The JS that's downloaded is written for use in HTML.
// - The fact that it crashes very fast is abused.
try {
eval(launcherJs);
} catch (e) { }
return FilemapVersion;
})();
if (!fs.existsSync(OUTPUT_DIR + version))
fs.mkdirSync(OUTPUT_DIR + version);
// Write the html out for debugging, if something has changed.try {
fs.writeFileSync(OUTPUT_DIR + version + "/index.html", html);
console.log("Detected version: " + version);
const binaryUrl = "https://gcpcdn-universe.flyff.com/client/program/web/main-wasm32.wasm?" + version;
const emscriptenUrl = "https://gcpcdn-universe.flyff.com/client/program/web/main-wasm32.js?" + version;
const binaryPath = OUTPUT_DIR + version + "/client-original.wasm";
const file = fs.createWriteStream(binaryPath);
https.get(binaryUrl, function (response) {
response.pipe(file);
// after download completed close filestream
file.on("finish", () => {
file.close();
console.log("Binary: downloaded.");
download(emscriptenUrl, (js) => {
const path = OUTPUT_DIR + version + "/client-original.js";
fs.writeFileSync(path, js);
console.log("Javascript Environment: downloaded.");
const importFnMap = new Map();
const exportFnMap = new Map();
const handleVariableDeclarator = (node, meta) => {
if(node.id.name === "wasmImports") {
// Find minified import names.
for(const property of node.init.properties) {
const obfuscated = property.key.value;
const nice = property.value.name;
importFnMap.set(obfuscated, nice);
}
} else {
// Find minified export names.
if(node.init && node.init.type === "AssignmentExpression" &&
node.init.right && node.init.right.type === "FunctionExpression") {
const nice = node.id.name;
// What a mess...
const initExpression = node.init.right;
const returnStatement = initExpression.body.body[0];
const callee = returnStatement.argument.callee;
const computedMemberExpression = callee.object.right.right;
const obfuscated = computedMemberExpression.property.value;
exportFnMap.set(obfuscated, nice);
}
}
}
console.log("Javascript Environment: Finding minified function map...");
parseScript(js, null, (node, meta) => {
if(node.type === "VariableDeclarator")
return handleVariableDeclarator(node, meta);
if(node.type === "ExpressionStatement") {
// Find minified memory and table names.
if((node.expression.left?.name === "wasmTable" ||
node.expression.left?.name === "wasmMemory") &&
node.expression.right?.object?.object?.name === "Module") {
const obfuscated = node.expression.right.property.value;
const jsName = node.expression.left.name;
const nice = jsName === "wasmMemory" ? "memory" :
jsName === "wasmTable" ? "table" : "";
exportFnMap.set(obfuscated, nice);
}
}
});
// Use this to identify what you are looking for.
// parseScript("var wasmTable; wasmTable = other['kc'];", null, (node, meta) => {
// console.log(node);
// });
const jsonObj = {
// Sort 'm
imports: Object.fromEntries(new Map([...importFnMap.entries()].sort())),
exports: Object.fromEntries(new Map([...exportFnMap.entries()].sort())),
};
fs.writeFileSync(OUTPUT_DIR + version + "/functions.json", JSON.stringify(jsonObj, null, 4));
// console.log(fnMap);
console.log("Identified " + importFnMap.size + " imported, and " + exportFnMap.size + " exported symbols!");
// console.log("Loading binary from " + binaryPath);
// const binary = fs.readFileSync(binaryPath);
// console.log("Loaded binary.");
// const visitors = {
// ModuleImport({ node }) {
// console.log("Renaming " + node.module + "::" + node.name + " to " + IMPORT_NAMESPACE + "::" + fnMap[node.name]);
// // console.log("MODULE IMPORT: ", node);
// node.module = "flyff";
// node.name = fnMap[node.name];
// }
// };
// console.log("Fixing imports (this may take a while...)");
// const newBinary = edit(binary, visitors);
// console.log("Fixed imports, writing new binary...");
// console.log(typeof(newBinary), newBinary);
// fs.writeFileSync(binaryPath, Buffer.from(newBinary));
// console.log("Done writing new binary.");
// console.log("Binary: Starting decompilation...");
// const outputPath = OUTPUT_DIR + version + "/client.c";
// execSync("wasm2c " + binaryPath + " -o " + outputPath);
// console.log("Binary: Decompilation finished.");
// Tag our header file so we know what version of the filemap was when decompiled.
// let data = fs.readFileSync(OUTPUT_DIR + version + "/client.h", 'utf8');
// data = "/* Automagically edited by fugg-fetch for FilemapVersion " + version + " */\n\n" + data;
// fs.writeFileSync(OUTPUT_DIR + version + "/client.h", data);
// console.log("Binary: wrote FilemapVersion to file.");
process.exit();
});
});
});
}
function download(url, cb) {
https.get(url, (res) => {
console.log("Got response: " + res.statusCode);
let body = "";
res.on("data", function (chunk) {
body += chunk;
});
res.on('end', function () {
cb(body);
});
}).on('error', function (e) {
console.log("Unable to retrieve webpage at '" + FLYFF_URL + "': " + e.message);
});
}

1076
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "fugg-fetch",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"deob": "synchrony deobfuscate ./out/client_47.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@webassemblyjs/wasm-edit": "^1.11.1",
"deobfuscator": "^2.3.0",
"esprima": "^4.0.1",
"node-fetch": "^3.2.9",
"node-html-parser": "^5.3.3"
}
}