1
Fork 0
mirror of https://github.com/thegeneralist01/twitter-tid-deobf-fork synced 2026-01-11 23:50:28 +01:00
twitter-tid-deobf-fork/deobf2.js
ふぁ 51ad406da4
add 2
Signed-off-by: ふぁ <yuki@yuki0311.com>
2024-12-15 21:41:56 +09:00

163 lines
4.7 KiB
JavaScript

const fs = require("fs");
const babel = require("@babel/core");
const t = require("@babel/types");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const generate = require("@babel/generator").default;
const { readFileSync } = require("fs");
let beautify_opts = {
comments: true,
minified: false,
concise: false,
};
const [_, __, input, output] = process.argv;
const script = readFileSync(input, "utf-8");
const AST = parser.parse(script, {});
const inlineDestructuredVariables = {
VariableDeclaration(path) {
const { node, scope } = path;
node.declarations.forEach((declarator) => {
const { id, init } = declarator;
// Handle array destructuring
if (t.isArrayPattern(id) && t.isArrayExpression(init)) {
const elementsLeft = id.elements;
const elementsRight = init.elements;
// Ensure both sides have the same number of elements
if (elementsLeft.length !== elementsRight.length) return;
elementsLeft.forEach((leftElem, index) => {
const rightElem = elementsRight[index];
if (!leftElem || !rightElem) return;
if (t.isIdentifier(leftElem)) {
const varName = leftElem.name;
const binding = scope.getBinding(varName);
// Ensure the variable is not reassigned
if (binding && binding.constant) {
// Replace all references
binding.referencePaths.forEach((refPath) => {
// Resolve nested identifiers recursively
replaceWithResolvedValue(refPath, rightElem, scope);
});
// Optionally remove the declarator
// binding.path.remove();
}
}
});
}
// Handle object destructuring if needed
// (Similar logic can be applied here if your code contains object destructuring)
});
// Optionally remove the entire declaration if all variables have been inlined
if (node.declarations.every((decl) => !scope.getBinding(decl.id.name))) {
path.remove();
}
},
};
// Helper function to resolve nested identifiers and member expressions
function replaceWithResolvedValue(refPath, valueNode, scope) {
if (t.isIdentifier(valueNode)) {
const binding = scope.getBinding(valueNode.name);
if (binding && binding.constant && binding.path.node.init) {
// Recursively replace with the actual value
replaceWithResolvedValue(refPath, binding.path.node.init, scope);
} else {
refPath.replaceWith(valueNode);
}
} else if (t.isMemberExpression(valueNode)) {
// Resolve the object and property if possible
const objectNode = valueNode.object;
const propertyNode = valueNode.property;
let resolvedObjectNode = objectNode;
if (t.isIdentifier(objectNode)) {
const objectBinding = scope.getBinding(objectNode.name);
if (
objectBinding &&
objectBinding.constant &&
objectBinding.path.node.init
) {
resolvedObjectNode = objectBinding.path.node.init;
}
}
refPath.replaceWith(
t.memberExpression(resolvedObjectNode, propertyNode, valueNode.computed)
);
} else {
refPath.replaceWith(valueNode);
}
}
const evaluateMemberExpressions = {
MemberExpression(path) {
const { node } = path;
if (t.isIdentifier(node.object) && t.isStringLiteral(node.property)) {
const objectName = node.object.name;
const propertyName = node.property.value;
if (objectName === "window") {
path.replaceWithSourceString(propertyName);
}
}
},
};
const evaluateCallExpressions = {
MemberExpression(path) {
const { node } = path;
if (t.isIdentifier(node.object) && t.isStringLiteral(node.property)) {
const objectName = node.object.name;
const propertyName = node.property.value;
const validObjects = [
"document",
"crypto",
"Array",
"Uint8Array",
"TextEncoder",
"RTCPeerConnection",
"Promise",
"Math",
"String",
];
if (validObjects.includes(objectName)) {
path.replaceWithSourceString(`${objectName}.${propertyName}`);
}
}
},
};
traverse(AST, inlineDestructuredVariables);
traverse(AST, evaluateMemberExpressions);
traverse(AST, evaluateCallExpressions);
const final_code = generate(AST, beautify_opts).code;
babel.transform(
final_code,
{
plugins: [
"babel-plugin-minify-constant-folding",
"babel-plugin-minify-dead-code-elimination",
"babel-plugin-transform-inline-consecutive-adds",
],
},
function (err, result) {
if (err) {
console.error(err);
} else {
const transformedCode = result.code;
fs.writeFileSync(output, transformedCode);
}
}
);