js_deobfuscator/core/config.rs
1//! Configuration types for the deobfuscation engine.
2
3// ============================================================================
4// LogLevel
5// ============================================================================
6
7/// Log level for engine output.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
9pub enum LogLevel {
10 /// No logging.
11 Off,
12 /// Errors only.
13 Error,
14 /// Warnings and errors.
15 Warn,
16 /// Informational messages.
17 #[default]
18 Info,
19 /// Debug messages.
20 Debug,
21 /// Trace-level messages.
22 Trace,
23}
24
25// ============================================================================
26// EcmaConfig
27// ============================================================================
28
29/// Fine-grained ECMA layer configuration.
30#[derive(Debug, Clone)]
31pub struct EcmaConfig {
32 /// Enable operator passes (+, -, *, /, etc.).
33 pub operators: bool,
34 /// Enable String.prototype method passes.
35 pub string: bool,
36 /// Enable Array.prototype method passes.
37 pub array: bool,
38 /// Enable Number method passes.
39 pub number: bool,
40 /// Enable Math method passes.
41 pub math: bool,
42 /// Enable Object method passes.
43 pub object: bool,
44 /// Enable JSON method passes.
45 pub json: bool,
46 /// Enable RegExp method passes.
47 pub regexp: bool,
48 /// Enable URI function passes.
49 pub uri: bool,
50 /// Enable type coercion passes (JSFuck patterns).
51 pub coercion: bool,
52 /// Enable syntax simplification passes.
53 pub syntax: bool,
54 /// Enable control flow simplification passes.
55 pub control: bool,
56 /// Enable dead code removal passes.
57 pub dead: bool,
58}
59
60impl Default for EcmaConfig {
61 fn default() -> Self {
62 Self::all()
63 }
64}
65
66impl EcmaConfig {
67 /// Enable all ECMA passes.
68 pub fn all() -> Self {
69 Self {
70 operators: true,
71 string: true,
72 array: true,
73 number: true,
74 math: true,
75 object: true,
76 json: true,
77 regexp: true,
78 uri: true,
79 coercion: true,
80 syntax: true,
81 control: true,
82 dead: true,
83 }
84 }
85
86 /// Disable all ECMA passes.
87 pub fn none() -> Self {
88 Self {
89 operators: false,
90 string: false,
91 array: false,
92 number: false,
93 math: false,
94 object: false,
95 json: false,
96 regexp: false,
97 uri: false,
98 coercion: false,
99 syntax: false,
100 control: false,
101 dead: false,
102 }
103 }
104}
105
106// ============================================================================
107// RuntimeConfig
108// ============================================================================
109
110/// Fine-grained Runtime layer configuration.
111#[derive(Debug, Clone)]
112pub struct RuntimeConfig {
113 /// Enable encoding passes (atob, btoa).
114 pub encoding: bool,
115 /// Enable deprecated API passes (escape, unescape).
116 pub deprecated: bool,
117}
118
119impl Default for RuntimeConfig {
120 fn default() -> Self {
121 Self::all()
122 }
123}
124
125impl RuntimeConfig {
126 /// Enable all Runtime passes.
127 pub fn all() -> Self {
128 Self {
129 encoding: true,
130 deprecated: true,
131 }
132 }
133
134 /// Disable all Runtime passes.
135 pub fn none() -> Self {
136 Self {
137 encoding: false,
138 deprecated: false,
139 }
140 }
141}
142
143// ============================================================================
144// ExtensionsConfig
145// ============================================================================
146
147/// Fine-grained Extensions layer configuration.
148#[derive(Debug, Clone, Default)]
149pub struct ExtensionsConfig {
150 /// Enable string array decoder.
151 pub string_array: bool,
152 /// Enable control flow deflattener.
153 pub control_flow: bool,
154 /// Enable proxy function inliner.
155 pub proxy: bool,
156}
157
158impl ExtensionsConfig {
159 /// Enable all extension patterns.
160 pub fn all() -> Self {
161 Self {
162 string_array: true,
163 control_flow: true,
164 proxy: true,
165 }
166 }
167
168 /// Disable all extension patterns.
169 pub fn none() -> Self {
170 Self {
171 string_array: false,
172 control_flow: false,
173 proxy: false,
174 }
175 }
176}
177
178// ============================================================================
179// LayerConfig
180// ============================================================================
181
182/// Layer enable/disable configuration.
183#[derive(Debug, Clone)]
184pub struct LayerConfig {
185 /// Enable ECMA layer (recommended: always true).
186 pub ecma: bool,
187 /// Enable Runtime layer (browser/Node APIs).
188 pub runtime: bool,
189 /// Enable Extensions layer (obfuscator patterns).
190 pub extensions: bool,
191 /// Fine-grained ECMA configuration.
192 pub ecma_config: EcmaConfig,
193 /// Fine-grained Runtime configuration.
194 pub runtime_config: RuntimeConfig,
195 /// Fine-grained Extensions configuration.
196 pub extensions_config: ExtensionsConfig,
197}
198
199impl Default for LayerConfig {
200 fn default() -> Self {
201 Self {
202 ecma: true,
203 runtime: true,
204 extensions: false, // Opt-in for obfuscator-specific patterns
205 ecma_config: EcmaConfig::default(),
206 runtime_config: RuntimeConfig::default(),
207 extensions_config: ExtensionsConfig::default(),
208 }
209 }
210}
211
212impl LayerConfig {
213 /// Create config with all layers enabled.
214 pub fn all() -> Self {
215 Self {
216 ecma: true,
217 runtime: true,
218 extensions: true,
219 ecma_config: EcmaConfig::all(),
220 runtime_config: RuntimeConfig::all(),
221 extensions_config: ExtensionsConfig::all(),
222 }
223 }
224
225 /// Create config with only ECMA layer (pure ECMAScript).
226 pub fn ecma_only() -> Self {
227 Self {
228 ecma: true,
229 runtime: false,
230 extensions: false,
231 ecma_config: EcmaConfig::all(),
232 runtime_config: RuntimeConfig::none(),
233 extensions_config: ExtensionsConfig::none(),
234 }
235 }
236}
237
238// ============================================================================
239// EngineConfig
240// ============================================================================
241
242/// Engine configuration.
243#[derive(Debug, Clone)]
244pub struct EngineConfig {
245 /// Maximum iterations before stopping.
246 pub max_iterations: usize,
247 /// Layer configuration.
248 pub layers: LayerConfig,
249 /// Log level.
250 pub log_level: LogLevel,
251}
252
253impl Default for EngineConfig {
254 fn default() -> Self {
255 Self {
256 max_iterations: 100,
257 layers: LayerConfig::default(),
258 log_level: LogLevel::Info,
259 }
260 }
261}
262
263impl EngineConfig {
264 /// Create minimal config (ECMA operators only).
265 pub fn minimal() -> Self {
266 Self {
267 layers: LayerConfig {
268 ecma: true,
269 runtime: false,
270 extensions: false,
271 ecma_config: EcmaConfig {
272 operators: true,
273 ..EcmaConfig::none()
274 },
275 runtime_config: RuntimeConfig::none(),
276 extensions_config: ExtensionsConfig::none(),
277 },
278 ..Default::default()
279 }
280 }
281
282 /// Create standard config (ECMA + Runtime).
283 pub fn standard() -> Self {
284 Self::default()
285 }
286
287 /// Create full config (all layers enabled).
288 pub fn full() -> Self {
289 Self {
290 layers: LayerConfig::all(),
291 ..Default::default()
292 }
293 }
294
295 /// Create aggressive config (full + high iterations).
296 pub fn aggressive() -> Self {
297 Self {
298 max_iterations: 200,
299 layers: LayerConfig::all(),
300 ..Default::default()
301 }
302 }
303
304 /// Set max iterations.
305 #[must_use]
306 pub fn with_max_iterations(mut self, max: usize) -> Self {
307 self.max_iterations = max;
308 self
309 }
310
311 /// Set layer configuration.
312 #[must_use]
313 pub fn with_layers(mut self, layers: LayerConfig) -> Self {
314 self.layers = layers;
315 self
316 }
317
318 /// Set log level.
319 #[must_use]
320 pub fn with_log_level(mut self, level: LogLevel) -> Self {
321 self.log_level = level;
322 self
323 }
324}