codedefender_config/
lib.rs

1//! `codedefender-config` provides the Rust data structures used for serializing and deserializing
2//! CodeDefender YAML configuration files and analysis results. These structures are used by both
3//! the CodeDefender CLI and its backend services.
4//!
5//! This crate is intended to be consumed by tools that integrate with or generate CodeDefender config files.
6
7use serde::{Deserialize, Serialize};
8
9/// Current supported YAML config version.
10pub const YAML_CONFIG_VERSION: &str = "1.0.2";
11
12/// Available SIMD extension types used by mutation engines.
13#[derive(Debug, Serialize, Deserialize, Clone)]
14pub enum MutationEngineExtension {
15    /// Generic (no special SIMD usage)
16    Generic,
17    /// SSE-enabled
18    SSE,
19}
20
21/// Supported PE environments.
22#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
23pub enum PeEnvironment {
24    /// User-mode PE (exe, dll)
25    UserMode,
26    /// Kernel-mode PE (sys)
27    KernelMode,
28    /// UEFI firmware image
29    UEFI,
30}
31
32/// Configuration settings for lifting x86 instructions into IR.
33#[derive(Debug, Serialize, Deserialize, Clone)]
34pub struct LifterSettings {
35    /// Whether to lift calls into IR.
36    pub lift_calls: bool,
37    /// Calling convention used for lifting, only `WindowsAbi`, and `Conservative` are supported.
38    pub calling_convention: String,
39    /// Max stack copy size in bytes when lifting.
40    pub max_stack_copy_size: u32,
41    /// Fallback: split on calls if lifting fails.
42    pub split_on_calls_fallback: bool,
43}
44
45/// IR optimization settings.
46#[derive(Debug, Serialize, Deserialize, Clone)]
47pub struct OptimizationSettings {
48    /// Enable constant propagation.
49    pub constant_propagation: bool,
50    /// Enable instruction combining.
51    pub instruction_combine: bool,
52    /// Enable dead code elimination.
53    pub dead_code_elim: bool,
54    /// Enable pruning of unused block parameters.
55    pub prune_useless_block_params: bool,
56    /// Number of optimization iterations to run.
57    pub iterations: u32,
58}
59
60/// Assembler-level codegen settings.
61#[derive(Debug, Serialize, Deserialize, Clone)]
62pub struct AssemblerSettings {
63    /// Whether to shuffle basic blocks.
64    pub shuffle_basic_blocks: bool,
65    /// Instruction prefix to prepend to emitted instructions.
66    pub instruction_prefix: String,
67    /// Chance of randomly applying the prefix.
68    pub random_prefix_chance: f64,
69}
70
71/// Compiler configuration (IR + codegen) for a profile.
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct CDCompilerSettings {
74    /// Assembler settings.
75    pub assembler_settings: AssemblerSettings,
76    /// Optimization settings.
77    pub optimization_settings: OptimizationSettings,
78    /// IR lifter settings.
79    pub lifter_settings: LifterSettings,
80}
81
82/// Fake PDB string settings to confuse debuggers.
83#[derive(Default, Debug, Serialize, Deserialize)]
84pub struct FakePdbString {
85    /// Whether the fake PDB string is enabled.
86    pub enabled: bool,
87    /// Value to emit as the fake PDB string.
88    pub value: String,
89}
90
91/// Custom `.text` section name override.
92#[derive(Default, Debug, Serialize, Deserialize)]
93pub struct CustomSectionName {
94    /// Whether this feature is enabled.
95    pub enabled: bool,
96    /// Custom section name value.
97    pub value: String,
98}
99
100/// Global obfuscation settings for the module.
101#[derive(Debug, Serialize, Deserialize)]
102pub struct CDModuleSettings {
103    /// Whether to crash the IDA decompiler intentionally.
104    #[serde(default)]
105    pub ida_crasher: bool,
106    /// Whether to enable IAT/Import protection.
107    #[serde(default)]
108    pub import_protection: bool,
109    /// Obscure the entry point of the module with anti tamper and anti debug tactics
110    #[serde(default)]
111    pub obscure_entry_point: bool,
112    /// Clear unwind information. makes it harder for attackers to locate functions, however
113    /// structured exception handling will not work.
114    #[serde(default)]
115    pub clear_unwind_info: bool,
116    /// Fake PDB string settings.
117    #[serde(default)]
118    pub fake_pdb_string: FakePdbString,
119    /// Custom PE section name settings.
120    #[serde(default)]
121    pub custom_section_name: CustomSectionName,
122}
123
124/// Instruction-level semantics used in transformations.
125#[derive(Debug, Serialize, Deserialize, Clone)]
126pub struct Semantics {
127    #[serde(default)]
128    pub add: bool,
129    #[serde(default)]
130    pub sub: bool,
131    #[serde(default)]
132    pub and: bool,
133    #[serde(default)]
134    pub xor: bool,
135    #[serde(default)]
136    pub or: bool,
137    #[serde(default)]
138    pub not: bool,
139    #[serde(default)]
140    pub neg: bool,
141}
142
143/// Bit widths to apply transformations to.
144#[derive(Debug, Serialize, Deserialize, Clone)]
145pub struct BitWidths {
146    #[serde(default)]
147    pub bit8: bool,
148    #[serde(default)]
149    pub bit16: bool,
150    #[serde(default)]
151    pub bit32: bool,
152    #[serde(default)]
153    pub bit64: bool,
154}
155
156/// Configuration for the Loop Encode Semantics pass.
157#[derive(Debug, Serialize, Deserialize, Clone)]
158pub struct LoopEncodeSemantics {
159    /// Number of times to attempt transformation.
160    pub iterations: u32,
161    /// Percent chance to apply transformation (0–100).
162    pub probability: u32,
163    /// Instruction semantics to consider.
164    pub semantics: Semantics,
165    /// Bit widths to target.
166    pub bitwidths: BitWidths,
167}
168
169/// Configuration for Mixed Boolean Arithmetic pass.
170#[derive(Debug, Serialize, Deserialize, Clone)]
171pub struct MixedBooleanArithmetic {
172    pub iterations: u32,
173    pub probability: u32,
174    pub semantics: Semantics,
175    pub bitwidths: BitWidths,
176}
177
178/// Configuration for Mutation Engine pass.
179#[derive(Debug, Serialize, Deserialize, Clone)]
180pub struct MutationEngine {
181    pub iterations: u32,
182    pub probability: u32,
183    pub extension: MutationEngineExtension,
184    pub semantics: Semantics,
185    pub bitwidths: BitWidths,
186}
187
188/// Pass that crashes IDA’s decompiler.
189#[derive(Debug, Serialize, Deserialize, Clone)]
190pub struct IDADecompilerCrasher;
191
192/// Constant obfuscation pass.
193#[derive(Debug, Serialize, Deserialize, Clone)]
194pub struct ObscureConstants;
195
196/// Memory reference obfuscation pass.
197#[derive(Debug, Serialize, Deserialize, Clone)]
198pub struct ObscureReferences;
199
200/// Control-flow obfuscation pass.
201#[derive(Debug, Serialize, Deserialize, Clone)]
202pub struct ObscureControlFlow {
203    pub probability: u32,
204}
205
206/// Tether extraction pass.
207#[derive(Debug, Serialize, Deserialize, Clone)]
208pub struct TetherExtraction {
209    /// Min length of a sequence of instructions that should be extracted.
210    /// Its a bad idea for this to be 1 usually because its easy to synthesize
211    pub min_extract_len: usize,
212    /// Tether server endpoint
213    pub endpoint: String,
214    /// Tether server port
215    pub port: u16,
216    /// Hex string of the servers public key. This is used for public key pinning.
217    /// This needs to be length 64...
218    pub server_public_key: String,
219}
220
221/// All possible obfuscation passes.
222#[derive(Debug, Serialize, Deserialize, Clone)]
223#[serde(tag = "type")]
224pub enum ObfuscationPass {
225    LoopEncodeSemantics(LoopEncodeSemantics),
226    MixedBooleanArithmetic(MixedBooleanArithmetic),
227    MutationEngine(MutationEngine),
228    TetherExtraction(TetherExtraction),
229    IDADecompilerCrasher,
230    ObscureConstants,
231    ObscureReferences,
232    ObscureControlFlow,
233}
234
235/// Profile definition used to apply passes to symbols.
236#[derive(Debug, Serialize, Deserialize)]
237pub struct CDProfile {
238    /// Name of the profile.
239    pub name: String,
240    /// Obfuscation passes for this profile.
241    pub passes: Vec<ObfuscationPass>,
242    /// Compiler settings for this profile.
243    pub compiler_settings: CDCompilerSettings,
244    /// List of symbol RVAs this profile targets.
245    pub symbols: Vec<u64>,
246}
247
248/// Top-level config file structure.
249#[derive(Debug, Serialize, Deserialize)]
250pub struct CDConfig {
251    /// Module-wide settings.
252    pub module_settings: CDModuleSettings,
253    /// All profiles to apply during obfuscation.
254    pub profiles: Vec<CDProfile>,
255}
256
257/// Information about a single function found during analysis.
258#[derive(Deserialize, Serialize, Clone, Debug)]
259pub struct AnalysisFunction {
260    /// RVA of the function.
261    pub rva: u64,
262    /// Function name.
263    pub symbol: String,
264    /// Number of references to this function.
265    pub ref_count: usize,
266}
267
268/// Reason why a function was rejected from analysis.
269#[derive(Deserialize, Serialize, Clone, Debug)]
270pub struct AnalysisReject {
271    /// RVA of the rejected function.
272    pub rva: u64,
273    /// Symbol name.
274    pub symbol: String,
275    /// Mnemonic reason string (e.g., internal enum).
276    pub ty: String,
277    /// Stringified reason (human-readable).
278    pub reason: String,
279}
280
281/// Grouping of functions under a named macro profile.
282#[derive(Deserialize, Serialize, Clone, Debug)]
283pub struct AnalysisMacroProfile {
284    /// Name of the macro profile.
285    pub name: String,
286    /// List of function RVAs in this macro.
287    pub rvas: Vec<u64>,
288}
289
290/// Results from binary analysis, returned to the frontend.
291#[derive(Deserialize, Serialize, Clone, Debug)]
292pub struct AnalysisResult {
293    /// Environment type (UserMode, KernelMode, UEFI).
294    pub environment: PeEnvironment,
295    /// Functions found during analysis.
296    pub functions: Vec<AnalysisFunction>,
297    /// Rejected functions and reasons.
298    pub rejects: Vec<AnalysisReject>,
299    /// Macro profiles generated from analysis.
300    pub macros: Vec<AnalysisMacroProfile>,
301}
302
303/// Symbol representation used in YAML: either name or RVA.
304#[derive(Debug, Serialize, Deserialize)]
305pub enum YamlSymbol {
306    /// Symbol name
307    Name(String),
308    /// Symbol RVA.
309    Rva(u64),
310}
311
312/// Obfuscation profile for YAML configuration.
313#[derive(Debug, Serialize, Deserialize)]
314pub struct YamlProfile {
315    /// Profile name (referenced by source macros).
316    pub name: String,
317    /// Passes to apply to this profile.
318    pub passes: Vec<ObfuscationPass>,
319    /// Compiler configuration for this profile.
320    pub compiler_settings: CDCompilerSettings,
321    /// Symbols targeted by this profile.
322    pub symbols: Vec<YamlSymbol>,
323    /// Only used by the SaaS UI. Not used by the CLI.
324    pub color: Option<String>,
325}
326
327/// Root YAML config structure.
328#[derive(Debug, Serialize, Deserialize)]
329pub struct YamlConfig {
330    /// Version of the config file format.
331    pub version: String,
332    /// Global module-wide obfuscation settings.
333    pub module_settings: CDModuleSettings,
334    /// Obfuscation profiles to apply.
335    pub profiles: Vec<YamlProfile>,
336}