reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
const { runPatternPass } = require("./shared-pattern-pass");
|
||||
const {
|
||||
createSandbox,
|
||||
evaluateNodes,
|
||||
foldWrapperObjects,
|
||||
inlineStringMethodCalls,
|
||||
seedSandboxFromAliases,
|
||||
traverse,
|
||||
t
|
||||
} = require("./pattern-utils");
|
||||
|
||||
function getDecoderPreludeNodes(ast) {
|
||||
const topLevelDeclarator = ast.program.body
|
||||
.filter((node) => t.isVariableDeclaration(node))
|
||||
.flatMap((node) => node.declarations)
|
||||
.find((decl) =>
|
||||
t.isIdentifier(decl.id) &&
|
||||
(
|
||||
t.isFunctionExpression(decl.init) ||
|
||||
(t.isCallExpression(decl.init) && t.isFunctionExpression(decl.init.callee))
|
||||
)
|
||||
);
|
||||
|
||||
const rootFunction = !topLevelDeclarator ? null :
|
||||
t.isFunctionExpression(topLevelDeclarator.init) ? topLevelDeclarator.init :
|
||||
t.isCallExpression(topLevelDeclarator.init) && t.isFunctionExpression(topLevelDeclarator.init.callee) ? topLevelDeclarator.init.callee :
|
||||
null;
|
||||
|
||||
if (!rootFunction || !t.isBlockStatement(rootFunction.body)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const nodes = [];
|
||||
for (const stmt of rootFunction.body.body) {
|
||||
if (t.isFunctionDeclaration(stmt) && stmt.id && (stmt.id.name === "t" || stmt.id.name === "u")) {
|
||||
nodes.push(stmt);
|
||||
continue;
|
||||
}
|
||||
if (t.isVariableDeclaration(stmt) && stmt.declarations.every((decl) => t.isIdentifier(decl.id) && decl.init == null)) {
|
||||
nodes.push(stmt);
|
||||
continue;
|
||||
}
|
||||
if (t.isExpressionStatement(stmt)) {
|
||||
nodes.push(stmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function tonghuashunOrderPass(ast) {
|
||||
let changed = false;
|
||||
let localChanged = false;
|
||||
const sandbox = createSandbox();
|
||||
const preludeNodes = getDecoderPreludeNodes(ast);
|
||||
if (preludeNodes.length > 0 && evaluateNodes(preludeNodes, sandbox, 2000)) {
|
||||
while (seedSandboxFromAliases(ast, sandbox)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
const decoderAliasNames = collectDecoderAliasNames(ast, ["t"]);
|
||||
do {
|
||||
localChanged = false;
|
||||
|
||||
if (replaceDecoderAliasCalls(ast, sandbox, decoderAliasNames)) {
|
||||
localChanged = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (inlineStringMethodCalls(ast)) {
|
||||
localChanged = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
const foldResult = foldWrapperObjects(ast, {
|
||||
ignoreDynamicUsage: true
|
||||
});
|
||||
if (foldResult.changed) {
|
||||
localChanged = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (inlineStringMethodCalls(ast)) {
|
||||
localChanged = true;
|
||||
changed = true;
|
||||
}
|
||||
} while (localChanged);
|
||||
|
||||
return { ast, changed };
|
||||
}
|
||||
|
||||
function collectDecoderAliasNames(ast, seedNames) {
|
||||
const aliasNames = new Set(seedNames);
|
||||
let expanded = false;
|
||||
|
||||
do {
|
||||
expanded = false;
|
||||
traverse(ast, {
|
||||
VariableDeclarator(path) {
|
||||
if (!path.get("id").isIdentifier() || !path.get("init").isIdentifier()) {
|
||||
return;
|
||||
}
|
||||
const sourceName = path.get("init").node.name;
|
||||
const aliasName = path.get("id").node.name;
|
||||
if (!aliasNames.has(sourceName) || aliasNames.has(aliasName)) {
|
||||
return;
|
||||
}
|
||||
aliasNames.add(aliasName);
|
||||
expanded = true;
|
||||
},
|
||||
AssignmentExpression(path) {
|
||||
if (!path.get("left").isIdentifier() || !path.get("right").isIdentifier()) {
|
||||
return;
|
||||
}
|
||||
const sourceName = path.get("right").node.name;
|
||||
const aliasName = path.get("left").node.name;
|
||||
if (!aliasNames.has(sourceName) || aliasNames.has(aliasName)) {
|
||||
return;
|
||||
}
|
||||
aliasNames.add(aliasName);
|
||||
expanded = true;
|
||||
}
|
||||
});
|
||||
} while (expanded);
|
||||
|
||||
return aliasNames;
|
||||
}
|
||||
|
||||
function nodeFromPrimitiveValue(value) {
|
||||
if (typeof value === "undefined") {
|
||||
return t.identifier("undefined");
|
||||
}
|
||||
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
return t.valueToNode(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function replaceDecoderAliasCalls(ast, sandbox, aliasNames) {
|
||||
if (typeof sandbox.t !== "function" || aliasNames.size === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let changed = false;
|
||||
traverse(ast, {
|
||||
CallExpression(path) {
|
||||
const calleePath = path.get("callee");
|
||||
let isDecoderAliasCall = false;
|
||||
|
||||
if (calleePath.isIdentifier()) {
|
||||
isDecoderAliasCall = aliasNames.has(calleePath.node.name);
|
||||
} else if (
|
||||
calleePath.isAssignmentExpression({ operator: "=" }) &&
|
||||
calleePath.get("left").isIdentifier() &&
|
||||
calleePath.get("right").isIdentifier()
|
||||
) {
|
||||
isDecoderAliasCall = aliasNames.has(calleePath.get("right").node.name);
|
||||
}
|
||||
|
||||
if (!isDecoderAliasCall) {
|
||||
return;
|
||||
}
|
||||
if (path.node.arguments.length !== 1 || !path.get("arguments.0").isNumericLiteral()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value;
|
||||
try {
|
||||
value = sandbox.t(path.get("arguments.0").node.value);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
const literalNode = nodeFromPrimitiveValue(value);
|
||||
if (!literalNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
path.replaceWith(literalNode);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
runPatternPass(tonghuashunOrderPass);
|
||||
Reference in New Issue
Block a user