|
10 | 10 | [](README.md) |
11 | 11 | [](README_ZH.md) |
12 | 12 |
|
13 | | -Mistode (Mist Code, pronounced like "Miss Told") is a lightweight code obfuscation tool supporting Python and C. It focuses on making code difficult to read while maintaining functional integrity. |
| 13 | +Mistode (Mist Code, pronounced like *miss-told*) is a lightweight, advanced code obfuscation tool protecting **Python** and **C** source code. It combines robust AST/Regex parsing with a distributed layout engine to ensure code is unreadable yet fully functional and perfectly restorable. |
14 | 14 |
|
15 | 15 | ## Features |
16 | 16 |
|
17 | | -- **Encrypted Token Generator**: Highly customizable encrypted token generation supporting various configurations: |
18 | | - - **Random Seed**: Supports setting a random seed to ensure reproducibility. |
19 | | - - **Length Control**: Custom token length, range [8, 32] characters. |
20 | | - - **Style Configuration**: Supports two obfuscation styles: |
21 | | - - **Similar Character Style**: Uses visually similar character groups to enhance obfuscation (e.g., `Oo0`, `iIlL1`, `b6B8`, `Zz2`, `Ss5`). |
22 | | - - **Random Character Style**: Uses random alphanumeric combinations. |
23 | | - - **Smart Deduplication**: Automatically maintains a set of generated tokens to avoid duplicates. |
24 | | -- **Python Support**: |
25 | | - - **AST Parsing**: Accurate obfuscation based on Abstract Syntax Trees, ensuring complete preservation of code format. |
26 | | - - **Smart Identifier Classification**: Automatically identifies and preserves imported modules, functions, and built-in methods. |
27 | | - - **Docstring Obfuscation**: Replaces docstrings with hash values. |
28 | | - - **Fully Reversible**: Supports full restoration using generated key files or embedded metadata. |
29 | | - - **Lossless Restoration**: Achieves lossless consistency with the original file (preserving all comments and formatting) via distributed annotated injection of source chunks. |
30 | | -- **C Support**: |
31 | | - - **Fast Tokenization**: Uses robust regular expression tokenizers. |
32 | | - - **Layout Engine**: Uses `// @mistode:chunk:` metadata to preserve code structure. |
33 | | - - **Compilation Safety**: Preserves keywords, preprocessor directives, and external symbols. |
34 | | - - **Lossless Restoration**: Achieves lossless consistency with the original file via distributed layout chunks. |
| 17 | +- **🛡️ Advanced Obfuscation Engine**: |
| 18 | + - **Encrypted Token Generation**: Configurable token length (8-32 chars) and styles (Similar Characters like `Oo01Il` or Random Alphanumeric). |
| 19 | + - **Smart Deduplication & Validation**: Ensures no collisions and validates generated tokens against language keywords. |
| 20 | + - **Seed Support**: Fully reproducible obfuscation with `--seed`. |
35 | 21 |
|
36 | | -## Installation |
37 | | - |
38 | | -```shell |
39 | | -pip install mistode |
40 | | -``` |
| 22 | +- **🐍 Python Support (v3.14+)**: |
| 23 | + - **AST-Based Precision**: Parses the Abstract Syntax Tree for safe and accurate transformation. |
| 24 | + - **Smart Preservation**: Automatically protects imports, built-ins (`print`, `len`), and standard library calls. |
| 25 | + - **Docstring Hashing**: Replaces docstrings with unique hash markers. |
41 | 26 |
|
42 | | -## Usage |
| 27 | +- **🇨 C Support**: |
| 28 | + - **Robust Tokenization**: Regex-based engine safely handling macros, pointers, and structs. |
| 29 | + - **Layout Engine**: Preserves complex file structures using distributed `// @mistode:chunk:` markers. |
| 30 | + - **Symbol Safety**: Automatically preserves keywords, preprocessor directives, and standard headers. |
43 | 31 |
|
44 | | -### Simple Usage (Default Settings) |
| 32 | +- **🔄 Zero-Loss Restoration**: |
| 33 | + - **Distributed Source Chunks**: The original source is compressed, encrypted, and distributed throughout the obfuscated file as comments. |
| 34 | + - **Embedded Metadata**: Identifier mappings are embedded directly in the file header/footer. **No key file is required for restoration.** |
| 35 | + - **Bit-Perfect Restore**: Restores every byte of the original code, including comments, formatting, and empty lines. |
45 | 36 |
|
46 | | -```shell |
47 | | -# Obfuscate (generates input.obf.py and input.map.json) |
48 | | -mistode o input.py |
| 37 | +- **⚙️ Modern Tooling**: |
| 38 | + - **Configuration File**: Global defaults via `pyproject.toml`. |
| 39 | + - **Detailed Statistics**: `--stats` flag provides identifier counts, compression ratios, and safety checks. |
49 | 40 |
|
50 | | -# Restore (automatically detects input.map.json if naming matches) |
51 | | -# Generates input.res.py |
52 | | -mistode r input.obf.py |
53 | | -``` |
54 | | - |
55 | | -### Full Usage |
| 41 | +## Installation |
56 | 42 |
|
57 | | -```shell |
58 | | -# Obfuscate with explicit options |
59 | | -mistode obfuscate input.py --out output.py --key mapping.json |
| 43 | +> [!IMPORTANT] |
| 44 | +> Mistode requires **Python 3.14** or higher. |
60 | 45 |
|
61 | | -# Restore with explicit options |
62 | | -mistode restore output.py --out restored.py --key mapping.json |
| 46 | +```bash |
| 47 | +pip install mistode |
63 | 48 | ``` |
64 | 49 |
|
65 | | -### Configuration File |
| 50 | +## Quick Start |
66 | 51 |
|
67 | | -You can set default options in `pyproject.toml` to avoid repeating the same arguments: |
| 52 | +### 1. Python Example |
68 | 53 |
|
69 | | -```toml |
70 | | -[tool.mistode] |
71 | | -style = "similar" # Default obfuscation style ("similar" or "random") |
72 | | -length = 16 # Default token length (8-32) |
73 | | -stats = true # Always show statistics |
74 | | -# seed = 42 # Optional: set a default seed for reproducibility |
75 | | -``` |
| 54 | +```bash |
| 55 | +# Obfuscate 'app.py' (generates app.obf.py) |
| 56 | +mistode o app.py --stats |
76 | 57 |
|
77 | | -**How it works**: |
| 58 | +# Restore to original (generates app.res.py) |
| 59 | +# No key file needed - uses embedded metadata! |
| 60 | +mistode r app.obf.py |
78 | 61 |
|
79 | | -- Mistode automatically searches for `pyproject.toml` in the current directory and parent directories |
80 | | -- If found, settings from `[tool.mistode]` are used as defaults |
81 | | -- Command-line arguments always override configuration file settings |
| 62 | +# Verify match |
| 63 | +diff app.py app.res.py |
| 64 | +``` |
82 | 65 |
|
83 | | -**Example**: |
| 66 | +### 2. C Example |
84 | 67 |
|
85 | 68 | ```bash |
86 | | -# With the config above, these are equivalent: |
87 | | -mistode o input.py |
88 | | -mistode o input.py --style similar --length 16 --stats |
| 69 | +# Obfuscate 'main.c' (generates main.obf.c) |
| 70 | +mistode o main.c --stats |
| 71 | + |
| 72 | +# Compile and run obfuscated code |
| 73 | +gcc main.obf.c -o main_obf |
| 74 | +./main_obf |
89 | 75 |
|
90 | | -# Override config with command-line args: |
91 | | -mistode o input.py --style random --length 20 |
| 76 | +# Restore |
| 77 | +mistode r main.obf.c |
92 | 78 | ``` |
93 | 79 |
|
94 | | -For a complete guide, see [`examples/CONFIG_GUIDE.md`](examples/CONFIG_GUIDE.md). |
| 80 | +## Usage Guide |
95 | 81 |
|
96 | | -## Advanced Features |
| 82 | +### Command Line Interface |
97 | 83 |
|
98 | | -### Smart Identifier Recognition for Python Obfuscation |
| 84 | +```bash |
| 85 | +# General Syntax |
| 86 | +mistode [command] [file] [options] |
99 | 87 |
|
100 | | -Mistode intelligently identifies and avoids obfuscating the following types of identifiers: |
| 88 | +# Commands |
| 89 | +o, obf, obfuscate Obfuscate a file |
| 90 | +r, res, restore Restore a file |
| 91 | +``` |
101 | 92 |
|
102 | | -- **Built-in Modules**: `re`, `os`, `sys`, `json`, `math`, etc. |
103 | | -- **Built-in Functions**: `print`, `len`, `range`, `str`, `int`, etc. |
104 | | -- **Imported Functions**: Functions imported via `import` and `from ... import` statements. |
105 | | -- **Built-in Methods**: `re.sub`, `str.strip`, `list.append`, etc. |
| 93 | +### Common Options |
106 | 94 |
|
107 | | -### Example |
| 95 | +| Option | Alias | Description | |
| 96 | +| :--- | :--- | :--- | |
| 97 | +| `--out` | `-o` | Specify output filename. | |
| 98 | +| `--key` | `-k` | Specify key file path (optional, as metadata is embedded). | |
| 99 | +| `--stats` | | Show detailed statistics after processing. | |
| 100 | +| `--style` | | `similar` (default) or `random`. | |
| 101 | +| `--length` | `-l` | Token length (8-32). | |
| 102 | +| `--seed` | `-s` | Random seed for reproducibility. | |
| 103 | +| `--password` | `-p` | Password for encryption/decryption. | |
108 | 104 |
|
109 | | -**Original Code**: |
| 105 | +### Configuration File (`pyproject.toml`) |
110 | 106 |
|
111 | | -```python |
112 | | -import re |
113 | | -from openpyxl.utils import get_column_letter, column_index_from_string |
| 107 | +You can define project-wide defaults in `pyproject.toml`. Mistode automatically looks for this file in the current and parent directories. |
114 | 108 |
|
115 | | -def shift_column_letter(base_column, offset): |
116 | | - """Calculate the shifted column letter based on the given column letter and offset""" |
117 | | - base_idx = column_index_from_string(base_column) |
118 | | - target_idx = base_idx + offset |
119 | | - return get_column_letter(target_idx) |
| 109 | +```toml |
| 110 | +[tool.mistode] |
| 111 | +style = "similar" # "similar" (Io01) or "random" (aB3d) |
| 112 | +length = 24 # Stronger tokens |
| 113 | +stats = true # Always show stats |
| 114 | +seed = 12345 # Deterministic builds |
120 | 115 | ``` |
121 | 116 |
|
122 | | -**Obfuscated Code**: |
| 117 | +For a detailed guide, see [examples/CONFIG_GUIDE.md](examples/CONFIG_GUIDE.md). |
123 | 118 |
|
124 | | -```python |
125 | | -import re |
126 | | -from openpyxl.utils import get_column_letter, column_index_from_string |
| 119 | +## What Gets Obfuscated? |
127 | 120 |
|
128 | | -#@mistode:chunk:eJzjSklNU8hIzcnJ11BQyEvMTVVQ0LTiU... |
129 | | -def Oo0iIlL1b6B8Zz2Ss5(Oo0iIlL1b6B8Zz2Ss6, Oo0iIlL1b6B8Zz2Ss7): |
130 | | - """Obfuscated docstring: e2d30883ac53""" |
131 | | -#@mistode:chunk:aVaCikKXmAdOkoVEO01SopaCoogFWAiQo... |
132 | | - Oo0iIlL1b6B8Zz2Ss8 = column_index_from_string(Oo0iIlL1b6B8Zz2Ss6) |
133 | | - Oo0iIlL1b6B8Zz2Ss9 = Oo0iIlL1b6B8Zz2Ss8 + Oo0iIlL1b6B8Zz2Ss7 |
134 | | - return get_column_letter(Oo0iIlL1b6B8Zz2Ss9) |
135 | | -#@mistode:metadata:eJxVk1Fr3DAMx79K... |
136 | | -``` |
| 121 | +### Python |
137 | 122 |
|
138 | | -### Embedded Metadata & Distributed Source |
| 123 | +| Component | Status | Notes | |
| 124 | +| :--- | :---: | :--- | |
| 125 | +| **Variable Names** | ✅ | Replaced with tokens | |
| 126 | +| **Function/Class Names** | ✅ | Replaced with tokens | |
| 127 | +| **Docstrings** | ✅ | Replaced with hash placeholders | |
| 128 | +| **Imports** | ❌ | Preserved (`import math`) | |
| 129 | +| **Built-ins** | ❌ | Preserved (`print`, `len`) | |
| 130 | +| **Stdlib Methods** | ❌ | Preserved (`os.path.join`) | |
139 | 131 |
|
140 | | -Mistode uses a two-layer restoration mechanism: |
| 132 | +### C / C++ |
141 | 133 |
|
142 | | -1. **Distributed Source Chunks (`#@mistode:chunk:` or `// @mistode:chunk:`)**: The original source code is compressed, encoded, and injected as chunks before each line of the obfuscated code. Restoration prioritizes these chunks to reconstruct the original code, achieving **lossless restoration** (including all comments, empty lines, and formatting). |
143 | | -2. **Embedded Metadata (`#@mistode:metadata:`)**: Contains the identifier mapping table as a backup restoration method. |
| 134 | +| Component | Status | Notes | |
| 135 | +| :--- | :---: | :--- | |
| 136 | +| **Functions** | ✅ | User-defined only | |
| 137 | +| **Variables/Structs** | ✅ | Local and Global | |
| 138 | +| **Comments** | ✅ | Scrambled or Removed | |
| 139 | +| **Keywords** | ❌ | Preserved (`if`, `while`) | |
| 140 | +| **Preprocessor** | ❌ | Preserved (`#include`, `#define`) | |
| 141 | +| **Std Lib** | ❌ | Preserved (`printf`, `malloc`) | |
144 | 142 |
|
145 | | -This means you can perfectly restore the original code even without keeping the key file. |
| 143 | +## Restoration Mechanics |
146 | 144 |
|
147 | | -```python |
148 | | -# ... Obfuscated Code ... |
149 | | -#@mistode:chunk:eJzjSk... (Distributed Source Chunk) |
150 | | -# ... |
151 | | -#@mistode:metadata:eJxVk1... (Base64 Encoded Mapping) |
152 | | -``` |
| 145 | +Mistode uses a **dual-layer restoration system** to guarantee safety: |
153 | 146 |
|
154 | | -If no key file is provided, the restore command automatically detects and uses this metadata. |
155 | | - |
156 | | -## Project Structure |
157 | | - |
158 | | -```shell |
159 | | -mistode/ |
160 | | -├── src/ |
161 | | -│ └── mistode/ |
162 | | -│ ├── __init__.py # Package Initialization |
163 | | -│ ├── cli.py # Command Line Interface |
164 | | -│ ├── python.py # Python Obfuscator (mistode.python) |
165 | | -│ ├── c.py # C Obfuscator (mistode.c) |
166 | | -│ └── core.py # Core Functionality (mistode.core) |
167 | | -├── tests/ # Tests Directory |
168 | | -│ ├── __init__.py |
169 | | -│ ├── test_python.py # Python Obfuscator Tests |
170 | | -│ ├── test_c.py # C Obfuscator Tests |
171 | | -│ ├── test_cli.py # CLI Tests (Integration) |
172 | | -│ ├── test_cli_unit.py # CLI Tests (Unit) |
173 | | -│ └── test_core.py # Core Functionality Tests |
174 | | -├── pyproject.toml # Project Configuration |
175 | | -└── README.md # Project Documentation |
176 | | -``` |
| 147 | +1. **Distributed Source Chunks (Primary)**: |
| 148 | + Chunks of the compressed original source are injected as comments (e.g., `#@mistode:chunk:...`) throughout the file. This allows **100% bit-perfect restoration**. |
177 | 149 |
|
178 | | -## Development |
| 150 | +2. **Embedded Mappings (Secondary)**: |
| 151 | + The renaming map is compressed and embedded in the file footer (`#@mistode:metadata:`). If chunks are damaged, this allows functional restoration. |
179 | 152 |
|
180 | | -### Running Tests |
| 153 | +3. **Key File (Optional)**: |
| 154 | + You can explicitly save the mapping to a JSON file with `--key`, but it is not required for standard workflows. |
181 | 155 |
|
182 | | -```shell |
183 | | -python -m pytest tests/ |
184 | | -``` |
| 156 | +## Contributing |
185 | 157 |
|
186 | | -### Building the Package |
| 158 | +Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details. |
187 | 159 |
|
188 | | -```shell |
189 | | -pip install build |
190 | | -python -m build |
191 | | -``` |
| 160 | +## License |
| 161 | + |
| 162 | +This project is licensed under the [GPLv3 License](LICENSE). |
0 commit comments