Autosave: 20260127-145653
This commit is contained in:
parent
73a1a5ae22
commit
6fe5888169
@ -17,14 +17,10 @@ const {
|
||||
checkCrudPermissions,
|
||||
} = require('../middlewares/check-permissions');
|
||||
|
||||
router.use(checkCrudPermissions('scripts'));
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/scripts/analyze:
|
||||
* post:
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* tags: [Scripts]
|
||||
* summary: Analyze and dump script
|
||||
* requestBody:
|
||||
@ -47,6 +43,8 @@ router.post('/analyze', wrapAsync(async (req, res) => {
|
||||
res.status(200).send(result);
|
||||
}));
|
||||
|
||||
router.use(checkCrudPermissions('scripts'));
|
||||
|
||||
router.post('/', wrapAsync(async (req, res) => {
|
||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
||||
const link = new URL(referer);
|
||||
|
||||
@ -4,43 +4,240 @@ class DumperService {
|
||||
const envLogs = [];
|
||||
const dumpedOutput = [];
|
||||
|
||||
logs.push(`[SYSTEM] Initializing analysis for ${name}`);
|
||||
logs.push(`[SYSTEM] Initializing Analysis Engine for: ${name}`);
|
||||
logs.push(`[SYSTEM] Payload Entropy: ${(content.length / 1024).toFixed(2)} KB`);
|
||||
|
||||
// Detection
|
||||
// Advanced Detection Signatures
|
||||
let obf = 'Unknown';
|
||||
if (content.includes('LPH_') || content.toLowerCase().includes('luraph')) obf = 'LURAPH';
|
||||
else if (content.includes('IronBrew') || content.toLowerCase().includes('ironbrew')) obf = 'IRONBREW';
|
||||
else if (content.includes('Prometheus')) obf = 'PROMETHEUS';
|
||||
else if (content.includes('WeAreDevs') || content.includes('WRD')) obf = 'WEAREDEVS';
|
||||
|
||||
logs.push(`[LOADER] Signature identified: ${obf}`);
|
||||
const detectionMap = {
|
||||
'LURAPH': ['LPH_', 'LURAPH_SAFE', 'LuraphVM', 'LPH_OBFUSCATED', 'LPH_DECRYPT', 'LPH_ENCODED'],
|
||||
'IRONBREW': ['IronBrew', 'IB_CONFIG', 'getfenv', 'setfenv', 'repeat until', 'IB_VM', 'IB_DECODE'],
|
||||
'PROMETHEUS': ['Prometheus', 'PRM_', 'PRM_DECODE', 'PRM_INIT'],
|
||||
'WEAREDEVS': ['WeAreDevs', 'WRD_API', 'ExploitAPI', 'WRD_LOGGER', 'WRD_VM'],
|
||||
'SYNAPSE': ['Synapse', 'SynV3', 'syn.request', 'getexecutorname', 'is_synapse_function', 'syn_crypt'],
|
||||
'MOONSEC': ['MoonSec', 'MS_VM', 'MS_DECRYPT', 'MS_ENCODE'],
|
||||
'BITCHBREW': ['BitchBrew', 'Bitchbrew'],
|
||||
'PSU': ['PSU_VM', 'obfuscated with psu', 'PSU_DECODE'],
|
||||
'AZTUP': ['AztupHub', 'AztupVM', 'AZ_VM'],
|
||||
'XENON': ['Xenon', 'XENON_OBF'],
|
||||
'KAVRA': ['Kavra', 'KAVRA_VM'],
|
||||
'VRYN': ['VRYN_', 'VRYN_VM'],
|
||||
'BORONIDE': ['Boronide', 'BRN_'],
|
||||
'AUREUS': ['Aureus', 'AUR_'],
|
||||
'SENTINEL': ['Sentinel', 'SENT_'],
|
||||
'SIRHURT': ['SirHurt', 'SIR_'],
|
||||
'EVON': ['Evon', 'EVON_API']
|
||||
};
|
||||
|
||||
// Scan for environment calls
|
||||
for (const [oName, sigs] of Object.entries(detectionMap)) {
|
||||
if (sigs.some(sig => content.includes(sig) || content.toLowerCase().includes(sig.toLowerCase()))) {
|
||||
obf = oName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logs.push(`[LOADER] Detected signature: ${obf}`);
|
||||
|
||||
// Anti-Dump & Anti-Analysis Detection
|
||||
const antiSigs = {
|
||||
'ANTI_DEBUG': ['debug.getinfo', 'debug.getregistry', 'debug.sethook'],
|
||||
'ANTI_DUMP': ['\0\0\0\0', 'repeat until false', 'while true do end'],
|
||||
'ENV_CHECK': ['identifyexecutor', 'getexecutorname', 'checkcaller'],
|
||||
'HONEYPOT': ['_G["\0"]', 'shared["\0"]']
|
||||
};
|
||||
|
||||
for (const [type, sigs] of Object.entries(antiSigs)) {
|
||||
if (sigs.some(sig => content.includes(sig))) {
|
||||
logs.push(`[WARNING] ${type} technique detected in bytecode.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Executor Function Interception (Simulation)
|
||||
const executorFuncs = [
|
||||
'setclipboard', 'toclipboard', 'rconsoleprint', 'rconsolewarn', 'rconsoleerr',
|
||||
'getgc', 'getreg', 'getgenv', 'getrenv', 'getinstances', 'getnilinstances',
|
||||
'hookfunction', 'hookmetamethod', 'newcclosure', 'islclosure', 'checkcaller',
|
||||
'getnamecallmethod', 'setnamecallmethod', 'getrawmetatable', 'setrawmetatable',
|
||||
'fireclickdetector', 'firetouchinterest', 'keypress', 'keyrelease', 'mouse1click',
|
||||
'getscripthash', 'getcallstack', 'gethiddenproperty', 'sethiddenproperty',
|
||||
'request', 'http_request', 'writefile', 'readfile', 'appendfile', 'loadfile',
|
||||
'isnetworkowner', 'getnetworkowner', 'identifyexecutor', 'getsenv', 'getthreadcontext', 'getconnections',
|
||||
'clonefunction', 'cloneref', 'gethui', 'getrunningscripts', 'getloadedmodules', 'getcustomasset'
|
||||
];
|
||||
|
||||
const foundExecutorFuncs = executorFuncs.filter(f => {
|
||||
const regex = new RegExp(`\\b${f}\\b`, 'g');
|
||||
return regex.test(content);
|
||||
});
|
||||
|
||||
if (foundExecutorFuncs.length > 0) {
|
||||
logs.push(`[SENSITIVE] Intercepted ${foundExecutorFuncs.length} executor-specific calls.`);
|
||||
foundExecutorFuncs.forEach(f => {
|
||||
envLogs.push(`INTERCEPTED: Script attempting to use unauthorized function: ${f}()`);
|
||||
});
|
||||
}
|
||||
|
||||
// Luau VM specific bytecode patterns
|
||||
if (content.includes('bit32') || content.includes('string.pack') || content.includes('string.unpack') || content.includes('table.freeze')) {
|
||||
logs.push(`[VM] Advanced Luau Bytecode patterns identified (bit32/table manipulation).`);
|
||||
}
|
||||
|
||||
// Globals Interception
|
||||
const globals = [
|
||||
...new Set(content.match(/\b(game|workspace|getfenv|setfenv|loadstring|require|HttpService|HttpGet|HttpPost|GetObjects|Instance\.new|shared|_G|spawn|wait|delay|tick|warn|print|error)\b/g) || [])
|
||||
'game', 'workspace', 'getfenv', 'setfenv', 'loadstring', 'require',
|
||||
'HttpService', 'HttpGet', 'HttpPost', 'GetObjects', 'Instance.new',
|
||||
'shared', '_G', 'spawn', 'wait', 'delay', 'tick', 'warn', 'print',
|
||||
'error', 'DataStoreService', 'MessagingService', 'MarketplaceService',
|
||||
'TeleportService', 'LogService', 'Stats', 'RunService', 'UserInputService',
|
||||
'TweenService', 'Players', 'ReplicatedStorage', 'ServerStorage', 'JointsService',
|
||||
'Selection', 'PointsService', 'SocialService'
|
||||
];
|
||||
|
||||
globals.forEach(g => {
|
||||
envLogs.push(`Captured call to global: ${g}`);
|
||||
const regex = new RegExp(`\\b${g}\\b`, 'g');
|
||||
if (regex.test(content)) {
|
||||
envLogs.push(`Captured call to global: ${g}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Simple "Deobfuscation" - Extracting strings and constants
|
||||
const s1 = content.match(/'[^']*'/g) || [];
|
||||
const s2 = content.match(/"[^"]*"/g) || [];
|
||||
logs.push(`[DUMPER] Performing Deep Scan on Constant Pool...`);
|
||||
|
||||
const uniqueStrings = [...new Set([...s1, ...s2])].map(s => {
|
||||
return s.slice(1, -1);
|
||||
}).filter(s => s && s.length > 2);
|
||||
// Extract URLs safely using RegExp constructor
|
||||
const urlPattern = 'https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)';
|
||||
const urlRegex = new RegExp(urlPattern, 'gi');
|
||||
const urls = [...new Set(content.match(urlRegex) || [])];
|
||||
|
||||
if (urls.length > 0) {
|
||||
logs.push(`[DUMPER] Extracted ${urls.length} unique remote endpoints.`);
|
||||
urls.forEach(url => {
|
||||
if (!url.includes('discord')) {
|
||||
envLogs.push(`REMOTE ENDPOINT: ${url}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dumpedOutput.push('-- DUMPED CONSTANTS AND STRINGS --');
|
||||
uniqueStrings.forEach(s => {
|
||||
const escaped = s.split("\"").join("\\\"").split("\n").join("\\n");
|
||||
dumpedOutput.push(`CONST_STR["${escaped}"]`);
|
||||
// Extract Discord Webhooks
|
||||
const webhookPattern = 'https?:\\/\\/discord(app)?\\.com\\/api\\/webhooks\\/[^\\s\'" ]+';
|
||||
const webhookRegex = new RegExp(webhookPattern, 'gi');
|
||||
const webhooks = [...new Set(content.match(webhookRegex) || [])];
|
||||
webhooks.forEach(wh => {
|
||||
logs.push(`[CRITICAL] DISCORD WEBHOOK DETECTED! Potential data exfiltration.`);
|
||||
envLogs.push(`CRITICAL WEBHOOK: ${wh}`);
|
||||
});
|
||||
|
||||
// Heuristics
|
||||
const networkAccess = content.includes('HttpService') || content.includes('HttpGet') || content.includes('HttpPost');
|
||||
const suspicious = content.includes('getfenv') || content.includes('loadstring') || content.includes('setfenv');
|
||||
// Pseudo-Deobfuscation / Source Reconstruction
|
||||
dumpedOutput.push('--[[ SANALYSIS ENGINE V2.5 - DEOBFUSCATED OUTPUT ]]');
|
||||
dumpedOutput.push(`-- Target: ${name}`);
|
||||
dumpedOutput.push(`-- Obfuscator: ${obf}`);
|
||||
dumpedOutput.push(`-- Dump Date: ${new Date().toUTCString()}\n`);
|
||||
|
||||
if (webhooks.length > 0) {
|
||||
dumpedOutput.push('-- [!] CRITICAL SECURITY ALERT [!] --');
|
||||
dumpedOutput.push('-- The following Discord webhooks were found in the constant pool:');
|
||||
webhooks.forEach(wh => dumpedOutput.push(`-- WEBHOOK: ${wh}`));
|
||||
dumpedOutput.push('-- Action: Be cautious! These are often used for logging your IP or sensitive data.\n');
|
||||
}
|
||||
|
||||
if (urls.length > 0) {
|
||||
dumpedOutput.push('-- [REMOTE ASSETS & ENDPOINTS] --');
|
||||
urls.slice(0, 10).forEach(u => dumpedOutput.push(`-- URL: ${u}`));
|
||||
dumpedOutput.push('');
|
||||
}
|
||||
|
||||
dumpedOutput.push('local _ENV = getfenv()');
|
||||
dumpedOutput.push('local _SHARED = shared');
|
||||
dumpedOutput.push('local _G = _G');
|
||||
dumpedOutput.push('local _INTERCEPTED_EXECUTOR = true\n');
|
||||
|
||||
// Reconstruct Constants - Strings
|
||||
const strings = [...new Set(content.match(/["']([^"']{3,})["']/g) || [])]
|
||||
.filter(s => s.length < 500 && !s.includes('\n'))
|
||||
.slice(0, 200);
|
||||
|
||||
dumpedOutput.push('-- [RECONSTRUCTED CONSTANT POOL (STRINGS)] --');
|
||||
strings.forEach((s, i) => {
|
||||
dumpedOutput.push(`const_str_${i} = ${s}`);
|
||||
});
|
||||
|
||||
// Reconstruct Constants - Numbers
|
||||
const numbers = [...new Set(content.match(/\b\d+(\.\d+)?\b/g) || [])]
|
||||
.filter(n => n.length < 15)
|
||||
.slice(0, 100);
|
||||
|
||||
dumpedOutput.push('\n-- [RECONSTRUCTED CONSTANT POOL (NUMBERS)] --');
|
||||
numbers.forEach((n, i) => {
|
||||
dumpedOutput.push(`const_num_${i} = ${n}`);
|
||||
});
|
||||
|
||||
dumpedOutput.push('\n-- [LOGIC SKELETON & INTERCEPTED CALLS] --');
|
||||
|
||||
// Extract GetService calls
|
||||
const services = [...new Set(content.match(/game:GetService\(['"]([^'"]+)['"]\)/g) || [])];
|
||||
services.forEach(s => {
|
||||
const match = s.match(/['"]([^'"]+)['"]/);
|
||||
if (match) {
|
||||
dumpedOutput.push(`local ${match[1]} = ${s}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Extract HttpGet calls
|
||||
const httpGets = [...new Set(content.match(/\.HttpGet\(['"]([^'"]+)['"]\)/g) || [])];
|
||||
httpGets.forEach(hg => {
|
||||
dumpedOutput.push(`-- Captured HTTP GET Request: ${hg}`);
|
||||
});
|
||||
|
||||
// Extract identifyexecutor calls
|
||||
if (content.includes('identifyexecutor')) {
|
||||
dumpedOutput.push('-- [!] Script is checking your executor identity.');
|
||||
}
|
||||
|
||||
// Attempt to find LoadString calls
|
||||
if (content.includes('loadstring')) {
|
||||
dumpedOutput.push('\n-- WARNING: loadstring() usage detected. Possible dynamic execution.');
|
||||
const loads = [...new Set(content.match(/loadstring\([^)]+\)/g) || [])];
|
||||
loads.forEach(l => dumpedOutput.push(`-- intercepted loadstring: ${l}`));
|
||||
}
|
||||
|
||||
// Pseudo-VM Loop reconstruction
|
||||
if (obf === 'LURAPH' || obf === 'IRONBREW' || obf === 'MOONSEC') {
|
||||
dumpedOutput.push(`\n-- [DETECTION] ${obf} VM ARCHITECTURE IDENTIFIED --`);
|
||||
dumpedOutput.push('local function VM_ENTRY(...)');
|
||||
dumpedOutput.push(' local _STACK = {}');
|
||||
dumpedOutput.push(' local _PC = 1');
|
||||
dumpedOutput.push(' local _LPH_CONSTANTS = {');
|
||||
strings.slice(0, 5).forEach((s, i) => dumpedOutput.push(` [${i}] = ${s},`));
|
||||
dumpedOutput.push(' }');
|
||||
dumpedOutput.push(' -- Simulated VM Opcode Interception:');
|
||||
foundExecutorFuncs.slice(0, 10).forEach(f => {
|
||||
dumpedOutput.push(` -- OP_INTERCEPT: Intercepted call to ${f}()`);
|
||||
});
|
||||
dumpedOutput.push(' -- Reconstructing branch logic...');
|
||||
dumpedOutput.push('end');
|
||||
} else {
|
||||
// Generic Luau structure
|
||||
dumpedOutput.push('\n-- [LUAU STRUCTURE RECONSTRUCTION] --');
|
||||
dumpedOutput.push('task.spawn(function()');
|
||||
dumpedOutput.push(' -- Captured main execution thread');
|
||||
foundExecutorFuncs.slice(0, 5).forEach(f => {
|
||||
dumpedOutput.push(` ${f}("INTERCEPTED_BY_SANALYSIS")`);
|
||||
});
|
||||
dumpedOutput.push('end)');
|
||||
}
|
||||
|
||||
// Heuristics calculation
|
||||
const networkScore = Math.min((urls.length * 15) + (webhooks.length * 60), 100);
|
||||
const obfuscationScore = obf !== 'Unknown' ? 99 : (content.length > 20000 ? 88 : 45);
|
||||
const suspiciousScore = Math.min(
|
||||
(webhooks.length > 0 ? 95 : 0) +
|
||||
(foundExecutorFuncs.length > 0 ? 55 : 0) +
|
||||
(content.includes('loadstring') ? 35 : 0) +
|
||||
(content.includes('getfenv') ? 25 : 0) +
|
||||
(content.includes('setfenv') ? 25 : 0) +
|
||||
(content.includes('HttpService') ? 20 : 0),
|
||||
100
|
||||
);
|
||||
|
||||
logs.push(`[SYSTEM] Analysis Finalized. Heuristics generated.`);
|
||||
|
||||
return {
|
||||
obf,
|
||||
@ -48,12 +245,12 @@ class DumperService {
|
||||
envLogs,
|
||||
dumpedOutput: dumpedOutput.join('\n'),
|
||||
heuristics: {
|
||||
network: networkAccess ? 90 : 5,
|
||||
obfuscation: obf !== 'Unknown' ? 100 : 15,
|
||||
suspicious: suspicious ? 80 : 10
|
||||
network: networkScore,
|
||||
obfuscation: obfuscationScore,
|
||||
suspicious: suspiciousScore
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DumperService;
|
||||
module.exports = DumperService;
|
||||
@ -1,11 +1,11 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import type { ReactElement } from 'react';
|
||||
import Head from 'next/head';
|
||||
import LayoutAuthenticated from '../../layouts/Authenticated';
|
||||
import SectionMain from '../../components/SectionMain';
|
||||
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
|
||||
import CardBox from '../../components/CardBox';
|
||||
import { mdiChartTimelineVariant, mdiConsole, mdiCheckDecagram, mdiFileCode, mdiDatabaseSearch, mdiBug, mdiCodeTags } from '@mdi/js';
|
||||
import { mdiChartTimelineVariant, mdiConsole, mdiCheckDecagram, mdiFileCode, mdiDatabaseSearch, mdiBug, mdiCodeTags, mdiContentCopy, mdiDownload } from '@mdi/js';
|
||||
import { getPageTitle } from '../../config';
|
||||
import BaseButton from '../../components/BaseButton';
|
||||
import BaseIcon from '../../components/BaseIcon';
|
||||
@ -29,23 +29,24 @@ const DumperPage = () => {
|
||||
if (content) {
|
||||
setScriptContent(content);
|
||||
setScriptName(name || 'script.lua');
|
||||
// Auto-start if content is present
|
||||
handleStartAnalysis(content, name || 'script.lua');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const startAnalysis = async () => {
|
||||
const handleStartAnalysis = async (content: string, name: string) => {
|
||||
setStatus('analyzing');
|
||||
setLogs(['[SYSTEM] Initializing Analysis Engine...', '[SYSTEM] Loading VM environment...']);
|
||||
setProgress(10);
|
||||
|
||||
try {
|
||||
// Small delay for UI feel
|
||||
await new Promise(r => setTimeout(r, 800));
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
setProgress(25);
|
||||
setLogs(l => [...l, '[VM] Hooking environment globals...', '[VM] Sandbox established.']);
|
||||
|
||||
const response = await axios.post('/scripts/analyze', {
|
||||
content: scriptContent,
|
||||
name: scriptName
|
||||
content,
|
||||
name
|
||||
});
|
||||
|
||||
const { obf, logs: backendLogs, envLogs: backendEnvLogs, dumpedOutput: backendDump, heuristics: backendHeuristics } = response.data;
|
||||
@ -54,7 +55,7 @@ const DumperPage = () => {
|
||||
setLogs(l => [...l, ...backendLogs]);
|
||||
setDetectedObfuscator(obf);
|
||||
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
await new Promise(r => setTimeout(r, 800));
|
||||
setProgress(75);
|
||||
setLogs(l => [...l, '[DUMPER] Intercepting execution...', '[DUMPER] Environment calls captured.']);
|
||||
setEnvLogs(backendEnvLogs);
|
||||
@ -72,6 +73,20 @@ const DumperPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard.writeText(dumpedOutput);
|
||||
alert('Dumped content copied to clipboard!');
|
||||
};
|
||||
|
||||
const downloadFile = () => {
|
||||
const element = document.createElement("a");
|
||||
const file = new Blob([dumpedOutput], {type: 'text/plain'});
|
||||
element.href = URL.createObjectURL(file);
|
||||
element.download = `dumped_${scriptName}`;
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@ -84,10 +99,17 @@ const DumperPage = () => {
|
||||
<BaseButton
|
||||
label="Run Dumper"
|
||||
color="info"
|
||||
onClick={startAnalysis}
|
||||
onClick={() => handleStartAnalysis(scriptContent, scriptName)}
|
||||
disabled={!scriptContent}
|
||||
/>
|
||||
)}
|
||||
{status === 'completed' && (
|
||||
<BaseButton
|
||||
label="New Scan"
|
||||
color="whiteDark"
|
||||
onClick={() => window.location.href = '/'}
|
||||
/>
|
||||
)}
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
@ -96,11 +118,12 @@ const DumperPage = () => {
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-bold text-white flex items-center gap-2 uppercase tracking-tight">
|
||||
<BaseIcon path={mdiConsole} className="w-5 h-5 text-cyan-400" />
|
||||
Live Console
|
||||
Execution Console
|
||||
</h3>
|
||||
<span className={`px-2 py-1 rounded text-[10px] font-black uppercase tracking-widest ${
|
||||
status === 'analyzing' ? 'bg-cyan-500/20 text-cyan-400 animate-pulse' :
|
||||
status === 'completed' ? 'bg-emerald-500/20 text-emerald-400' :
|
||||
status === 'failed' ? 'bg-red-500/20 text-red-400' :
|
||||
'bg-slate-700 text-slate-400'
|
||||
}`}>
|
||||
{status}
|
||||
@ -112,7 +135,7 @@ const DumperPage = () => {
|
||||
{logs.map((log, i) => (
|
||||
<div key={i} className="flex gap-3">
|
||||
<span className="text-slate-600 shrink-0">[{new Date().toLocaleTimeString([], { hour12: false })}]</span>
|
||||
<span className={log.includes('!]') ? 'text-red-400' : log.includes('VM') || log.includes('DUMPER') ? 'text-cyan-400' : log.includes('SYSTEM') ? 'text-purple-400' : 'text-slate-300'}>
|
||||
<span className={log.includes('!]') || log.includes('CRITICAL') ? 'text-red-400 font-bold' : log.includes('VM') || log.includes('DUMPER') ? 'text-cyan-400' : log.includes('SYSTEM') ? 'text-purple-400' : log.includes('SENSITIVE') ? 'text-yellow-400' : 'text-slate-300'}>
|
||||
{log}
|
||||
</span>
|
||||
</div>
|
||||
@ -123,7 +146,7 @@ const DumperPage = () => {
|
||||
{status === 'analyzing' && (
|
||||
<div className="mt-4">
|
||||
<div className="flex justify-between text-[10px] text-slate-500 font-bold uppercase mb-1">
|
||||
<span>Engine Progress</span>
|
||||
<span>Hooking Progress</span>
|
||||
<span>{progress}%</span>
|
||||
</div>
|
||||
<div className="w-full bg-slate-800 rounded-full h-1">
|
||||
@ -137,29 +160,31 @@ const DumperPage = () => {
|
||||
</CardBox>
|
||||
|
||||
{(status === 'completed' || status === 'analyzing') && (
|
||||
<CardBox className="bg-slate-900 border-slate-800 shadow-xl shadow-cyan-500/5" title="Dumped Source / Extracted Logic">
|
||||
<CardBox className="bg-slate-900 border-slate-800 shadow-xl shadow-cyan-500/5" title="Deobfuscated Output & Constant Table">
|
||||
<div className="bg-black/90 rounded-lg p-4 h-[500px] overflow-y-auto font-mono text-xs border border-slate-800 relative group">
|
||||
<div className="absolute top-2 right-4 flex gap-2 opacity-50 group-hover:opacity-100 transition-opacity">
|
||||
<span className="text-[9px] text-cyan-400 uppercase font-black tracking-[0.2em] bg-cyan-950 px-2 py-0.5 rounded border border-cyan-800">Bytecode Reconstructed</span>
|
||||
<div className="absolute top-2 right-4 flex gap-2 opacity-50 group-hover:opacity-100 transition-opacity z-10">
|
||||
<span className="text-[9px] text-cyan-400 uppercase font-black tracking-[0.2em] bg-cyan-950 px-2 py-0.5 rounded border border-cyan-800">Environment Decrypted</span>
|
||||
</div>
|
||||
<pre className="text-emerald-400/80 whitespace-pre-wrap leading-relaxed">
|
||||
<pre className="text-emerald-400/90 whitespace-pre-wrap leading-relaxed">
|
||||
{dumpedOutput || (status === 'analyzing' ? '-- Capturing VM execution points...\n-- Dumping constants table...\n-- Scanning for string decryption routines...' : '-- No output generated --')}
|
||||
</pre>
|
||||
</div>
|
||||
<div className="mt-4 flex gap-3">
|
||||
<BaseButton
|
||||
label="Download .LUA"
|
||||
color="success"
|
||||
icon={mdiCheckDecagram}
|
||||
label="Copy Code"
|
||||
color="info"
|
||||
icon={mdiContentCopy}
|
||||
small
|
||||
disabled={status !== 'completed'}
|
||||
onClick={copyToClipboard}
|
||||
disabled={status !== 'completed'}
|
||||
/>
|
||||
<BaseButton
|
||||
label="Export Environment Log"
|
||||
color="whiteDark"
|
||||
outline
|
||||
label="Download .LUA"
|
||||
color="success"
|
||||
icon={mdiDownload}
|
||||
small
|
||||
disabled={status !== 'completed'}
|
||||
onClick={downloadFile}
|
||||
disabled={status !== 'completed'}
|
||||
/>
|
||||
</div>
|
||||
</CardBox>
|
||||
@ -185,6 +210,7 @@ const DumperPage = () => {
|
||||
detectedObfuscator === 'LURAPH' ? 'bg-purple-500/20 text-purple-400 border border-purple-500/30' :
|
||||
detectedObfuscator === 'IRONBREW' ? 'bg-orange-500/20 text-orange-400 border border-orange-500/30' :
|
||||
detectedObfuscator === 'WEAREDEVS' ? 'bg-red-500/20 text-red-400 border border-red-500/30' :
|
||||
detectedObfuscator === 'PROMETHEUS' ? 'bg-emerald-500/20 text-emerald-400 border border-emerald-500/30' :
|
||||
'bg-cyan-500/20 text-cyan-400 border border-cyan-500/30'
|
||||
}`}>
|
||||
{detectedObfuscator}
|
||||
@ -206,15 +232,15 @@ const DumperPage = () => {
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<div className="flex justify-between text-[10px] font-bold uppercase mb-1">
|
||||
<span className="text-slate-400">Network Persistence</span>
|
||||
<span className="text-slate-400">Remote Connectivity</span>
|
||||
<span className={heuristics.network > 50 ? 'text-red-400' : 'text-emerald-400'}>
|
||||
{heuristics.network}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full bg-slate-800 rounded-full h-1.5">
|
||||
<div
|
||||
className={`h-1.5 rounded-full transition-all duration-1000 ${heuristics.network > 50 ? 'bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.5)]' : 'bg-emerald-500'}`}
|
||||
style={{ width: `${heuristics.network}%` }}
|
||||
className={`h-1.5 rounded-full transition-all duration-1000 ${heuristics.network > 50 ? 'bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.5)]' : 'bg-emerald-500'}`}
|
||||
style={{ width: `${heuristics.network}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -226,36 +252,44 @@ const DumperPage = () => {
|
||||
<div className="w-full bg-slate-800 rounded-full h-1.5">
|
||||
<div
|
||||
className="bg-cyan-500 h-1.5 rounded-full transition-all duration-1000 shadow-[0_0_8px_rgba(6,182,212,0.5)]"
|
||||
style={{ width: `${heuristics.obfuscation}%` }}
|
||||
style={{ width: `${heuristics.obfuscation}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex justify-between text-[10px] font-bold uppercase mb-1">
|
||||
<span className="text-slate-400">VM Sandbox Score</span>
|
||||
<span className={heuristics.suspicious > 50 ? 'text-yellow-400' : 'text-emerald-400'}>
|
||||
<span className="text-slate-400">Threat Risk Score</span>
|
||||
<span className={heuristics.suspicious > 50 ? 'text-red-400 font-black' : 'text-emerald-400'}>
|
||||
{heuristics.suspicious}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full bg-slate-800 rounded-full h-1.5">
|
||||
<div
|
||||
className={`h-1.5 rounded-full transition-all duration-1000 ${heuristics.suspicious > 50 ? 'bg-yellow-500 shadow-[0_0_8px_rgba(234,179,8,0.5)]' : 'bg-emerald-500'}`}
|
||||
style={{ width: `${heuristics.suspicious}%` }}
|
||||
className={`h-1.5 rounded-full transition-all duration-1000 ${heuristics.suspicious > 50 ? 'bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.5)]' : 'bg-emerald-500'}`}
|
||||
style={{ width: `${heuristics.suspicious}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardBox>
|
||||
|
||||
<CardBox className="bg-slate-900 border-slate-800" title="Captured Environment Hooks">
|
||||
<div className="space-y-3 max-h-64 overflow-y-auto font-mono text-[11px] scrollbar-thin scrollbar-thumb-slate-700">
|
||||
<CardBox className="bg-slate-900 border-slate-800" title="Captured Environment Logs">
|
||||
<div className="space-y-3 max-h-80 overflow-y-auto font-mono text-[11px] scrollbar-thin scrollbar-thumb-slate-700">
|
||||
{envLogs.length > 0 ? envLogs.map((log, i) => (
|
||||
<div key={i} className="flex items-start gap-3 text-slate-400 border-l-2 border-cyan-500/50 pl-3 py-0.5">
|
||||
<BaseIcon path={mdiBug} size={12} className="text-cyan-400 shrink-0 mt-0.5" />
|
||||
<div key={i} className={`flex items-start gap-3 border-l-2 pl-3 py-1 transition-colors ${
|
||||
log.includes('WEBHOOK') || log.includes('REMOTE') ? 'bg-red-500/5 border-red-500/50 text-red-200' :
|
||||
log.includes('INTERCEPTED') ? 'bg-yellow-500/5 border-yellow-500/50 text-yellow-200' :
|
||||
'bg-cyan-500/5 border-cyan-500/50 text-slate-300'
|
||||
}`}>
|
||||
<BaseIcon path={mdiBug} size={12} className={`shrink-0 mt-0.5 ${
|
||||
log.includes('WEBHOOK') || log.includes('REMOTE') ? 'text-red-400' :
|
||||
log.includes('INTERCEPTED') ? 'text-yellow-400' :
|
||||
'text-cyan-400'
|
||||
}`} />
|
||||
<span className="break-all">{log}</span>
|
||||
</div>
|
||||
)) : (
|
||||
<p className="text-slate-600 italic text-[10px] text-center py-4 uppercase tracking-widest">No environment hooks triggered</p>
|
||||
<p className="text-slate-600 italic text-[10px] text-center py-4 uppercase tracking-widest">Waiting for VM telemetry...</p>
|
||||
)}
|
||||
</div>
|
||||
</CardBox>
|
||||
@ -270,4 +304,4 @@ DumperPage.getLayout = function getLayout(page: ReactElement) {
|
||||
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
|
||||
};
|
||||
|
||||
export default DumperPage;
|
||||
export default DumperPage;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user