Пожалуйста, обратите внимание, что пользователь заблокирован
Code.js:
.env:
JavaScript:
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const Parser = require('tree-sitter');
const Rust = require('tree-sitter-rust');
// ============ ЗАГРУЗКА НАСТРОЕК ИЗ .env ============
const config = {
enableInjection: process.env.ENABLE_INJECTION === 'true',
enableAliases: process.env.ENABLE_ALIASES === 'true',
enableRenameProgramMod: process.env.ENABLE_RENAME_PROGRAM_MOD === 'true',
enableAddJunkStatements: process.env.ENABLE_ADD_JUNK_STATEMENTS === 'true',
enableRenameIdentifiers: process.env.ENABLE_RENAME_IDENTIFIERS === 'true',
enableMinify: process.env.ENABLE_MINIFY === 'false',
snakeCasePrefix: process.env.SNAKE_CASE_PREFIX || 'obf',
snakeCaseLength: parseInt(process.env.SNAKE_CASE_LENGTH || '4', 10),
camelCasePrefix: process.env.CAMEL_CASE_PREFIX || 'En',
camelCaseLength: parseInt(process.env.CAMEL_CASE_LENGTH || '4', 10),
junkRatio: parseFloat(process.env.JUNK_RATIO || '20'),
};
let renameMap = new Map();
function randomIdentSnakeCase(
prefix = config.snakeCasePrefix,
length = config.snakeCaseLength
) {
const firstChars = 'abcdefghijklmnopqrstuvwxyz';
const allChars = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = prefix.toLowerCase() + '_';
if (length > 0) {
result += firstChars.charAt(Math.floor(Math.random() * firstChars.length));
}
for (let i = 1; i < length; i++) {
result += allChars.charAt(Math.floor(Math.random() * allChars.length));
}
return result;
}
function randomIdentCamelCase(
prefix = config.camelCasePrefix,
length = config.camelCaseLength
) {
const firstChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const allChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = prefix;
if (length > 0) {
result += firstChars.charAt(Math.floor(Math.random() * firstChars.length));
}
for (let i = 1; i < length; i++) {
result += allChars.charAt(Math.floor(Math.random() * allChars.length));
}
return result;
}
const junkSnippets = [
[
'let mut {{VAR}} = 42;',
'{{VAR}} += 1;',
'if {{VAR}} < 50 {',
' {{VAR}} *= 2;',
'}',
],
[
'let {{VAR}} = vec![1,2,3];',
'for x in &{{VAR}} {',
' println!("x: {}", x);',
'}',
],
[
'let {{VAR}} = "dummy_string";',
'println!("Len: {}", {{VAR}}.len());',
],
[
'fn {{VAR}}_helper() {',
' let _tmp = 123;',
' // do nothing',
'}',
'{{VAR}}_helper();'
],
[
'let {{VAR}} = (10, 20);',
'let sum = {{VAR}}.0 + {{VAR}}.1;',
'println!("sum = {}", sum);',
'if sum > 25 {',
' println!("big sum");',
'}',
],
[
'let {{VAR}} = 0;',
'while {{VAR}} < 3 {',
' {{VAR}} += 1;',
' println!("while loop: {}", {{VAR}});',
'}'
],
[
'let {{VAR}} = Some(100);',
'if let Some(val) = {{VAR}} {',
' println!("val = {}", val);',
'} else {',
' println!("no val");',
'}'
],
[
'let mut {{VAR}} = String::new();',
'{{VAR}}.push_str("junk");',
'{{VAR}}.push(\'_\');',
'println!("junk str: {}", {{VAR}});',
],
[
'let {{VAR}} = [0; 4];',
'println!("arr: {:?}", {{VAR}});',
],
[
'struct {{VAR}}Struct { x: i32, y: i32 }',
'let point = {{VAR}}Struct { x: 1, y: 2 };',
'println!("point.x = {}", point.x);'
],
];
function collectDeclarations(node, sourceCode) {
const nodeType = node.type;
if (nodeType === 'function_item') {
if (config.enableRenameIdentifiers) {
const fnNameNode = node.childForFieldName('name');
if (fnNameNode) {
const oldName = sourceCode.slice(fnNameNode.startIndex, fnNameNode.endIndex);
const newName = randomIdentSnakeCase('fn', 4);
renameMap.set(oldName, newName);
const paramsNode = node.childForFieldName('parameters');
if (paramsNode) {
for (let i = 0; i < paramsNode.childCount; i++) {
const child = paramsNode.child(i);
if (child.type === 'parameter') {
const patNode = child.childForFieldName('pattern');
if (patNode) {
const oldParamName = sourceCode.slice(
patNode.startIndex,
patNode.endIndex
);
if (/^[A-Za-z_]\w*$/.test(oldParamName)) {
const newParamName = randomIdentSnakeCase('prm', 3);
renameMap.set(oldParamName, newParamName);
}
}
}
}
}
}
}
} else if (nodeType === 'let_declaration') {
if (config.enableRenameIdentifiers) {
const patNode = node.childForFieldName('pattern');
if (patNode) {
const oldVarName = sourceCode.slice(patNode.startIndex, patNode.endIndex);
if (/^[A-Za-z_]\w*$/.test(oldVarName)) {
const newVarName = randomIdentSnakeCase('var', 4);
renameMap.set(oldVarName, newVarName);
}
}
}
} else if (nodeType === 'enum_item') {
if (config.enableRenameIdentifiers) {
const nameNode = node.childForFieldName('name');
if (nameNode) {
const oldEnumName = sourceCode.slice(nameNode.startIndex, nameNode.endIndex);
const newEnumName = randomIdentCamelCase('En', 4);
renameMap.set(oldEnumName, newEnumName);
}
const bodyNode = node.childForFieldName('body');
if (bodyNode) {
for (let i = 0; i < bodyNode.childCount; i++) {
const variant = bodyNode.child(i);
if (variant.type === 'enum_variant') {
const varNameNode = variant.childForFieldName('name');
if (varNameNode) {
const oldVariantName = sourceCode.slice(
varNameNode.startIndex,
varNameNode.endIndex
);
const newVariantName = randomIdentCamelCase('Var', 4);
renameMap.set(oldVariantName, newVariantName);
}
}
}
}
}
} else if (nodeType === 'struct_item') {
if (config.enableRenameIdentifiers) {
const structNameNode = node.childForFieldName('name');
if (structNameNode) {
const oldStructName = sourceCode.slice(
structNameNode.startIndex,
structNameNode.endIndex
);
const newStructName = randomIdentSnakeCase('st', 4);
renameMap.set(oldStructName, newStructName);
}
const bodyNode = node.childForFieldName('body');
if (bodyNode) {
for (let i = 0; i < bodyNode.childCount; i++) {
const fieldDecl = bodyNode.child(i);
if (fieldDecl.type === 'field_declaration') {
const fieldNameNode = fieldDecl.childForFieldName('name');
if (fieldNameNode) {
const oldFieldName = sourceCode.slice(
fieldNameNode.startIndex,
fieldNameNode.endIndex
);
if (/^[A-Za-z_]\w*$/.test(oldFieldName)) {
const newFieldName = randomIdentSnakeCase('fld', 4);
renameMap.set(oldFieldName, newFieldName);
}
}
}
}
}
}
}
for (let i = 0; i < node.childCount; i++) {
collectDeclarations(node.child(i), sourceCode);
}
}
function replaceIdentifiers(node, sourceCode, chunks) {
if (!config.enableRenameIdentifiers) {
return;
}
const nodeType = node.type;
if (
nodeType === 'identifier' ||
nodeType === 'field_identifier' ||
nodeType === 'type_identifier'
) {
const oldName = sourceCode.slice(node.startIndex, node.endIndex);
const newName = renameMap.get(oldName);
if (newName) {
chunks.push({
start: node.startIndex,
end: node.endIndex,
replacement: newName,
});
}
}
for (let i = 0; i < node.childCount; i++) {
replaceIdentifiers(node.child(i), sourceCode, chunks);
}
}
function applyReplacements(sourceCode, replacements) {
let result = '';
let currentPos = 0;
replacements.sort((a, b) => a.start - b.start);
for (const r of replacements) {
result += sourceCode.slice(currentPos, r.start);
result += r.replacement;
currentPos = r.end;
}
if (currentPos < sourceCode.length) {
result += sourceCode.slice(currentPos);
}
return result;
}
function generateOneJunkSnippet() {
const snippetIndex = Math.floor(Math.random() * junkSnippets.length);
const snippet = junkSnippets[snippetIndex];
const varName = randomIdentSnakeCase('junk', 2);
return snippet.map(line => line.replace(/{{VAR}}/g, varName));
}
function wrapJunkSnippetLines(snippetLines) {
return `
${snippetLines.join('\n ')}
`;
}
function collectFunctionBodies(node, functionNodes) {
if (node.type === 'function_item') {
const bodyNode = node.childForFieldName('body');
if (bodyNode && bodyNode.type === 'block') {
functionNodes.push(bodyNode);
}
}
for (let i = 0; i < node.childCount; i++) {
collectFunctionBodies(node.child(i), functionNodes);
}
}
function addJunkStatementsToFunctions(rootNode, sourceCode) {
if (!config.enableAddJunkStatements) {
return [];
}
let functionNodes = [];
collectFunctionBodies(rootNode, functionNodes);
const totalLines = sourceCode.split('\n').length;
const junkLinesTotal = Math.floor(totalLines * (config.junkRatio / 100));
if (junkLinesTotal < 1 || functionNodes.length === 0) {
return [];
}
let leftover = junkLinesTotal;
let replacements = [];
for (let i = 0; i < functionNodes.length; i++) {
if (leftover < 1) {
break;
}
const snippetLines = generateOneJunkSnippet();
const snippetSize = snippetLines.length;
if (snippetSize <= leftover) {
leftover -= snippetSize;
const startPos = functionNodes[i].startIndex + 1;
const junkBlock = wrapJunkSnippetLines(snippetLines);
replacements.push({
start: startPos,
end: startPos,
replacement: junkBlock,
});
}
}
return replacements;
}
function injectExtraCode(sourceCode) {
if (!config.enableInjection) {
return sourceCode;
}
const injection = `
// >>> Obfuscation extra code start
fn qyqo_a37() {
let mut ksr_ua02 = 0;
for i in 0..3 {
ksr_ua02 += i;
}
let gxn_lq82 = format!("HhcR_{}", ksr_ua02);
let _ = gxn_lq82;
}
fn ddn_tk19(x: u64) -> u64 {
let mut ksy_vj61 = x;
for _ in 0..5 {
ksy_vj61 = ksy_vj61.wrapping_add(1);
}
ksy_vj61
}
// >>> Obfuscation extra code end
`;
return injection + '\n' + sourceCode;
}
function insertAliasesAfterPrelude(lines) {
if (!config.enableAliases) {
return lines;
}
let inserted = false;
return lines.map((line) => {
if (!inserted && /^use\s+anchor_lang::prelude::\*;/.test(line)) {
inserted = true;
const alias1 = randomIdentSnakeCase('dgt', 2);
const alias2 = randomIdentSnakeCase('fkm', 2);
const alias3 = randomIdentSnakeCase('awp', 2);
const extra = [
`use std::collections::HashMap as ${alias1};`,
`use std::fmt::Write as ${alias2};`,
`use spl_token::instruction::AuthorityType as ${alias3};`,
].join('\n');
return line + '\n' + extra;
}
return line;
});
}
function renameProgramMod(lines) {
if (!config.enableRenameProgramMod) {
return lines;
}
let inProgramSection = false;
const randomModName = randomIdentSnakeCase('mod', 3);
return lines.map((line) => {
const trimmed = line.trim();
if (trimmed.startsWith('#[program]')) {
inProgramSection = true;
return line;
}
if (inProgramSection && trimmed.startsWith('mod ')) {
inProgramSection = false;
return line.replace(/mod\s+\w+\s*\{/, `mod ${randomModName} {`);
}
return line;
});
}
function minifyRustCode(sourceCode) {
const parser = new Parser();
parser.setLanguage(Rust);
const tree = parser.parse(sourceCode);
const tokens = [];
function traverse(node) {
for (let i = 0; i < node.childCount; i++) {
traverse(node.child(i));
}
if (node.childCount === 0) {
const text = sourceCode.slice(node.startIndex, node.endIndex);
if (node.type === 'comment') {
} else if (/^\s+$/.test(text)) {
} else {
tokens.push({ text, start: node.startIndex, end: node.endIndex });
}
}
}
traverse(tree.rootNode);
tokens.sort((a, b) => a.start - b.start);
let result = '';
const punctuation = /^[:;,\(\)\[\]\{\}\.<>\=\+\-\*\/&\|\^!%]+$/;
for (let i = 0; i < tokens.length; i++) {
if (i === 0) {
result += tokens[i].text;
continue;
}
const prev = tokens[i - 1].text;
const curr = tokens[i].text;
const needSpace = !punctuation.test(prev) && !punctuation.test(curr);
if (needSpace) {
result += ' ' + curr;
} else {
result += curr;
}
}
return result;
}
function obfuscateRustCodeWithAst(sourceCode) {
let modified = injectExtraCode(sourceCode);
let lines = modified.split('\n');
lines = insertAliasesAfterPrelude(lines);
lines = renameProgramMod(lines);
modified = lines.join('\n');
const parser1 = new Parser();
parser1.setLanguage(Rust);
const tree1 = parser1.parse(modified);
const junkReplacements = addJunkStatementsToFunctions(tree1.rootNode, modified);
let codeWithJunk = applyReplacements(modified, junkReplacements);
renameMap.clear();
const parser2 = new Parser();
parser2.setLanguage(Rust);
const tree2 = parser2.parse(codeWithJunk);
collectDeclarations(tree2.rootNode, codeWithJunk);
let renameReplacements = [];
replaceIdentifiers(tree2.rootNode, codeWithJunk, renameReplacements);
let finalCode = applyReplacements(codeWithJunk, renameReplacements);
if (config.enableMinify) {
finalCode = minifyRustCode(finalCode);
}
return finalCode;
}
function main() {
const args = process.argv.slice(2);
if (args.length < 2) {
console.error('Usage: node obfuscate-ast.js <input.rs> <output.rs>');
process.exit(1);
}
const [inputFile, outputFile] = args;
if (!fs.existsSync(inputFile)) {
console.error(`File not found: ${inputFile}`);
process.exit(1);
}
const sourceCode = fs.readFileSync(inputFile, 'utf8');
const obf = obfuscateRustCodeWithAst(sourceCode);
fs.writeFileSync(outputFile, obf, 'utf8');
console.log(`Obfuscated code saved to ${outputFile}`);
}
main();
.env:
Код:
ENABLE_INJECTION=true
ENABLE_ALIASES=true
ENABLE_RENAME_PROGRAM_MOD=true
ENABLE_ADD_JUNK_STATEMENTS=true
ENABLE_RENAME_IDENTIFIERS=true
SNAKE_CASE_PREFIX=obf
SNAKE_CASE_LENGTH=4
CAMEL_CASE_PREFIX=En
CAMEL_CASE_LENGTH=4
JUNK_LINES_MAX=5
JUNK_RATIO=20
ENABLE_MINIFY=true