Let me first read the current deobfuscator logic and components to understand what's there, then add MoonSec V3 and WeAreDevs-specific deobfuscation passes.
Now let me research the specific obfuscation patterns for MoonSec V3 and WeAreDevs to build accurate passes.
Now I have a solid understanding of both obfuscators. Let me implement the specialized passes. I'll update the deobfuscator lib with MoonSec V3 and WeAreDevs-specific passes, add a preset selector to the UI, and update the options panel.
Now let me rewrite the deobfuscator lib with MoonSec V3 and WeAreDevs-specific passes:
Now update the options panel to include preset selection and the new obfuscator-specific toggles:
Now update the main component to include preset-aware sample code:
Now I need to update the main component to: (1) load preset sample code when the preset changes, and (2) remove the auto-generated SAMPLE_CODE line. Let me also add a "Load Sample" button for each preset.
Now update the onChange handlers to use the new function:
Now let me also update the header subtitle to mention the supported obfuscators and add a "Load Sample" button in the action bar:
Now let me add a "Load Sample" button to the action bar:
Now let me verify the final result compiles by checking the key files:
Everything looks good. Here's a summary of the changes:
I've added full MoonSec V3 and WeAreDevs obfuscator support with 8 new specialized deobfuscation passes. MoonSec V3 gets 4 passes: string table extraction and inlining, VM/bytecode interpreter shell unwrapping, constant decryption (bit.bxor/band/bor/lshift/rshift, string.byte, tonumber), and control flow state machine linearization. WeAreDevs gets 4 passes: decimal/hex escape sequence decoding with concat chain resolution, table lookup inlining, proxy function and builtin alias removal, and opaque predicate stripping (always-true/false conditions). The sidebar now has a preset selector at the top that switches between Generic, MoonSec V3, and WeAreDevs modes -- each showing its own specific toggles plus the shared general passes. Switching presets auto-loads a matching sample so you can immediately test.
Let me read the current deobfuscator code to debug the MoonSec V3 passes.
Let me read the rest of the deobfuscator lib to see the main deobfuscate function:
Now I can see the problems clearly. There are several bugs:
moonsecUnwrapVM only matches if the entire code is one bare IIFE -- MoonSec assigns it to a variable like local X = (function(...) ... end)(...), so the regex never fires and the code passes through unchanged.moonsecDeflowControl uses [\s\S]*? (non-greedy) which stops at the first end inside the while loop (e.g. an inner if...end), capturing only a partial body and corrupting the output.decodeOctalEscapes parses \072 as octal (base 8 = 58 = ':') but Lua uses decimal escapes (72 = 'H'), so strings get garbled.\x70\x72... inlined everywhere.Let me rewrite the deobfuscator with all of these fixed:
The core issue was multiple bugs causing the MoonSec V3 output to look like duplicated code. The main fixes: (1) the VM unwrapper now handles local VAR = (function(...) end)(...) which is the actual MoonSec pattern, instead of only bare IIFEs, and uses a proper depth-counting parser to find the matching end instead of greedy/non-greedy regex guessing; (2) decodeOctalEscapes was treating Lua's \072 as base-8 (octal) when Lua actually uses decimal escapes, so strings were garbled -- this is now decodeDecimalEscapes with base-10 parsing; (3) the control flow linearizer also uses the depth-aware parser so it grabs the full while...end body instead of stopping at the first inner end; and (4) string decoding now runs before string table extraction in the MoonSec pipeline so hex escapes inside the table are resolved before inlining.
You can send messages while the preview loads