├── LICENSE ├── README.md ├── doc ├── designDoc.pptx └── img │ ├── HomePage.png │ ├── consoleRun.png │ ├── decodeFlow.png │ ├── decoderPage.png │ ├── encodeFlow.png │ ├── encoderPage.png │ ├── logo_mid.png │ ├── logo_mid2.png │ ├── logo_normal.png │ ├── sysWorkflow.png │ ├── title.png │ ├── usageExample.png │ ├── useDecoder.png │ └── useEncoder.png └── src ├── exampleTestcode.py ├── pyObfuscator.py ├── pyObfuscatorApp.py ├── static └── img │ ├── consoleRun.png │ ├── logo_normal.png │ ├── logo_small.png │ ├── sysWorkflow.png │ ├── useDecoder.png │ └── useEncoder.png └── templates ├── base.html ├── index.html ├── mgmbase.html ├── obfdecoder.html ├── obfencoder.html └── usagemanual.html /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Yuancheng Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Program Obfuscator 2 | 3 | ![](doc/img/logo_mid.png) 4 | 5 | **Program Design Purpose**: The project main objective is to develop a multiplatform Python program obfuscation tool which can easily safeguard the source code for the people who wants to protect their intellectual property rights or manage their software sensitive algorithm. This tool will seamlessly obfuscate and encode the source code into unreadable but Python-interpreter executable bytes data which can be mixed executed with normal python program. Additionally, it will offer a decoder to revert obfuscated byte data back to its original source code. The program comprises three main components: 6 | 7 | - **Obfuscation Encoder** : This component encrypts the Python source code, whether it's an entire file or a specific section, rendering it unreadable as bytes data, then embed an execution header to create the executable but unreadable python program/section. 8 | - **Obfuscation Decoder** : The decoder is designed to reverse the encoding process, this decoder transforms obfuscated bytes data back into its original Python code, ensuring ease of readability and accessibility. 9 | - **Service Web Interface** : Provide a user-friendly web interface for the user to easily encoding and decoding of Python programs. 10 | 11 | The usage example of the program obfuscation tool is shown below, the user can use encoder to obfuscate the one line code `print("hello world")` to unreadable code bytes, then use the decoder to covert it back: 12 | 13 | ![](doc/img/usageExample.png) 14 | 15 | `Figure 00: Code obfuscation encode and decode example, version v_0.1.3 (2025)` 16 | 17 | We also provide the Python-API for user to integrated the encoding and real-time decoding & execution function into their program. Video to show the detail usage : [link](https://youtu.be/2vG-mqkGg_4?si=keG-J5XppWxbxhtY) 18 | 19 | ``` 20 | # Created: 2024/03/21 21 | # Version: v_0.1.3 22 | # Copyright: Copyright (c) 2024 LiuYuancheng 23 | # License: MIT License 24 | ``` 25 | 26 | **Table of Contents** 27 | 28 | [TOC] 29 | 30 | - [Python Program Obfuscator](#python-program-obfuscator) 31 | + [Introduction](#introduction) 32 | * [Obfuscation Encoder Web UI](#obfuscation-encoder-web-ui) 33 | * [Obfuscation Decoder Web UI](#obfuscation-decoder-web-ui) 34 | + [Background Knowledge](#background-knowledge) 35 | + [Project Design](#project-design) 36 | * [Design of Encoding and Decoding](#design-of-encoding-and-decoding) 37 | + [Program Setup](#program-setup) 38 | * [Development Environment](#development-environment) 39 | * [Additional Lib/Software Need](#additional-lib-software-need) 40 | * [Hardware Needed : None](#hardware-needed---none) 41 | * [Program Files List](#program-files-list) 42 | + [Program Usage/Execution](#program-usage-execution) 43 | - [Run the obfuscator via command interface](#run-the-obfuscator-via-command-interface) 44 | - [Run the obfuscator via web interface](#run-the-obfuscator-via-web-interface) 45 | + [Reference](#reference) 46 | + [Problem and Solution](#problem-and-solution) 47 | 48 | ------ 49 | 50 | ### Introduction 51 | 52 | Program obfuscation is a widely adopted common technique for enhancing the security of Python applications. There are various obfuscation libraries and tools exist in the market, such as [pyarm](https://pyarmor.readthedocs.io/en/latest/) or [free online tool's obfuscation tool](https://freecodingtools.org/py-obfuscator). The obfuscation process will employ methods such as `identifier renaming`, `code encryption`, `code packing`, `dead code insertion` and so on, it effectively makes it difficult for hackers to understand the program execution/control flow and safeguards sensitive source code from unauthorized access. But most of the current obfuscation tools don't provide the features like `decoding algorithms`, `customization of obfuscation result size` , or the `selection of whether obfuscate entire/part of file`. 53 | 54 | Inspired by the concept of this [free online tool's obfuscation tool](https://freecodingtools.org/py-obfuscator), our goal is to develop a web-based Python program obfuscation tool with the following key features: 55 | 56 | - Provide multi-layer Python code obfuscation with customizable encoded obfuscated code sizes configuration. 57 | - Provide provision of both encoder and decoder functions to facilitate maintenance and debugging of obfuscated code. 58 | - Provide capability to obfuscate entire Python programs or specific sections of source code for added flexibility. 59 | - Integration of flexible code randomization techniques to ensure that each generated obfuscated code is unique, even when derived from the same source code. 60 | - Provision of a standardized API for users to seamlessly integrate the tool into their projects, coupled with a user-friendly Web UI for convenient encoding and decoding operations. 61 | 62 | The obfuscation tool work flow is shown below: 63 | 64 | ![](doc/img/sysWorkflow.png) 65 | 66 | `Figure 01: Code obfuscation encode and decode work flow, version v_0.1.3 (2025)` 67 | 68 | ##### Obfuscation Encoder Web UI 69 | 70 | The Obfuscate Encoder page is shown below. To obfuscate a Python function or program, simply paste the Python source code into the source code text field, then select the random contents append config parameter `randomLen` (ranging from 0 to 100). Each line of source code will be appended `randomLen` * 16 Bytes random sting before do the obfuscation encoding process. 71 | 72 | > Obfuscation encoder web page view : 73 | 74 | ![](doc/img/encoderPage.png) 75 | 76 | `Figure 02: Code obfuscation webApp encoder screen shot, version v_0.1.3 (2025)` 77 | 78 | Upon pressing the "Run Obfuscation Encode" button, the obfuscated code will appear in the result text field on the right. Press the copy code button then paste the obfuscated code to your program to execute. 79 | 80 | > Note : Each time the user presses the run button, a different obfuscated code result will be generated. 81 | 82 | 83 | 84 | ##### Obfuscation Decoder Web UI 85 | 86 | Similar to the encoder page, the decoder page is displayed below. Users are required to copy the byte data of the obfuscated code (contained within the `exec()` function) into the left text field. Then, by clicking the "Run Decoder" button, the obfuscated code will be converted back to its original source code. 87 | 88 | > Obfuscation decoder web page view : 89 | 90 | ![](doc/img/decoderPage.png) 91 | 92 | `Figure 03: Code obfuscation webApp decoder screen shot, version v_0.1.3 (2025)` 93 | 94 | > Note: If users prefer to obtain the source code without comments, they can check the "Remove the comments" checkbox. 95 | 96 | 97 | 98 | ------ 99 | 100 | ### Background Knowledge 101 | 102 | **What is Program obfuscation ?** 103 | 104 | Program obfuscation is a technique used in software development to deliberately make the source code of a program more difficult to understand or reverse-engineer, while preserving its functionality. It is commonly employed in scenarios where the developer wants to protect their intellectual property, prevent unauthorized access, or hinder attempts to tamper with the software. 105 | 106 | Here are some common techniques used in program obfuscation: 107 | 108 | 1. **Renaming identifiers**: This involves renaming variables, functions, classes, and other identifiers in the code to non-descriptive or cryptic names. For example, variables like `userInput` might be renamed to `a` or `b`, making it harder to understand their purpose. 109 | 2. **Control flow obfuscation**: This technique involves altering the flow of control in the program, making it harder to follow the logical structure. This can be achieved through techniques such as adding redundant code, using conditional statements in unusual ways, or restructuring loops. 110 | 3. **Data obfuscation**: Data obfuscation involves disguising data within the program, making it harder to understand or extract sensitive information. This can include encrypting strings or splitting them into smaller parts that are concatenated at runtime. 111 | 4. **Code encryption**: This involves encrypting some or all of the code in the program and decrypting it at runtime. This makes it difficult for attackers to analyze the code without knowing the decryption key. 112 | 5. **Dead code insertion**: Inserting dead code (code that is never executed) into the program can confuse reverse engineers and make it harder to understand the true functionality of the program. 113 | 6. **Code packing**: This involves compressing or packing the executable file, making it harder to analyze using standard tools. The packed code is typically decompressed and executed at runtime. 114 | 7. **Anti-debugging techniques**: These are methods used to detect and prevent the program from being debugged, which can make it harder for attackers to analyze the code. 115 | 116 | It's important to note that while obfuscation can make reverse engineering more difficult, it's not a foolproof method for protecting software. Skilled attackers may still be able to reverse engineer obfuscated code given enough time and resources. Therefore, obfuscation is often used in conjunction with other security measures such as encryption, access control, and code signing. Additionally, obfuscated code can be harder to maintain and debug, so developers should weigh the benefits against the potential drawbacks before applying obfuscation techniques. 117 | 118 | 119 | 120 | ------ 121 | 122 | ### Project Design 123 | 124 | This section integrates with the background knowledge to elucidate the steps and techniques applied in the obfuscation process. 125 | 126 | ##### Design of Encoding and Decoding 127 | 128 | As depicted in the program workflow diagram provided in the introduction, the Python source code section undergoes encoding through a series of steps to convert the Python source code string into bytes data. Subsequently, it is encapsulated with a decode header. To execute the bytes data, the decode header is utilized to convert the bytes back into a string, which is then passed into the Python dynamic code execution function `exec()` for code execution. The encoding steps are outlined below: 129 | 130 | ```mermaid 131 | flowchart TD 132 | A[Python source code] --> |Remove code comments & doc strings| B 133 | B[Pure soure code] --> D 134 | C[Random contents length config] --> D 135 | D[Insert random-contents or dead-code] --> |'zlib' compress| E 136 | E[Compressed bytes] --> |base64 encode| F 137 | F[Encode bytes] --> |Reversed byte sequence| G 138 | H[Execution header and wrapper code] --> G 139 | G[Obfuscated executable python code] 140 | ``` 141 | 142 | Example encoder source code input : 143 | 144 | ```python 145 | import os 146 | # Code comment 1 147 | print("Current working directory is : %s" % os.getcwd()) 148 | dirpath = '' 149 | # Code document 2 150 | if os.path.dirname(__file__): 151 | dirpath = os.path.dirname(__file__) 152 | else: 153 | dirpath = os.getcwd() 154 | # Code comment 3 155 | print("Current source code location : %s" % dirpath) 156 | print("Hello world") 157 | ``` 158 | 159 | Example encoder obfuscated code output: 160 | 161 | ```python 162 | def obfDecode(data): return __import__('zlib').decompress(__import__('base64').b64decode(data[::-1])) 163 | exec(obfDecode(b'kDMA2910OfmOY0xz1Jeq1cjF1JMlFPYhZCtLm5r5V0c3LyNFMwBmnV7YF3hnto2YOMsfrKkvLSzKTp1tL3je1dP+R8t2mH74DVtheP0G1EUMVMnsRP3APWbRcAfFkilrWTbnlp3ttZVjhXcluBz5GOMb/UlK2UKJRzbbUXHe7DKL65v/y/trHOP3hfqE83kkRwle1v6OSgbVVAT7CZvvXGXWa6u6wBXjGgHPV02VULPoNfXFUXRCUxN11+ZFIxbON+t67wffylf9V3/xKJxHbe96nWPH/3aBwKW0e9GFl5DlK4zJUCSNqnhxlGpiCVNIKCHTC2uuOvPgUNLjQXiOJWJbRbEnW/YfrDQrsX9eUPX+tT4w6hx10UIIG2U7zcC2maRyDUhYcjeEeMOVjqHUR/aZTjtcVuOJ0GjIzrjqdau0yCup99y2Hov6/TZyKf/JPXmd1M+6IMyrPBpVuw8uBVYW72TRSDh1o1F2OuFvl05d1HhzjFYOuiuSqq+58tbop9aXeMV/lzj02klznW10GVcXSYESwFoLEcLoStyQaVw72AYC9UNEqEhvYgvGJizlmu1QsDmIhOcq1M3ViI2UV9/6Hrf55PtrZWqMfX0CF3YFPWI20OQmE4FjWKTHwduZ+wMzweDKqrBNbhWwj6GL6srBRXvVZvVAiyV+WNUAs8n3u/uPlbv7u/Ok6/4vU9jPP+1Dyme57KhvsRITjAGw1AakCa8M+oVb7C7IZ0pRFn8xyVdXmJRlRwoduC6hR/cuwBZUHCjScdDhB4I0G81XqP+/PIvAGmFho19mLzJCyZ94+m1k7trz3/QUzBQ0h0oJhbaeEOhzrBm15OrFoXuiATAG3TpdTH0Jqud75vO/97ffXQsSeG7Az9GP55p5moVcW4AZxQt+3pDQtfJeYVwSU3kh6jJNyuApFffdvFQdytMKCJGO9OLnjnWf+fPe3uvPzFO852U+Vnu58HP/pX+8P3+6nT/tukz8xX+x2X/2zH123+6pV7O/4Lf7Ln+492o77mrhGcdXegy4lyiNQJnIiRrIqRx9Vf+eJTdEbR0B1yoxwskbtt7SYIWLoujaBPnJYb+oGzH+5/wDvmN5rd68rP9g1gmsgROkfKzZgg/k0ZjoPgwZmWzkwtXgZCngFcnu1eKchFyUMpbHjJgR3QGnL6IKemRn6JX/+4Lf2X/yhXe0ff0RK9Hc5urkwNBs3d02Jz4ZmO9Mmw5roHzbmIvsZUSVKlKGejtxGfYeNcfhMcEXK2Ml1xJe')) 164 | ``` 165 | 166 | The obfuscation technique used in the obfuscation encoding process: 167 | 168 | 1. **Bytes reversal**: The result data bytes array are reversed to make reversed code harder to understand at a glance and requires reversing it before interpreting it correctly. 169 | 2. **Randomization**: The encode function adds a random string of specified length to each line before obfuscation. This adds further complexity and randomness to the obfuscated code. 170 | 3. **Dynamic import**: The obfuscated code uses `__import__()` to dynamically import modules (`zlib` and `base64`). This technique hides the imports, making it less obvious what modules are being used. 171 | 4. **String manipulation**: The encode process removes comments, static strings and empty lines from the code to make the code becomes more difficult to understand and analyze. 172 | 5. **Encoding and compression**: The encode function obfuscates the code by encoding it with base64 and compressing it with `zlib`. Additionally, it reverses the resulting string. This process makes the code unreadable in its encoded form. 173 | 6. **Execution via `exec()`**: The code is executed by `exec()` function. This method of execution makes it challenging to understand the code's behavior without analyzing its execution. 174 | 175 | These obfuscation techniques make the code difficult to understand, analyze, and reverse engineer, enhancing its resistance to reverse engineering and unauthorized access. 176 | 177 | The decoding progress reverse the encoding process with below steps: 178 | 179 | ```mermaid 180 | flowchart TD 181 | A[Obfuscated Bytes] --> |Reversed byte sequence| B 182 | B[Obfuscated encoded Bytes] --> |Base64 decode| C 183 | C[Obfuscated compressed code byte ] --> |'zlib' decompress|D 184 | D[Code with random contents and dead code] --> |remove random contents | E 185 | E[Python source code] 186 | 187 | ``` 188 | 189 | Example decoder obfuscated bytes input : 190 | 191 | ```python 192 | b'==Azg/E+Hk/eC9JOcaYt02SskKCJHfYu6ZVAPyhHdaUjsOse30tA1QP7d3nvW7U4eWbcNtHxmP4jG6VKRiMCbBNe1/8UHBxw7WSMdLdeA6vnz07MBSDeOxNd91GOps8hieqUrq+9QO8BIrlwh1me8uwTqOvK7qNLgbc/bAsiysVCPPfoDwOxAE+YpjwxPvGPaBCdTP2QWyRuO36o4GRlaf8NtENhd5Uzcz6VcBntUaz73kkqyNxjXKCvrqFH2Cy5pc12ydzjuIS2p2ERKLy1IA0LZdHllai3el3/e4VY40KhjXeZkjmtgMmJxAyQ4wDgWPWqXiNfywoHb2OWVBA442CkfaqknK/aDE4exCL2PGERtupfoaVAgikXMR/ZdA2NkxKhO19JWowZYU0I8GSzd7mwOI6S+6C8r4ZwVAj12P+t5OUnvkVvx1lxRGXFxyh8FaFglYml1iilkUBzBrsTI24q2VgoCr5bA1nvSNdY8hbXvZBRS05i9YWwlQGzbgB15Qlcnh6Wb0aYxUVMrT58MYXngucLlVZVvACQdIr2YTFBjwlN5aslybv/Pf/zeML/+4zvjs9x1v+P+97fe8rP+9867fe++3v++fuO6uloQpnGAp9n2CEh7cmhi43pvoPpZK5ThFO7GeeRQETHqtkk1xJe' 193 | ``` 194 | 195 | Example decoder source code output: 196 | 197 | ```python 198 | print("hello world") 199 | ``` 200 | 201 | 202 | 203 | ------ 204 | 205 | ### Program Setup 206 | 207 | Follow the below configuration steps before run the program. 208 | 209 | ##### Development Environment 210 | 211 | - python 3.8.2rc2+ [Windows11] 212 | 213 | ##### Additional Lib/Software Need 214 | 215 | - Flask: https://flask.palletsprojects.com/en/3.0.x/ , install `pip install Flask` 216 | - Flask-SocketIO: https://flask-socketio.readthedocs.io/en/latest/ , install `pip install Flask-SocketIO` 217 | 218 | ##### Hardware Needed : None 219 | 220 | ##### Program Files List 221 | 222 | | Program File | Execution Env | Description | 223 | | ---------------------- | ------------- | ------------------------------------------------------------ | 224 | | src/pyObfuscator.py | python 3.7 + | The main lib module to provide the obfuscation encode and decode functions. | 225 | | src/pyObfuscatorApp.py | python 3.7 + | The obfuscate web interface. | 226 | | templates/*.html | | All the web page html files. | 227 | 228 | 229 | 230 | ------ 231 | 232 | ### Program Usage/Execution 233 | 234 | We offer two interfaces for users to utilize the program: a console command interface and a web interface. 235 | 236 | #### Run the obfuscator via command interface 237 | 238 | **Step1**: Run the program via command: 239 | 240 | ``` 241 | python pyObfuscator.py 242 | ``` 243 | 244 | **Step2**: Select mode 0, then follow the steps to input the python program need to be obfuscate, the obfuscated code will be saved in file `obfuscateCode.py` , then user can change the file's name and replace the original file. 245 | 246 | ![](doc/img/consoleRun.png) 247 | 248 | `Figure 03: obfuscator test case usage screen shot, version v_0.1.3 (2025)` 249 | 250 | #### Run the obfuscator via web interface 251 | 252 | **Step1**: Run the web host program via command: 253 | 254 | ``` 255 | python pyObfuscatorApp.py 256 | ``` 257 | 258 | **Step2**: Open browser type in the URL: http://127.0.0.1:5000/ 259 | 260 | ![](doc/img/HomePage.png) 261 | 262 | `Figure 04: Code obfuscation webApp introduction page screen shot, version v_0.1.3 (2025)` 263 | 264 | **Step3**: Select the `Obfuscation Encoder` from the left guide menu, and follow the below steps to obfuscate the source code: 265 | 266 | ![](doc/img/useEncoder.png) 267 | 268 | `Figure 05: Code obfuscation webApp encoder usage steps, version v_0.1.3 (2025)` 269 | 270 | **Step4**: Select the `Obfuscation decoder` from the left guide menu, and follow the below steps to get the source code: 271 | 272 | ![](doc/img/useDecoder.png) 273 | 274 | `Figure 05: Code obfuscation webApp decoder usage steps, version v_0.1.3 (2025)` 275 | 276 | 277 | 278 | ------ 279 | 280 | ### Reference 281 | 282 | - **Pyarmor **: https://pyarmor.readthedocs.io/en/latest/ 283 | 284 | - **Free online tool's obfuscation tool**: https://freecodingtools.org/py-obfuscator 285 | 286 | 287 | 288 | ------ 289 | 290 | ### Problem and Solution 291 | 292 | Refer to `doc/ProblemAndSolution.md` 293 | 294 | ------ 295 | 296 | > Last edited by LiuYuancheng (liu_yuan_cheng@hotmail.com) at 20/02/2025, if you have any question please free to message me. 297 | 298 | -------------------------------------------------------------------------------- /doc/designDoc.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/designDoc.pptx -------------------------------------------------------------------------------- /doc/img/HomePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/HomePage.png -------------------------------------------------------------------------------- /doc/img/consoleRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/consoleRun.png -------------------------------------------------------------------------------- /doc/img/decodeFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/decodeFlow.png -------------------------------------------------------------------------------- /doc/img/decoderPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/decoderPage.png -------------------------------------------------------------------------------- /doc/img/encodeFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/encodeFlow.png -------------------------------------------------------------------------------- /doc/img/encoderPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/encoderPage.png -------------------------------------------------------------------------------- /doc/img/logo_mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/logo_mid.png -------------------------------------------------------------------------------- /doc/img/logo_mid2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/logo_mid2.png -------------------------------------------------------------------------------- /doc/img/logo_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/logo_normal.png -------------------------------------------------------------------------------- /doc/img/sysWorkflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/sysWorkflow.png -------------------------------------------------------------------------------- /doc/img/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/title.png -------------------------------------------------------------------------------- /doc/img/usageExample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/usageExample.png -------------------------------------------------------------------------------- /doc/img/useDecoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/useDecoder.png -------------------------------------------------------------------------------- /doc/img/useEncoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/doc/img/useEncoder.png -------------------------------------------------------------------------------- /src/exampleTestcode.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | # Code comment 1 4 | print("Current working directory is : %s" % os.getcwd()) 5 | dirpath = '' 6 | # Code document 2 7 | if os.path.dirname(__file__): 8 | dirpath = os.path.dirname(__file__) 9 | else: 10 | dirpath = os.getcwd() 11 | # Code comment 3 12 | print("Current source code location : %s" % dirpath) 13 | print("Hello world") -------------------------------------------------------------------------------- /src/pyObfuscator.py: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # Name: pyObfuscator.py 3 | # 4 | # Purpose: This module will provide a simplified Python obfuscation encode and 5 | # decode function to secure and protect the source code, the obfuscate 6 | # encode method uses 3 layers obfuscation technology to makes it difficult 7 | # for hackers to gain access to your sensitive source code. 8 | # 9 | # Author: Yuancheng Liu 10 | # 11 | # Version: v_0.1.3 12 | # Created: 2024/03/21 13 | # Copyright: Copyright (c) 2023 LiuYuancheng 14 | # License: MIT License 15 | #----------------------------------------------------------------------------- 16 | """ Program design: 17 | This module follow the idea in the link:[ https://freecodingtools.org/py-obfuscator#: 18 | ~:text=A%20Python%20obfuscator%20is%20a,to%20your%20sensitive%20source%20code] and the 19 | algo in the pyarmor obfuscation lib[https://pyarmor.readthedocs.io/en/latest/] to 20 | obfuscate a normal python program (section) with the compress and base64 encode lib. 21 | 22 | Usage steps: 23 | 1. Run the program with input test mode 0. 24 | 2. Type in the python source code program file name/path. 25 | 3. Set the random contents insertion parameter number. 26 | 4. The obfuscated code will be saved in the file . 27 | """ 28 | import zlib 29 | import uuid 30 | import base64 31 | 32 | # the decode header works with the obfuscated code 33 | CODE_HEADER = """def obfDecode(data): return __import__('zlib').decompress(__import__('base64').b64decode(data[::-1]))""" 34 | 35 | #----------------------------------------------------------------------------- 36 | def getRemoveCmtCode(codeStr): 37 | """ Remove the comments section in the input code. """ 38 | codeContent = '' 39 | for line in codeStr.split('\n'): 40 | # Removing the comments from the decoded data 41 | line = line.split("#")[0] 42 | # Removing the empty lines from the decoded data 43 | if line.strip() != "": 44 | # Adding the original encoded data to the output list 45 | codeContent += line+'\n' 46 | return codeContent 47 | 48 | #----------------------------------------------------------------------------- 49 | def obfEncode(data, removeCmt=True): 50 | """ Obfuscate encode the input python source code. 51 | Args: 52 | data (str): python source code string. 53 | removeCmt (bool, optional): flag to remove the code original comments and empty line. Defaults to True. 54 | Returns(bytes): obfuscated encoded bytes data or None if input is invalid. 55 | """ 56 | if isinstance(data, str): 57 | codeContent = getRemoveCmtCode(data) if removeCmt else data 58 | reversedData = base64.b64encode(zlib.compress(codeContent.encode('utf-8'))).decode()[::-1] 59 | return reversedData.encode('utf-8') 60 | else: 61 | print("Error: obfEncode() > The input data need to be str() type.") 62 | return None 63 | 64 | #----------------------------------------------------------------------------- 65 | def obfDecode(data, removeCmt=True): 66 | """ Decode the obfuscate bytes back to source code. 67 | Args: 68 | data (bytes): obfuscated bytes data. 69 | removeCmt (bool, optional): flag to remove the random comments and empty line 70 | of the result. Defaults to True. 71 | Returns: 72 | str: python code string 73 | """ 74 | if isinstance(data, bytes): 75 | # Reversing the input string to get the original encoded data 76 | decompressedData = zlib.decompress(base64.b64decode(data[::-1])) 77 | codeData = decompressedData.decode('utf-8') 78 | codeContent = getRemoveCmtCode(codeData) if removeCmt else codeData 79 | return codeContent 80 | else: 81 | print("Error: obfDecode() > the input data need to be a bytes() type value.") 82 | return None 83 | 84 | #----------------------------------------------------------------------------- 85 | def executeObfuscateCode(obfBytes, debug=False): 86 | """ Execute the input obfuscated code bytes. 87 | Args: 88 | obfBytes (bytes): obfuscated bytes data. 89 | debug (bool, optional): flag to identify whether show the execution result. 90 | Defaults to False. 91 | """ 92 | codeCode = obfDecode(obfBytes) 93 | if codeCode is None: return None 94 | try: 95 | if debug: print("Start to execute the code: %s " %str(codeCode)) 96 | rst = exec(codeCode) 97 | return rst 98 | except Exception as err: 99 | print("Execution Error: executeObfuscateCode() > %s" %str(err)) 100 | return None 101 | 102 | #----------------------------------------------------------------------------- 103 | def getObfuscatedCode(codeStr, randomLen=0): 104 | """ Crete the executable obfuscated contents based on the random contents length. 105 | Args: 106 | codeStr (str): python source code string. 107 | randomLen (int): each line will add a randomLen*16 Bytes random sting before 108 | do the Obfuscation encode. 109 | """ 110 | if isinstance(codeStr, str): 111 | newCodeContents = '' 112 | if randomLen > 0: 113 | for line in codeStr.split('\n'): 114 | newCodeContents += '%s\n' % line 115 | newCodeContents += '''#''' 116 | for _ in range(randomLen): 117 | newCodeContents += str(uuid.uuid4().hex) 118 | newCodeContents += '''\n''' 119 | else: 120 | newCodeContents = codeStr 121 | exeStr = str(obfEncode(newCodeContents, removeCmt=False)) 122 | exeStr = """exec(obfDecode(%s))""" % exeStr if exeStr.startswith('b') else """exec(obfDecode(b'%s'))""" % exeStr 123 | return CODE_HEADER + '\n' + exeStr + '\n' 124 | else: 125 | print("Error: getObfuscatedCode()> the input obfuscate need to be string type data.") 126 | 127 | #----------------------------------------------------------------------------- 128 | #----------------------------------------------------------------------------- 129 | 130 | def testCase(mode): 131 | """ Program test cases """ 132 | testCodeStr = "print('hello world')#this is a comment\nprint(123)" 133 | if mode == 0: 134 | import os 135 | print('Input the file name/path you want to obfuscate encode:') 136 | uInput = str(input()) 137 | print('Input the random append contents length number (0~100):') 138 | randomLen = int(input()) 139 | if os.path.isfile(uInput) and uInput.endswith('.py'): 140 | codeStr = '' 141 | with open(uInput,'r') as fh: 142 | codeStr = fh.read() 143 | data = getObfuscatedCode(codeStr, randomLen=randomLen) 144 | with open("obfuscateCode.py", "w") as f: 145 | f.write(data) 146 | print("- Done.") 147 | else: 148 | print("Input file not exist or file type not match.") 149 | elif mode == 1: 150 | print("Test Case1: obfuscate encode and decode test") 151 | encodeData = obfEncode(testCodeStr) 152 | print("Encoded data: %s" %str(encodeData)) 153 | decodeData = obfDecode(encodeData) 154 | print("Decoded source: %s" %str(decodeData)) 155 | exec(decodeData) 156 | if decodeData == getRemoveCmtCode(testCodeStr): 157 | print("- Pass.") 158 | else: 159 | print("- Failed.") 160 | elif mode == 2: 161 | print("Test Case2: obfuscate encode and execute") 162 | encodeData = obfEncode(testCodeStr) 163 | print("Execute the encoded data: %s" %str(encodeData)) 164 | result = executeObfuscateCode(encodeData) 165 | print(result) 166 | elif mode == 3: 167 | print("Test Case3: generate executable obfuscate code") 168 | data = getObfuscatedCode(testCodeStr, randomLen=10) 169 | with open("obfuscateCode.py", "w") as f: 170 | f.write(data) 171 | print("- Done.") 172 | else: 173 | print("Error: the input mode need to be 1, 2 or 3.") 174 | 175 | #----------------------------------------------------------------------------- 176 | if __name__ == '__main__': 177 | mode = 0 178 | print('Input the test mode you want to run [0~3]:') 179 | mode = int(input()) 180 | testCase(mode) 181 | -------------------------------------------------------------------------------- /src/pyObfuscatorApp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #----------------------------------------------------------------------------- 3 | # Name: pyObfuscatorApp.py [python3] 4 | # 5 | # Purpose: This module is the main web interface to call the obfuscator 6 | # API to encode/decode the python program and use the socketIO 7 | # to update result. 8 | # 9 | # Author: Yuancheng Liu 10 | # 11 | # Created: 2024/03/21 12 | # version: v0.1.3 13 | # Copyright: Copyright (c) 2024 LiuYuancheng 14 | # License: MIT License 15 | #----------------------------------------------------------------------------- 16 | import os 17 | import threading 18 | import pyObfuscator as obfuscate 19 | 20 | from flask import Flask, render_template, request 21 | from flask_socketio import SocketIO, emit # pip install Flask-SocketIO==5.3.5 22 | 23 | DEBUG_MD = False 24 | 25 | gflaskHost = "0.0.0.0" 26 | gflaskPort = 5000 27 | gflaskDebug = False 28 | gflaskMultiTH = True 29 | 30 | #----------------------------------------------------------------------------- 31 | # Init the flask web app program. 32 | def createApp(): 33 | """ Create the flask App.""" 34 | app = Flask(__name__) 35 | return app 36 | app = createApp() 37 | 38 | # SocketIO asynchronous mode 39 | async_mode = None 40 | socketio = SocketIO(app, async_mode=async_mode) 41 | #gv.iSocketIO = socketio 42 | thread = None 43 | threadLock = threading.Lock() 44 | 45 | #----------------------------------------------------------------------------- 46 | #----------------------------------------------------------------------------- 47 | # web request handling functions. 48 | @app.route('/') 49 | def index(): 50 | """ route to introduction index page.""" 51 | posts = {'page': 0} # page index is used to highlight the left page slide bar. 52 | return render_template('index.html', posts=posts) 53 | 54 | #----------------------------------------------------------------------------- 55 | @app.route('/encoder') 56 | def encoder(): 57 | """ route to introduction index page.""" 58 | posts = {'page': 1} # page index is used to highlight the left page slide bar. 59 | return render_template('obfencoder.html', posts=posts) 60 | 61 | @app.route('/encodesubmit', methods=['POST']) 62 | def encodesubmit(): 63 | """ Call the encoder API to encode the program and emit the result.""" 64 | code = request.form['codeContents'] 65 | randomLen = int(request.form['randomLen']) 66 | if DEBUG_MD: 67 | print("code: %s" % str(code)) 68 | print("randomLen: %s" % str(randomLen)) 69 | ofsCode = obfuscate.getObfuscatedCode(code, randomLen=randomLen) 70 | socketio.emit('encoderesult', {'data': ofsCode}) 71 | return 'Python source code obfuscation encoded.' 72 | 73 | #----------------------------------------------------------------------------- 74 | @app.route('/decoder') 75 | def decoder(): 76 | """ route to introduction index page.""" 77 | posts = {'page': 2} # page index is used to highlight the left page slide bar. 78 | return render_template('obfdecoder.html', posts=posts) 79 | 80 | @app.route('/decodesubmit', methods=['POST']) 81 | def decodesubmit(): 82 | """ Call the decoder API to encode the program and emit the result.""" 83 | code = request.form['codeContents'] 84 | checkboxVal = request.form.get('removeCmt') 85 | removCmtFlg = False if checkboxVal is None else True 86 | if str(code).startswith("b'"): code = str(code)[2:] 87 | if str(code).endswith("'"):code = str(code)[:-1] 88 | reusltCode = obfuscate.obfDecode(code.encode('utf-8'), removeCmt=removCmtFlg) 89 | #print("removeCmt: [%s]" %str(checkbox_value)) 90 | socketio.emit('decoderesult', {'data': reusltCode}) 91 | return 'Python source code obfuscation decoded.' 92 | 93 | @app.route('/usagemanual') 94 | def usagemanual(): 95 | """ route to introduction index page.""" 96 | posts = {'page': 3} # page index is used to highlight the left page slide bar. 97 | return render_template('usagemanual.html', posts=posts) 98 | 99 | #----------------------------------------------------------------------------- 100 | # socketIO communication handling functions. 101 | @socketio.event 102 | def connect(): 103 | gWeblogCount = 0 104 | emit('serv_response', 105 | {'data': 'server ready', 'count': gWeblogCount,}) 106 | 107 | #----------------------------------------------------------------------------- 108 | #----------------------------------------------------------------------------- 109 | if __name__ == '__main__': 110 | # app.run(host="0.0.0.0", port=5000, debug=False, threaded=True) 111 | app.run(host=gflaskHost, 112 | port=gflaskPort, 113 | debug=gflaskDebug, 114 | threaded=gflaskMultiTH) 115 | -------------------------------------------------------------------------------- /src/static/img/consoleRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/consoleRun.png -------------------------------------------------------------------------------- /src/static/img/logo_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/logo_normal.png -------------------------------------------------------------------------------- /src/static/img/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/logo_small.png -------------------------------------------------------------------------------- /src/static/img/sysWorkflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/sysWorkflow.png -------------------------------------------------------------------------------- /src/static/img/useDecoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/useDecoder.png -------------------------------------------------------------------------------- /src/static/img/useEncoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuYuancheng/Py-Code-Obfuscator/8f03c346324b8384f3eca4bb7cb92d88e1e9bfb0/src/static/img/useEncoder.png -------------------------------------------------------------------------------- /src/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block link%} {% endblock %} 15 | {% block script%} {% endblock %} 16 | {% block title %} {% endblock %} 17 | {% block style %} {% endblock %} 18 | 19 | 20 | 21 | 22 | 55 | 56 | 57 |
58 | {% block content %} 59 | {% endblock %} 60 |
61 |
62 |

Copyright 2024 © LiuYuancheng

63 |

Phone: +65 Address: NCL COM3-B1-09 Computing 3, 11 Research Link, Singapore 119391

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /src/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'mgmbase.html' %} 2 | 3 | {% block title %} Python Program Obfuscator {% endblock %} 4 | 5 | {% block style%} {% endblock %} 6 | 7 | {% block mgmContent %} 8 | 9 | 90 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/mgmbase.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html'%} 2 | 3 | {% block content %} 4 |
5 |
6 | 27 | 28 |
29 | {% block mgmContent %} 30 | {% endblock %} 31 |
32 |
33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /src/templates/obfdecoder.html: -------------------------------------------------------------------------------- 1 | {% extends 'mgmbase.html' %} 2 | 3 | {% block title %} Python Obfuscate Decoder {% endblock %} 4 | 5 | {% block style%} {% endblock %} 6 | 7 | {% block mgmContent %} 8 | 9 | 50 | 51 | 90 | 91 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/obfencoder.html: -------------------------------------------------------------------------------- 1 | {% extends 'mgmbase.html' %} 2 | 3 | {% block title %} Python Obfuscate Encoder {% endblock %} 4 | 5 | {% block style%} {% endblock %} 6 | 7 | {% block mgmContent %} 8 | 9 | 48 | 49 | 88 | 89 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/usagemanual.html: -------------------------------------------------------------------------------- 1 | {% extends 'mgmbase.html' %} 2 | 3 | {% block title %} Threats To MITRE Configuration {% endblock %} 4 | 5 | {% block style%} {% endblock %} 6 | 7 | {% block mgmContent %} 8 | 9 | 80 | 81 | {% endblock %} --------------------------------------------------------------------------------