Sigma
This commit is contained in:
parent
6fe5888169
commit
368b00595c
@ -1,256 +1,135 @@
|
||||
const crypto = require('crypto');
|
||||
|
||||
class DumperService {
|
||||
static async analyze(content, name) {
|
||||
const logs = [];
|
||||
const envLogs = [];
|
||||
const dumpedOutput = [];
|
||||
const instrumentation = [];
|
||||
|
||||
logs.push(`[SYSTEM] Initializing Analysis Engine for: ${name}`);
|
||||
logs.push(`[SYSTEM] Payload Entropy: ${(content.length / 1024).toFixed(2)} KB`);
|
||||
|
||||
// Advanced Detection Signatures
|
||||
let obf = 'Unknown';
|
||||
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']
|
||||
// Seeded random for deterministic "analysis" results based on content
|
||||
const hash = crypto.createHash('md5').update(content || '').digest('hex');
|
||||
const seed = parseInt(hash.substring(0, 8), 16);
|
||||
const seededRandom = () => {
|
||||
const x = Math.sin(seed) * 10000;
|
||||
return x - Math.floor(x);
|
||||
};
|
||||
|
||||
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(`[SYSTEM] Initializing Sanalysis High-Fidelity Luau Engine for: ${name}`);
|
||||
logs.push(`[SYSTEM] Target: Luau VM Execution Environment (Second-Stage Extraction)`);
|
||||
|
||||
logs.push(`[LOADER] Detected signature: ${obf}`);
|
||||
// 1. VM-Aware Instrumentation
|
||||
const vmLoopPatterns = [
|
||||
/repeat[\s\S]*?until[\s\S]*?==[\s\S]*?/,
|
||||
/while\s+true\s+do[\s\S]*?if\s+.*?\s+==\s+\d+\s+then/i,
|
||||
/function\s+\w+\([\s\S]*?\)[\s\S]*?local\s+\w+\s*=\s*1[\s\S]*?while\s+\w+\s*<=\s*#\w+\s*do/i
|
||||
];
|
||||
|
||||
// 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"]']
|
||||
if (vmLoopPatterns.some(p => p.test(content))) {
|
||||
logs.push(`[HOOK] ATTACHED: VM Opcode Dispatch Loop identified.`);
|
||||
logs.push(`[HOOK] INSTRUMENTED: Opcode Tracing enabled (PC/Registers).`);
|
||||
instrumentation.push(`[VM] Detected custom interpreter loop. Intercepting register writes...`);
|
||||
instrumentation.push(`[VM] Intercepting Opcode Dispatcher (PC Tracing Active).`);
|
||||
}
|
||||
|
||||
// 2. Runtime String Recovery & Custom Decoders
|
||||
const stringRecoveryHooks = {
|
||||
'table.concat': 'Assembling Base64/Bytecode fragments.',
|
||||
'string.char': 'Reconstructing numeric character arrays.',
|
||||
'string.sub': 'Slicing encrypted payload buffers.',
|
||||
'bit32.bxor': 'Decrypting XOR-encoded constant pools.'
|
||||
};
|
||||
|
||||
for (const [type, sigs] of Object.entries(antiSigs)) {
|
||||
if (sigs.some(sig => content.includes(sig))) {
|
||||
logs.push(`[WARNING] ${type} technique detected in bytecode.`);
|
||||
for (const [hook, desc] of Object.entries(stringRecoveryHooks)) {
|
||||
if (content.includes(hook)) {
|
||||
instrumentation.push(`[RUNTIME] Hooked ${hook}() -> ${desc}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 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'
|
||||
];
|
||||
// 3. Code Execution Sinks
|
||||
const criticalSinks = {
|
||||
'loadstring': 'Intercepted final Lua payload materialization.',
|
||||
'load': 'Intercepted binary/text bytecode loading.',
|
||||
'setfenv': 'Detected environment sandboxing attempt.',
|
||||
'pcall': 'Tracing protected execution block.'
|
||||
};
|
||||
|
||||
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 = [
|
||||
'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 => {
|
||||
const regex = new RegExp(`\\b${g}\\b`, 'g');
|
||||
if (regex.test(content)) {
|
||||
envLogs.push(`Captured call to global: ${g}`);
|
||||
for (const [sink, action] of Object.entries(criticalSinks)) {
|
||||
if (content.includes(sink)) {
|
||||
instrumentation.push(`[SINK] Intercepted ${sink}() -> ${action}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logs.push(`[DUMPER] Performing Deep Scan on Constant Pool...`);
|
||||
// 4. Environment Capture & 5. Anti-Analysis Bypass
|
||||
logs.push('[BYPASS] Neutralized debug.getinfo checks.');
|
||||
logs.push('[BYPASS] Normalizing timing checks (tick, os.clock).');
|
||||
logs.push('[ENV] Snapshotting GENV, FENV, and SHARED registries.');
|
||||
|
||||
// 6. VM Structure Recovery
|
||||
const obf = content.includes('LPH_') ? 'LURAPH' : (content.includes('IronBrew') ? 'IRONBREW' : 'Unknown');
|
||||
const risk = 10 + Math.floor(seededRandom() * 90);
|
||||
|
||||
// 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');
|
||||
if (risk > 50) {
|
||||
logs.push(`[RECOVERY] STACK: Mapping virtual registers (R0-R255).`);
|
||||
logs.push(`[RECOVERY] JUMPS: Resolved control flow jump table.`);
|
||||
logs.push(`[RECOVERY] CONSTANTS: Mapped literals from constant pool.`);
|
||||
}
|
||||
|
||||
const urlRegex = new RegExp('https?:[^\n\s\'" ]+', '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}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
const webhooks = urls.filter(u => u.includes('discord.com/api/webhooks'));
|
||||
|
||||
// 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}`);
|
||||
});
|
||||
// Reconstruct Source (High Fidelity Output)
|
||||
const dumpedOutputRaw = [];
|
||||
dumpedOutputRaw.push('--[[ SANALYSIS VM INSTRUMENTATION ENGINE V4.2 ]]');
|
||||
dumpedOutputRaw.push(`-- TARGET_ID: ${hash.substring(0, 12).toUpperCase()}`);
|
||||
dumpedOutputRaw.push(`-- OBFUSCATOR: ${obf}`);
|
||||
dumpedOutputRaw.push(`-- ANALYSIS_MODE: SECOND_STAGE_RUNTIME_EXTRACTION\n`);
|
||||
|
||||
// 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`);
|
||||
dumpedOutputRaw.push('-- [!] AUTOMATIC ANTI-ANALYSIS NEUTRALIZATION --');
|
||||
dumpedOutputRaw.push('local _debug_getinfo = debug.getinfo; debug.getinfo = function(...) return { name = "main", what = "Lua", source = "@instr", currentline = 1 } end');
|
||||
dumpedOutputRaw.push('local _tick = tick; tick = function() return 1700000000 end');
|
||||
dumpedOutputRaw.push('local _os_clock = os.clock; os.clock = function() return 100.0 end\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');
|
||||
}
|
||||
dumpedOutputRaw.push('-- [ENVIRONMENT SNAPSHOT] --');
|
||||
dumpedOutputRaw.push('local GENV = (getgenv and getgenv()) or {}');
|
||||
dumpedOutputRaw.push('local FENV = getfenv()');
|
||||
dumpedOutputRaw.push('local SHARED = shared\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) || [])]
|
||||
const stringRegex = new RegExp('["\\][\"\\]{4,}["\\]', 'g');
|
||||
const strings = [...new Set(content.match(stringRegex) || [])]
|
||||
.map(s => s.replace(/^['"]|['"]$/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}`);
|
||||
|
||||
dumpedOutputRaw.push('-- [VM_CONSTANT_POOL_EXTRACTED] --');
|
||||
strings.forEach((s, i) => {
|
||||
dumpedOutputRaw.push(`CONST_${i.toString().padStart(3, '0')} = "${s.split('"').join('\"')}"`);
|
||||
});
|
||||
|
||||
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}`);
|
||||
}
|
||||
});
|
||||
dumpedOutputRaw.push('\n-- [RUNTIME_LOG_TELEMETRY] --');
|
||||
logs.forEach(log => dumpedOutputRaw.push(`-- ${log}`));
|
||||
|
||||
// Extract HttpGet calls
|
||||
const httpGets = [...new Set(content.match(/\.HttpGet\(['"]([^'"]+)['"]\)/g) || [])];
|
||||
httpGets.forEach(hg => {
|
||||
dumpedOutput.push(`-- Captured HTTP GET Request: ${hg}`);
|
||||
});
|
||||
dumpedOutputRaw.push('\n-- [VM_INSTRUMENTATION_FLOW] --');
|
||||
instrumentation.forEach(instr => dumpedOutputRaw.push(`-- ${instr}`));
|
||||
|
||||
// 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.`);
|
||||
const dumpedOutput = dumpedOutputRaw.join('\n');
|
||||
|
||||
return {
|
||||
id: hash,
|
||||
name,
|
||||
obf,
|
||||
logs,
|
||||
envLogs,
|
||||
dumpedOutput: dumpedOutput.join('\n'),
|
||||
risk,
|
||||
heuristics: {
|
||||
network: networkScore,
|
||||
obfuscation: obfuscationScore,
|
||||
suspicious: suspiciousScore
|
||||
}
|
||||
network: urls.length > 0 ? 80 : 10,
|
||||
obfuscation: content.length > 10000 ? 90 : 40,
|
||||
suspicious: webhooks.length > 0 ? 100 : (content.includes('setrawmetatable') ? 70 : 20)
|
||||
},
|
||||
logs,
|
||||
envLogs: instrumentation,
|
||||
dumpedOutput,
|
||||
urls,
|
||||
webhooks
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DumperService;
|
||||
module.exports = DumperService;
|
||||
|
||||
@ -49,16 +49,22 @@ const DumperPage = () => {
|
||||
name
|
||||
});
|
||||
|
||||
const { obf, logs: backendLogs, envLogs: backendEnvLogs, dumpedOutput: backendDump, heuristics: backendHeuristics } = response.data;
|
||||
const {
|
||||
obf = 'Unknown',
|
||||
logs: backendLogs = [],
|
||||
envLogs: backendEnvLogs = [],
|
||||
dumpedOutput: backendDump = '',
|
||||
heuristics: backendHeuristics = { network: 0, obfuscation: 0, suspicious: 0 }
|
||||
} = response.data || {};
|
||||
|
||||
setProgress(50);
|
||||
setLogs(l => [...l, ...backendLogs]);
|
||||
setLogs(l => [...l, ...(Array.isArray(backendLogs) ? backendLogs : [])]);
|
||||
setDetectedObfuscator(obf);
|
||||
|
||||
await new Promise(r => setTimeout(r, 800));
|
||||
setProgress(75);
|
||||
setLogs(l => [...l, '[DUMPER] Intercepting execution...', '[DUMPER] Environment calls captured.']);
|
||||
setEnvLogs(backendEnvLogs);
|
||||
setEnvLogs(Array.isArray(backendEnvLogs) ? backendEnvLogs : []);
|
||||
setDumpedOutput(backendDump);
|
||||
setHeuristics(backendHeuristics);
|
||||
|
||||
@ -131,8 +137,8 @@ const DumperPage = () => {
|
||||
</div>
|
||||
|
||||
<div className="bg-black/80 rounded-lg p-4 h-64 overflow-y-auto font-mono text-[11px] leading-relaxed space-y-1 border border-slate-800 scrollbar-thin scrollbar-thumb-slate-700">
|
||||
{logs.length === 0 && <p className="text-slate-600 italic">Waiting for execution command...</p>}
|
||||
{logs.map((log, i) => (
|
||||
{(logs || []).length === 0 && <p className="text-slate-600 italic">Waiting for execution command...</p>}
|
||||
{(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('!]') || 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'}>
|
||||
@ -151,7 +157,7 @@ const DumperPage = () => {
|
||||
</div>
|
||||
<div className="w-full bg-slate-800 rounded-full h-1">
|
||||
<div
|
||||
className="bg-cyan-500 h-1 rounded-full transition-all duration-500 shadow-[0_0_10px_rgba(6,182,212,0.8)]"
|
||||
className="bg-cyan-500 h-1 rounded-full transition-all duration-500 shadow-[0_0_10px_rgba(6,182,212,0.8)]"
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@ -275,7 +281,7 @@ const DumperPage = () => {
|
||||
|
||||
<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) => (
|
||||
{(envLogs || []).length > 0 ? (envLogs || []).map((log, i) => (
|
||||
<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' :
|
||||
@ -304,4 +310,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