├── .DS_Store
├── .idea
├── .gitignore
├── inspectionProfiles
│ └── profiles_settings.xml
├── material_theme_project_new.xml
├── misc.xml
├── mitmproxy-gui.iml
├── modules.xml
└── vcs.xml
├── __pycache__
└── mitmproxy_gui.cpython-39.pyc
├── readme.md
├── requirements.txt
├── resource
├── icon
│ ├── 开关-关.png
│ └── 开关-开.png
├── logo
│ └── img.png
└── themes
│ ├── dark.qss
│ └── light.qss
└── src
├── .idea
├── .gitignore
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── material_theme_project_new.xml
├── misc.xml
├── modules.xml
└── src.iml
├── __init__.py
├── __pycache__
├── __init__.cpython-39.pyc
└── main.cpython-39.pyc
├── button
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-39.pyc
│ └── button.cpython-39.pyc
└── button.py
├── constants
├── __pycache__
│ ├── encryption_constants.cpython-39.pyc
│ ├── error_messages.cpython-39.pyc
│ ├── message_constants.cpython-39.pyc
│ ├── mode_constants.cpython-39.pyc
│ └── ui_constants.cpython-39.pyc
├── encryption_constants.py
├── error_messages.py
├── message_constants.py
├── mode_constants.py
└── ui_constants.py
├── highlighter
├── __pycache__
│ ├── log_highlighter.cpython-39.pyc
│ └── python_highlighter.cpython-39.pyc
├── log_highlighter.py
└── python_highlighter.py
├── log
├── __init__.py
└── logging_config.py
├── main.py
├── main_table
├── __init__.py
└── intercept_table.py
├── mode
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-39.pyc
│ └── mode.cpython-39.pyc
└── mode.py
├── network
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-39.pyc
│ ├── mitmproxy_packet_capture.cpython-39.pyc
│ └── shard.cpython-39.pyc
├── mitmproxy_packet_capture.py
└── shard.py
├── otherTools
├── QueryStringParser.py
├── __init__.py
├── __pycache__
│ ├── QueryStringParser.cpython-39.pyc
│ ├── __init__.cpython-39.pyc
│ ├── rsa_handler.cpython-39.pyc
│ └── script_loader.cpython-39.pyc
├── rsa_handler.py
└── script_loader.py
├── scripts
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-39.pyc
│ └── script_config.cpython-39.pyc
├── bothTools
│ ├── __pycache__
│ │ ├── aes_cbc.cpython-39.pyc
│ │ ├── base64.cpython-39.pyc
│ │ ├── des_cbc.cpython-39.pyc
│ │ └── rsa.cpython-39.pyc
│ ├── aes_cbc.py
│ ├── aes_ecb.py
│ ├── aes_gcm.py
│ ├── base64.py
│ ├── des3_cbc.py
│ ├── des_cbc.py
│ └── rsa.py
├── decryptTools
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── aes_cbc.cpython-39.pyc
│ │ ├── aes_ecb.cpython-39.pyc
│ │ ├── aes_gcm.cpython-39.pyc
│ │ ├── base64.cpython-39.pyc
│ │ ├── des3_cbc.cpython-39.pyc
│ │ ├── des_cbc.cpython-39.pyc
│ │ └── rsa.cpython-39.pyc
│ ├── aes_cbc.py
│ ├── aes_ecb.py
│ ├── aes_gcm.py
│ ├── base64.py
│ ├── des3_cbc.py
│ ├── des_cbc.py
│ ├── private.pem
│ ├── rsa.py
│ ├── rsa_private_key.pem
│ └── rsa_public_key.pem
├── encryptTools
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── aes.cpython-39.pyc
│ │ ├── aes_cbc.cpython-39.pyc
│ │ ├── aes_ecb.cpython-39.pyc
│ │ ├── base64.cpython-39.pyc
│ │ ├── des3_cbc.cpython-39.pyc
│ │ ├── des_cbc.cpython-39.pyc
│ │ ├── md5.cpython-39.pyc
│ │ ├── rsa.cpython-39.pyc
│ │ ├── sha1.cpython-39.pyc
│ │ ├── sha256.cpython-39.pyc
│ │ ├── sha384.cpython-39.pyc
│ │ └── sha512.cpython-39.pyc
│ ├── aes_cbc.py
│ ├── aes_ecb.py
│ ├── base64.py
│ ├── des3_cbc.py
│ ├── des_cbc.py
│ ├── md5.py
│ ├── rsa.py
│ ├── rsa_private_key.pem
│ ├── rsa_public_key.pem
│ ├── sha1.py
│ ├── sha256.py
│ ├── sha384.py
│ └── sha512.py
├── hookTools
│ ├── __init__.py
│ └── test.py
└── test
│ ├── des3_cbc_test.py
│ └── des_cbc_test.py
├── themes
├── __pycache__
│ └── theme.cpython-39.pyc
└── theme.py
├── thread
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-39.pyc
│ └── mitmproxy_thread.cpython-39.pyc
└── mitmproxy_thread.py
├── ui
├── __init__.py
├── __pycache__
│ └── __init__.cpython-39.pyc
└── mitmproxy_gui.ui
└── validator
├── KeyValidator.py
├── PortValidator.py
├── __init__.py
└── __pycache__
├── KeyValidator.cpython-39.pyc
├── PortValidator.cpython-39.pyc
└── __init__.cpython-39.pyc
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/.DS_Store
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/material_theme_project_new.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/mitmproxy-gui.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/__pycache__/mitmproxy_gui.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/__pycache__/mitmproxy_gui.cpython-39.pyc
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Mitmproxy GUI
2 |
3 | 一个基于 Mitmproxy 的 GUI 工具,支持多种加密算法的请求拦截和修改。
4 |
5 | ## 功能特点
6 |
7 | - 图形化界面,操作简单直观
8 | - 支持多种加密算法:
9 | - RSA
10 | - DES (ECB/CBC)
11 | - AES (ECB/CBC)
12 | - Base64
13 | - 支持三种工作模式:
14 | - 加密模式
15 | - 解密模式
16 | - 双向模式(同时支持加密和解密)
17 | - 支持 JSON 和表单数据的处理
18 | - 实时显示请求详情和日志
19 | - 支持多字段同时加解密
20 | - 支持自定义上游代理
21 |
22 | ## 安装要求
23 |
24 | - Python 3.8+
25 | - PyQt6
26 | - mitmproxy 9.0+
27 | - pycryptodome
28 |
29 | ## 快速开始
30 |
31 | 1. 安装依赖:
32 |
33 | bash
34 |
35 | pip install -r requirements.txt
36 |
37 |
38 |
39 | ## 使用说明
40 |
41 |
42 |
43 | 进入 src 目录
44 |
45 | ```python
46 | python main.py
47 | ```
48 |
49 |
50 |
51 | ### 基本设置
52 |
53 | 1. 选择工作模式(加密/解密/双向)
54 | 2. 选择加密算法
55 | 3. 设置监听端口(默认 8888)
56 | 4. 设置上游代理端口(默认 8080)
57 | 5. 输入需要处理的字段名(多个字段用逗号分隔)
58 | 6. 输入密钥和 IV(如果需要)
59 |
60 |
61 |
62 |
63 | ### 加密模式
64 |
65 | - 监听指定端口
66 | - 对请求数据进行加密处理
67 | - 支持的数据格式:
68 | - application/json
69 | - application/x-www-form-urlencoded
70 |
71 | ### 解密模式
72 |
73 | - 监听指定端口
74 | - 对请求数据进行解密处理
75 | - 自动转发到上游代理
76 |
77 | ### 双向模式
78 |
79 | - 同时启动加密和解密代理
80 | - 支持请求数据的实时加解密
81 | - 自动处理上下游代理转发
82 |
83 | ## 支持的加密算法
84 |
85 | ### RSA
86 |
87 | - 支持公钥加密/私钥解密
88 | - 支持 .pem 格式密钥文件
89 | - 支持 Base64 格式密钥
90 |
91 | ### DES
92 |
93 | - 支持 ECB/CBC 模式
94 | - 支持自定义 IV(CBC 模式)
95 | - 支持 PKCS7 填充
96 |
97 | ### AES
98 |
99 | - 支持 ECB/CBC 模式
100 | - 支持自定义 IV(CBC 模式)
101 | - 支持 PKCS7 填充
102 |
103 | ### Base64
104 |
105 | - 支持标准 Base64 编码/解码
106 | - 支持 URL 安全的 Base64 编码/解码
107 |
108 | ## 项目结构
109 |
110 | ## 使用说明
111 |
112 | ### 基本设置
113 |
114 | 1. 选择工作模式(加密/解密/双向)
115 | 2. 选择加密算法
116 | 3. 设置监听端口(默认 8888)
117 | 4. 设置上游代理端口(默认 8080)
118 | 5. 输入需要处理的字段名(多个字段用逗号分隔)
119 | 6. 输入密钥和 IV(如果需要)
120 |
121 | ### 加密模式
122 |
123 | - 监听指定端口
124 | - 对请求数据进行加密处理
125 | - 支持的数据格式:
126 | - application/json
127 | - application/x-www-form-urlencoded
128 |
129 | ### 解密模式
130 |
131 | - 监听指定端口
132 | - 对请求数据进行解密处理
133 | - 自动转发到上游代理
134 |
135 | ### 双向模式
136 |
137 | - 同时启动加密和解密代理
138 | - 支持请求数据的实时加解密
139 | - 自动处理上下游代理转发
140 |
141 | ## 支持的加密算法
142 |
143 | ### RSA
144 |
145 | - 支持公钥加密/私钥解密
146 | - 支持 .pem 格式密钥文件
147 | - 支持 Base64 格式密钥
148 |
149 | ### DES
150 |
151 | - 支持 ECB/CBC 模式
152 | - 支持自定义 IV(CBC 模式)
153 | - 支持 PKCS7 填充
154 |
155 | ### AES
156 |
157 | - 支持 ECB/CBC 模式
158 | - 支持自定义 IV(CBC 模式)
159 | - 支持 PKCS7 填充
160 |
161 | ### Base64
162 |
163 | - 支持标准 Base64 编码/解码
164 | - 支持 URL 安全的 Base64 编码/解码
165 |
166 | ## 项目结构
167 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/requirements.txt
--------------------------------------------------------------------------------
/resource/icon/开关-关.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/resource/icon/开关-关.png
--------------------------------------------------------------------------------
/resource/icon/开关-开.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/resource/icon/开关-开.png
--------------------------------------------------------------------------------
/resource/logo/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/resource/logo/img.png
--------------------------------------------------------------------------------
/resource/themes/dark.qss:
--------------------------------------------------------------------------------
1 | /* Modern Dark Theme - Mitmproxy GUI Pro */
2 | /*****************************************/
3 |
4 | QMainWindow, QWidget {
5 | background-color: #2b2b2b;
6 | color: #e0e0e0;
7 | font-family: 'Segoe UI', sans-serif;
8 | font-size: 13px;
9 | }
10 |
11 | /* ========== Global Text Styles ========== */
12 | QLabel {
13 | color: #a0a0a0;
14 | font-weight: 500;
15 | }
16 |
17 | QGroupBox {
18 | border: 1px solid #424647;
19 | border-radius: 4px;
20 | margin-top: 20px;
21 | padding-top: 15px;
22 | }
23 |
24 | QGroupBox::title {
25 | subcontrol-origin: margin;
26 | left: 10px;
27 | color: #7f8c8d;
28 | font-weight: bold;
29 | }
30 |
31 | /* ========== Input Fields ========== */
32 | QLineEdit, QTextEdit, QComboBox {
33 | background-color: #353535;
34 | border: 1px solid #404040;
35 | border-radius: 3px;
36 | padding: 5px 8px;
37 | min-height: 25px;
38 | selection-background-color: #3d8ec9;
39 | }
40 |
41 | QLineEdit:hover, QTextEdit:hover, QComboBox:hover {
42 | border-color: #4a4a4a;
43 | }
44 |
45 | QLineEdit:focus, QTextEdit:focus, QComboBox:focus {
46 | border-color: #3d8ec9;
47 | background-color: #424647;
48 | }
49 |
50 | /* ========== Buttons ========== */
51 | QPushButton {
52 | background-color: #424647;
53 | border: 1px solid #404040;
54 | border-radius: 4px;
55 | color: #e0e0e0;
56 | padding: 6px 15px;
57 | min-width: 80px;
58 | transition: all 0.3s ease;
59 | }
60 |
61 | QPushButton:hover {
62 | background-color: #444;
63 | border-color: #4a4a4a;
64 | }
65 |
66 | QPushButton:pressed {
67 | background-color: #333;
68 | border-color: #383838;
69 | }
70 |
71 | QPushButton[text="Start Proxy"] {
72 | background-color: #3d8ec9; /* 使用你指定的蓝色 */
73 | border-color: #1d8348; /* 边框颜色保持不变 */
74 | color: white;
75 | font-weight: bold;
76 | }
77 |
78 | QPushButton[text="Intercept Off"] {
79 | background: #424647;
80 |
81 | }
82 |
83 | /* ========== Tab Widget ========== */
84 | QTabWidget::pane {
85 | border: 1px solid #424647;
86 | top: -1px;
87 | background: #323232;
88 | }
89 |
90 | QTabBar::tab {
91 | background: #424647;
92 | border: 1px solid #404040;
93 | color: #a0a0a0;
94 | padding: 8px 20px;
95 | margin-right: 2px;
96 | border-top-left-radius: 4px;
97 | border-top-right-radius: 4px;
98 | }
99 |
100 | QTabBar::tab:selected {
101 | background: #323232;
102 | border-bottom-color: #323232;
103 | color: #e0e0e0;
104 | }
105 |
106 | QTabBar::tab:hover {
107 | background: #424242;
108 | }
109 |
110 | /* ========== Table Widget ========== */
111 | QTableWidget {
112 | background: #323334;
113 | gridline-color: #424647;
114 | border: none;
115 | alternate-background-color: #2a2a2a;
116 | }
117 |
118 | QHeaderView::section {
119 | background-color: #353535;
120 | color: #e0e0e0;
121 | padding: 6px;
122 | border: none;
123 | border-bottom: 2px solid #3d8ec9;
124 | }
125 |
126 | QTableWidget::item {
127 | padding: 5px;
128 | border-bottom: 1px solid #383838;
129 | }
130 |
131 | QTableWidget::item:selected {
132 | background-color: #3d8ec9;
133 | color: white;
134 | }
135 |
136 | /* ========== Scrollbars ========== */
137 | QScrollBar:vertical {
138 | background: #353535;
139 | width: 12px;
140 | }
141 |
142 | QScrollBar::handle:vertical {
143 | background: #4a4a4a;
144 | min-height: 20px;
145 | border-radius: 6px;
146 | }
147 |
148 | QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
149 | background: none;
150 | }
151 |
152 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
153 | background: none;
154 | }
155 |
156 | /* ========== ComboBox ========== */
157 | QComboBox::drop-down {
158 | subcontrol-origin: padding;
159 | subcontrol-position: top right;
160 | width: 20px;
161 | border-left: 1px solid #404040;
162 | }
163 |
164 | QComboBox QAbstractItemView {
165 | background: #353535;
166 | border: 1px solid #404040;
167 | color: #e0e0e0;
168 | selection-background-color: #3d8ec9;
169 | }
170 |
171 | /* ========== Progress Bars ========== */
172 | QProgressBar {
173 | border: 1px solid #404040;
174 | border-radius: 3px;
175 | text-align: center;
176 | background: #353535;
177 | }
178 |
179 | QProgressBar::chunk {
180 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
181 | stop:0 #3d8ec9, stop:1 #2b6ca3);
182 | border-radius: 2px;
183 | }
184 |
185 | /* ========== Checkboxes/Radios ========== */
186 | QCheckBox::indicator, QRadioButton::indicator {
187 | width: 16px;
188 | height: 16px;
189 | border: 1px solid #4a4a4a;
190 | }
191 |
192 | QCheckBox::indicator:checked {
193 | background-color: #3d8ec9;
194 | image: url(:/icons/check_light.svg);
195 | }
196 |
197 | QRadioButton::indicator:checked {
198 | background-color: #3d8ec9;
199 | border: 4px solid #424647;
200 | }
201 |
202 | /* ========== Tooltips ========== */
203 | QToolTip {
204 | background-color: #353535;
205 | color: #e0e0e0;
206 | border: 1px solid #404040;
207 | border-radius: 3px;
208 | padding: 5px;
209 | }
210 |
211 | /* ========== Splitter ========== */
212 | QSplitter::handle {
213 | background: #424647;
214 | height: 5px;
215 | }
216 |
217 | QSplitter::handle:hover {
218 | background: #3d8ec9;
219 | }
220 |
221 | /* ========== Menu Bar ========== */
222 | QMenuBar {
223 | background-color: #353535;
224 | border-bottom: 1px solid #404040;
225 | }
226 |
227 | QMenuBar::item {
228 | padding: 5px 15px;
229 | color: #a0a0a0;
230 | }
231 |
232 | QMenuBar::item:selected {
233 | background: #444;
234 | }
235 |
236 | QMenu {
237 | background-color: #353535;
238 | border: 1px solid #404040;
239 | padding: 5px;
240 | }
241 |
242 | QMenu::item {
243 | padding: 5px 25px;
244 | }
245 |
246 | QMenu::item:selected {
247 | background-color: #3d8ec9;
248 | color: white;
249 | }
250 |
251 | /* ========== Status Bar ========== */
252 | QStatusBar {
253 | background: #353535;
254 | border-top: 1px solid #404040;
255 | }
256 |
257 | QStatusBar::item {
258 | border: none;
259 | }
260 |
261 | /* 为水平布局中的QLineEdit添加弹性布局 */
262 | QHBoxLayout QLineEdit {
263 | flex: 1;
264 | }
265 |
266 | /* 调整FormLayout中标签和输入框的间距 */
267 | QFormLayout {
268 | spacing: 8px;
269 | }
270 |
271 | /* 优化输入框组的样式 */
272 | QLineEdit {
273 | margin-right: 4px;
274 | }
275 |
276 | QLineEdit:last-child {
277 | margin-right: 0;
278 | }
279 |
280 | QTextEdit {
281 | background-color: #353535;
282 | border: 1px solid #404040;
283 | border-radius: 3px;
284 | padding: 5px 8px;
285 | min-height: 25px;
286 | selection-background-color: #3d8ec9;
287 | font-size: 14pt;
288 | }
--------------------------------------------------------------------------------
/resource/themes/light.qss:
--------------------------------------------------------------------------------
1 | /* Modern Light Theme - Mitmproxy GUI Pro */
2 | /******************************************/
3 |
4 | QMainWindow, QWidget {
5 | background-color: #f5f6fa;
6 | color: #2d3436;
7 | font-family: 'Segoe UI', sans-serif;
8 | font-size: 13px;
9 | }
10 |
11 | /* ========== Global Text Styles ========== */
12 | QLabel {
13 | color: #636e72;
14 | font-weight: 500;
15 | }
16 |
17 | QGroupBox {
18 | border: 1px solid #dcdde1;
19 | border-radius: 4px;
20 | margin-top: 20px;
21 | padding-top: 15px;
22 | }
23 |
24 | QGroupBox::title {
25 | subcontrol-origin: margin;
26 | left: 10px;
27 | color: #747d8c;
28 | font-weight: bold;
29 | }
30 |
31 | /* ========== Input Fields ========== */
32 | QLineEdit, QTextEdit, QComboBox {
33 | background-color: white;
34 | border: 1px solid #dcdde1;
35 | border-radius: 3px;
36 | padding: 5px 8px;
37 | min-height: 25px;
38 | selection-background-color: #74b9ff;
39 | }
40 |
41 | QLineEdit:hover, QTextEdit:hover, QComboBox:hover {
42 | border-color: #a4b0be;
43 | }
44 |
45 | QLineEdit:focus, QTextEdit:focus, QComboBox:focus {
46 | border-color: #74b9ff;
47 | background-color: white;
48 | }
49 |
50 | /* ========== Buttons ========== */
51 | QPushButton {
52 | background-color: white;
53 | border: 1px solid #dcdde1;
54 | border-radius: 4px;
55 | color: #2d3436;
56 | padding: 6px 15px;
57 | min-width: 80px;
58 | transition: all 0.3s ease;
59 | }
60 |
61 | QPushButton:hover {
62 | background-color: #f8f9fa;
63 | border-color: #a4b0be;
64 | }
65 |
66 | QPushButton:pressed {
67 | background-color: #f1f2f6;
68 | border-color: #ced6e0;
69 | }
70 |
71 | QPushButton[text="Start Proxy"] {
72 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
73 | stop:0 #2ecc71, stop:1 #27ae60);
74 | border-color: #219a52;
75 | color: white;
76 | font-weight: bold;
77 | }
78 |
79 | QPushButton[text="Intercept"] {
80 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
81 | stop:0 #3498db, stop:1 #2980b9);
82 | border-color: #2472a4;
83 | }
84 |
85 | /* ========== Tab Widget ========== */
86 | QTabWidget::pane {
87 | border: 1px solid #dcdde1;
88 | top: -1px;
89 | background: white;
90 | }
91 |
92 | QTabBar::tab {
93 | background: #f8f9fa;
94 | border: 1px solid #dcdde1;
95 | color: #747d8c;
96 | padding: 8px 20px;
97 | margin-right: 2px;
98 | border-top-left-radius: 4px;
99 | border-top-right-radius: 4px;
100 | }
101 |
102 | QTabBar::tab:selected {
103 | background: white;
104 | border-bottom-color: white;
105 | color: #2d3436;
106 | }
107 |
108 | QTabBar::tab:hover {
109 | background: #f1f2f6;
110 | }
111 |
112 | /* ========== Table Widget ========== */
113 | QTableWidget {
114 | background: white;
115 | gridline-color: #dcdde1;
116 | border: none;
117 | alternate-background-color: #f8f9fa;
118 | }
119 |
120 | QHeaderView::section {
121 | background-color: #f8f9fa;
122 | color: #2d3436;
123 | padding: 6px;
124 | border: none;
125 | border-bottom: 2px solid #74b9ff;
126 | }
127 |
128 | QTableWidget::item {
129 | padding: 5px;
130 | border-bottom: 1px solid #f1f2f6;
131 | }
132 |
133 | QTableWidget::item:selected {
134 | background-color: #74b9ff;
135 | color: white;
136 | }
137 |
138 | /* ========== Scrollbars ========== */
139 | QScrollBar:vertical {
140 | background: #f8f9fa;
141 | width: 12px;
142 | }
143 |
144 | QScrollBar::handle:vertical {
145 | background: #ced6e0;
146 | min-height: 20px;
147 | border-radius: 6px;
148 | }
149 |
150 | QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
151 | background: none;
152 | }
153 |
154 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
155 | background: none;
156 | }
157 |
158 | /* ========== ComboBox ========== */
159 | QComboBox::drop-down {
160 | subcontrol-origin: padding;
161 | subcontrol-position: top right;
162 | width: 20px;
163 | border-left: 1px solid #dcdde1;
164 | }
165 |
166 | QComboBox QAbstractItemView {
167 | background: white;
168 | border: 1px solid #dcdde1;
169 | color: #2d3436;
170 | selection-background-color: #74b9ff;
171 | }
172 |
173 | /* ========== Progress Bars ========== */
174 | QProgressBar {
175 | border: 1px solid #dcdde1;
176 | border-radius: 3px;
177 | text-align: center;
178 | background: white;
179 | }
180 |
181 | QProgressBar::chunk {
182 | background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
183 | stop:0 #74b9ff, stop:1 #4a95d6);
184 | border-radius: 2px;
185 | }
186 |
187 | /* ========== Checkboxes/Radios ========== */
188 | QCheckBox::indicator, QRadioButton::indicator {
189 | width: 16px;
190 | height: 16px;
191 | border: 1px solid #a4b0be;
192 | }
193 |
194 | QCheckBox::indicator:checked {
195 | background-color: #74b9ff;
196 | image: url(:/icons/check_dark.svg);
197 | }
198 |
199 | QRadioButton::indicator:checked {
200 | background-color: #74b9ff;
201 | border: 4px solid white;
202 | }
203 |
204 | /* ========== Tooltips ========== */
205 | QToolTip {
206 | background-color: white;
207 | color: #2d3436;
208 | border: 1px solid #dcdde1;
209 | border-radius: 3px;
210 | padding: 5px;
211 | }
212 |
213 | /* ========== Splitter ========== */
214 | QSplitter::handle {
215 | background: #dcdde1;
216 | height: 5px;
217 | }
218 |
219 | QSplitter::handle:hover {
220 | background: #74b9ff;
221 | }
222 |
223 | /* ========== Menu Bar ========== */
224 | QMenuBar {
225 | background-color: white;
226 | border-bottom: 1px solid #dcdde1;
227 | }
228 |
229 | QMenuBar::item {
230 | padding: 5px 15px;
231 | }
232 |
233 | QTextEdit {
234 | background-color: white;
235 | border: 1px solid #dcdde1;
236 | border-radius: 3px;
237 | padding: 5px 8px;
238 | min-height: 25px;
239 | selection-background-color: #74b9ff;
240 | font-size: 14pt; /* 改为14pt */
241 | }
242 |
--------------------------------------------------------------------------------
/src/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/src/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/.idea/material_theme_project_new.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/.idea/src.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 | # 空文件,仅用于标记这是一个 Python 包
--------------------------------------------------------------------------------
/src/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/__pycache__/main.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/__pycache__/main.cpython-39.pyc
--------------------------------------------------------------------------------
/src/button/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/button/__init__.py
--------------------------------------------------------------------------------
/src/button/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/button/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/button/__pycache__/button.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/button/__pycache__/button.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/__pycache__/encryption_constants.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/constants/__pycache__/encryption_constants.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/__pycache__/error_messages.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/constants/__pycache__/error_messages.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/__pycache__/message_constants.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/constants/__pycache__/message_constants.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/__pycache__/mode_constants.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/constants/__pycache__/mode_constants.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/__pycache__/ui_constants.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/constants/__pycache__/ui_constants.cpython-39.pyc
--------------------------------------------------------------------------------
/src/constants/encryption_constants.py:
--------------------------------------------------------------------------------
1 | class EncryptionConstants:
2 | AES_ALGORITHMS = ['aes_cbc.py', 'aes_ecb.py', 'aes_cfb.py', 'aes_ofb.py', 'aes_ctr.py', 'aes_gcm.py', 'aes_ccm.py', 'aes_xts.py', 'aes_xts_128.py', 'aes_xts_256.py'] # 添加所有 AES 脚本
3 | DES_ALGORITHMS = ['des_cbc.py', 'des3_cbc','des_ecb.py', 'des_cfb.py', 'des_ofb.py', 'des_ctr.py', 'des_gcm.py', 'des_ccm.py', 'des_xts.py', 'des_xts_128.py', 'des_xts_256.py'] # 添加所有 DES 脚本
4 | HASH_ALGORITHMS = ['md5.py', 'sha1.py', 'sha256.py', 'sha512.py', 'hmac.py', 'hmac_md5.py', 'hmac_sha1.py', 'hmac_sha256.py', 'hmac_sha512.py'] # 添加所有哈希算法
5 | NO_KEY_ALGORITHMS = ['base64.py', 'md5.py','sha1.py','sha256.py','sha512.py','hmac.py','hmac_md5.py','hmac_sha1.py','hmac_sha256.py','hmac_sha512.py'] # 不需要密钥的算法
6 | AES_KEY_LENGTHS = [16, 24, 32] # AES 密钥长度
7 | DES_KEY_LENGTH = [8,16,24] # DES 密钥长度,3DES 秘钥长度
8 | IV_LENGTH = 16 # IV 长度
9 |
10 | # 不需要密钥的加密算法列表
11 | NO_KEY_ALGORITHMS = ['base64.py', 'md5.py','sha1.py','sha256.py','sha512.py','hmac.py','hmac_md5.py','hmac_sha1.py','hmac_sha256.py','hmac_sha512.py'] # 添加其他不需要密钥的算法
--------------------------------------------------------------------------------
/src/constants/error_messages.py:
--------------------------------------------------------------------------------
1 | class ErrorMessages:
2 |
3 | # 启动代理错误消息
4 | PROXY_START_ERROR = "❌ 启动代理失败: {}"
5 |
6 | # 秘钥错误消息
7 | EMPTY_KEY = "❌ 错误: 解密密钥不能为空"
8 | INVALID_MODE = "❌ 错误: 无效的模式"
9 | AES_KEY_LENGTH_ERROR = "❌ 错误: AES 密钥长度必须是 16、24 或 32 字节"
10 | DES_KEY_LENGTH_ERROR = "❌ 错误: DES 密钥长度必须是 8 字节,3DES 密钥长度必须是 16 或 24 字节"
11 | IV_LENGTH_ERROR = "❌ 错误: IV 必须是 16 字节长度"
12 | KEY_REQUIRED = "❌ 错误: 当前加密算法需要密钥"
13 | # 端口错误消息
14 | PORT_ERROR = "❌ 端口错误: {}"
15 |
16 |
--------------------------------------------------------------------------------
/src/constants/message_constants.py:
--------------------------------------------------------------------------------
1 | class MessageConstants:
2 | # 状态消息
3 | PROXY_STARTED = "✅ {} 模式抓包已启动"
4 | PROXY_STOPPED = "❌ 代理已停止"
5 | INTERCEPT_STARTED = "拦截已开启, Default Listen Port Is 8888"
6 | INTERCEPT_STOPPED = "拦截已停止"
7 | LOG_CLEARED = "✅ 日志已清空"
8 |
9 | # 秘钥消息
10 | DECRYPT_KEY_SAVED = "✅ 解密密钥保存成功: {}"
11 |
--------------------------------------------------------------------------------
/src/constants/mode_constants.py:
--------------------------------------------------------------------------------
1 | class ModeConstants:
2 | ENCRYPT = "Encrypt"
3 | DECRYPT = "Decrypt"
4 | BOTH = "Both"
5 | DEFAULT = "Default"
--------------------------------------------------------------------------------
/src/constants/ui_constants.py:
--------------------------------------------------------------------------------
1 | class UIConstants:
2 | # 链接
3 | GITHUB_URL = "https://github.com/blackguest007/"
4 |
5 | # 按钮文本
6 | BTN_START_PROXY = "Start Proxy"
7 | BTN_STOP_PROXY = "Stop Proxy"
8 | BTN_INTERCEPT_ON = "Intercept On"
9 | BTN_INTERCEPT_OFF = "Intercept Off"
10 |
11 | # 提示文本
12 | TOOLTIP_GITHUB = "访问项目 GitHub 页面"
13 | TOOLTIP_MENU = "访问 GitHub"
14 |
15 |
--------------------------------------------------------------------------------
/src/highlighter/__pycache__/log_highlighter.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/highlighter/__pycache__/log_highlighter.cpython-39.pyc
--------------------------------------------------------------------------------
/src/highlighter/__pycache__/python_highlighter.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/highlighter/__pycache__/python_highlighter.cpython-39.pyc
--------------------------------------------------------------------------------
/src/highlighter/log_highlighter.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | from PyQt6.QtCore import Qt
4 | from PyQt6.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont
5 |
6 |
7 | class LogHighlighter(QSyntaxHighlighter):
8 | def __init__(self, parent=None):
9 | super().__init__(parent)
10 |
11 | self.highlighting_rules = []
12 |
13 | # 成功信息格式(绿色)
14 | success_format = QTextCharFormat()
15 | success_format.setForeground(QColor("#98C379")) # 绿色
16 | success_format.setFontWeight(QFont.Weight.Bold)
17 | self.highlighting_rules.append((
18 | r"✅.*$", success_format
19 | ))
20 |
21 | # 错误信息格式(红色)
22 | error_format = QTextCharFormat()
23 | error_format.setForeground(QColor("#E06C75")) # 红色
24 | error_format.setFontWeight(QFont.Weight.Bold)
25 | self.highlighting_rules.append((
26 | r"❌.*$", error_format
27 | ))
28 |
29 | # 警告信息格式(黄色)
30 | warning_format = QTextCharFormat()
31 | warning_format.setForeground(QColor("#E5C07B")) # 黄色
32 | warning_format.setFontWeight(QFont.Weight.Bold)
33 | self.highlighting_rules.append((
34 | r"⚠.*$", warning_format
35 | ))
36 |
37 | # 加载脚本信息格式(蓝色)
38 | loading_format = QTextCharFormat()
39 | loading_format.setForeground(QColor("#61AFEF")) # 蓝色
40 | self.highlighting_rules.append((
41 | r"Loading script.*$", loading_format
42 | ))
43 |
44 | # 时间戳格式(灰色)
45 | timestamp_format = QTextCharFormat()
46 | timestamp_format.setForeground(QColor("#5C6370")) # 灰色
47 | self.highlighting_rules.append((
48 | r"\[\d{2}:\d{2}:\d{2}\.\d{3}\]", timestamp_format
49 | ))
50 |
51 | # 命令执行格式(青色)
52 | command_format = QTextCharFormat()
53 | command_format.setForeground(QColor("#56B6C2")) # 青色
54 | self.highlighting_rules.append((
55 | r"执行命令:.*$", command_format
56 | ))
57 |
58 | # 普通日志格式(白色)
59 | info_format = QTextCharFormat()
60 | info_format.setForeground(QColor("#ABB2BF")) # 浅灰白色
61 | self.highlighting_rules.append((
62 | r"^(?!✅|❌|⚠|\[|Loading|执行命令).*$", info_format
63 | ))
64 |
65 | def highlightBlock(self, text):
66 | """高亮文本块"""
67 | for pattern, format in self.highlighting_rules:
68 | for match in re.finditer(pattern, text):
69 | self.setFormat(match.start(), match.end() - match.start(), format)
--------------------------------------------------------------------------------
/src/highlighter/python_highlighter.py:
--------------------------------------------------------------------------------
1 | from PyQt6.QtCore import Qt
2 | from PyQt6.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont
3 | import re
4 |
5 | class PythonHighlighter(QSyntaxHighlighter):
6 | def __init__(self, parent=None):
7 | super().__init__(parent)
8 |
9 | self.highlighting_rules = []
10 |
11 | # 关键字格式
12 | keyword_format = QTextCharFormat()
13 | keyword_format.setForeground(QColor("#FF6B6B"))
14 | keyword_format.setFontWeight(QFont.Weight.Bold)
15 | keywords = [
16 | # 基础关键字
17 | "and", "as", "assert", "break", "class", "continue", "def",
18 | "del", "elif", "else", "except", "False", "finally", "for",
19 | "from", "global", "if", "import", "in", "is", "lambda", "None",
20 | "nonlocal", "not", "or", "pass", "raise", "return", "True",
21 | "try", "while", "with", "yield",
22 | # 扩展关键字
23 | "self", "cls", "async", "await", "match", "case"
24 | ]
25 | for word in keywords:
26 | self.highlighting_rules.append((
27 | f"\\b{word}\\b", keyword_format
28 | ))
29 |
30 | # 内置函数格式
31 | builtin_format = QTextCharFormat()
32 | builtin_format.setForeground(QColor("#C678DD"))
33 | builtins = [
34 | "abs", "all", "any", "bin", "bool", "bytes", "callable", "chr",
35 | "classmethod", "compile", "complex", "delattr", "dict", "dir",
36 | "divmod", "enumerate", "eval", "exec", "filter", "float", "format",
37 | "frozenset", "getattr", "globals", "hasattr", "hash", "help", "hex",
38 | "id", "input", "int", "isinstance", "issubclass", "iter", "len",
39 | "list", "locals", "map", "max", "min", "next", "object", "oct",
40 | "open", "ord", "pow", "print", "property", "range", "repr",
41 | "reversed", "round", "set", "setattr", "slice", "sorted",
42 | "staticmethod", "str", "sum", "super", "tuple", "type", "vars",
43 | "zip", "__import__"
44 | ]
45 | for word in builtins:
46 | self.highlighting_rules.append((
47 | f"\\b{word}\\b", builtin_format
48 | ))
49 |
50 | # 装饰器格式
51 | decorator_format = QTextCharFormat()
52 | decorator_format.setForeground(QColor("#E5C07B"))
53 | self.highlighting_rules.append((
54 | r"@\w+", decorator_format
55 | ))
56 |
57 | # 字符串格式(包括三引号字符串)
58 | string_format = QTextCharFormat()
59 | string_format.setForeground(QColor("#98C379"))
60 | self.highlighting_rules.extend([
61 | (r'"[^"\\]*(\\.[^"\\]*)*"', string_format),
62 | (r"'[^'\\]*(\\.[^'\\]*)*'", string_format),
63 | (r'""".*?"""', string_format),
64 | (r"'''.*?'''", string_format)
65 | ])
66 |
67 | # 注释格式
68 | comment_format = QTextCharFormat()
69 | comment_format.setForeground(QColor("#5C6370"))
70 | comment_format.setFontItalic(True)
71 | self.highlighting_rules.append((
72 | r"#[^\n]*", comment_format
73 | ))
74 |
75 | # 函数定义格式
76 | function_format = QTextCharFormat()
77 | function_format.setForeground(QColor("#61AFEF"))
78 | self.highlighting_rules.append((
79 | r"\bdef\s+(\w+)", function_format
80 | ))
81 |
82 | # 类定义格式
83 | class_format = QTextCharFormat()
84 | class_format.setForeground(QColor("#E5C07B"))
85 | class_format.setFontWeight(QFont.Weight.Bold)
86 | self.highlighting_rules.append((
87 | r"\bclass\s+(\w+)", class_format
88 | ))
89 |
90 | # 数字格式
91 | number_format = QTextCharFormat()
92 | number_format.setForeground(QColor("#D19A66"))
93 | self.highlighting_rules.extend([
94 | (r"\b[0-9]+\b", number_format),
95 | (r"\b0[xX][0-9a-fA-F]+\b", number_format), # 十六进制
96 | (r"\b0[oO][0-7]+\b", number_format), # 八进制
97 | (r"\b0[bB][01]+\b", number_format), # 二进制
98 | (r"\b\d*\.\d+\b", number_format), # 浮点数
99 | ])
100 |
101 | # 特殊方法格式(魔术方法)
102 | magic_format = QTextCharFormat()
103 | magic_format.setForeground(QColor("#56B6C2"))
104 | self.highlighting_rules.append((
105 | r"__\w+__", magic_format
106 | ))
107 |
108 | def highlightBlock(self, text):
109 | for pattern, format in self.highlighting_rules:
110 | for match in re.finditer(pattern, text):
111 | self.setFormat(match.start(), match.end() - match.start(), format)
--------------------------------------------------------------------------------
/src/log/__init__.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 |
--------------------------------------------------------------------------------
/src/log/logging_config.py:
--------------------------------------------------------------------------------
1 | # src/log/logger.py
2 | import logging
3 |
4 | def setup_logging():
5 | logging.basicConfig(level=logging.INFO,
6 | format='%(asctime)s - %(levelname)s - %(message)s')
7 |
--------------------------------------------------------------------------------
/src/main.py:
--------------------------------------------------------------------------------
1 | # path: /src/main.py
2 |
3 | # 主程序
4 |
5 | import warnings
6 | import os
7 | import sys
8 | from PyQt6.QtWidgets import QApplication, QMainWindow
9 | from PyQt6.uic import loadUi
10 | from PyQt6.QtGui import QFont, QIcon
11 | from PyQt6.QtWidgets import QTextEdit
12 | from PyQt6.QtCore import Qt
13 |
14 | # 过滤掉 Qt 的 transition 属性警告
15 | warnings.filterwarnings("ignore", "Unknown property transition")
16 | # 过滤掉 sip 的废弃警告
17 | warnings.filterwarnings("ignore", "sipPyTypeDict() is deprecated")
18 |
19 | from button.button import setup_buttons
20 | from highlighter.python_highlighter import PythonHighlighter
21 | from mode.mode import setup_mode_connections, update_mode
22 |
23 | from otherTools.script_loader import ScriptLoader
24 |
25 | from themes.theme import get_themes, init_themes
26 | from highlighter.log_highlighter import LogHighlighter
27 |
28 |
29 | class MainWindow(QMainWindow):
30 | def __init__(self):
31 | super().__init__()
32 |
33 | # 设置窗口标题
34 | self.setWindowTitle("mitmproxy-gui V1.0.0 Created by @LingDu")
35 |
36 | # 初始化属性
37 | self.mitm_threads = [] # 用于存储当前运行的线程
38 |
39 | # 首先加载UI
40 | self.load_ui() # 移到最前面
41 |
42 | # 设置窗口图标
43 | icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "resource", "logo", "img.png")
44 | if os.path.exists(icon_path):
45 | self.setWindowIcon(QIcon(icon_path))
46 | else:
47 | print(f"Warning: Icon file not found at {icon_path}")
48 |
49 | # 其他初始化
50 | self.initialize_script_loader()
51 | self.initialize_highlighters()
52 | self.setup_buttons()
53 | self.setup_themes()
54 |
55 | # 调用初始化函数
56 | self.initialize()
57 |
58 | def initialize_ui(self):
59 | """加载用户界面"""
60 | try:
61 | self.load_ui()
62 | except Exception as e:
63 | print(f"Error loading UI: {e}")
64 |
65 | def initialize_script_loader(self):
66 | """初始化脚本加载器"""
67 | try:
68 | self.script_loader = ScriptLoader(self)
69 | except Exception as e:
70 | print(f"Error initializing script loader: {e}")
71 |
72 | def initialize_highlighters(self):
73 | """初始化代码和日志高亮器"""
74 | try:
75 | self.init_code_highlighter()
76 | self.log_highlighter = LogHighlighter(self.packet_detail.document())
77 | except Exception as e:
78 | print(f"Error initializing highlighters: {e}")
79 |
80 | def setup_buttons(self):
81 | """设置按钮的信号连接"""
82 | setup_buttons(self)
83 |
84 | def setup_themes(self):
85 | """设置主题"""
86 | get_themes(self)
87 | init_themes(self)
88 |
89 | def setup_mode_connections(self):
90 | """设置模式连接"""
91 | setup_mode_connections(self)
92 |
93 | def load_ui(self):
94 | """ 加载 .ui 文件 """
95 | # 获取当前文件所在目录
96 | current_dir = os.path.dirname(os.path.abspath(__file__))
97 | # 构建 UI 文件的绝对路径
98 | ui_path = os.path.join(current_dir, "ui", "mitmproxy_gui.ui")
99 |
100 | if not os.path.exists(ui_path):
101 | raise FileNotFoundError(f"UI file not found: {ui_path}")
102 |
103 | loadUi(ui_path, self)
104 |
105 | def init_code_highlighter(self):
106 | """初始化代码高亮器"""
107 | # 设置代码编辑器字体
108 | font = QFont("Consolas")
109 | font.setPointSize(14) # 改为14pt
110 |
111 | # 修改为正确的控件名称
112 | self.encrypt_script_content.setFont(font)
113 | self.decrypt_script_content.setFont(font)
114 | self.both_script_content.setFont(font)
115 |
116 | # 启用Ctrl+滚轮缩放
117 | for editor in [self.encrypt_script_content, self.decrypt_script_content, self.both_script_content]:
118 | editor.setAcceptRichText(False) # 禁用富文本以确保正确的字体缩放
119 | editor.wheelEvent = lambda event, ed=editor: self._handle_wheel_event(event, ed)
120 |
121 | # 初始化高亮器
122 | self.highlighter_encrypt = PythonHighlighter(self.encrypt_script_content.document())
123 | self.highlighter_decrypt = PythonHighlighter(self.decrypt_script_content.document())
124 | self.highlighter_both = PythonHighlighter(self.both_script_content.document())
125 |
126 | def _handle_wheel_event(self, event, editor):
127 | """处理滚轮事件,实现Ctrl+滚轮缩放字体"""
128 | if event.modifiers() & Qt.KeyboardModifier.ControlModifier:
129 | delta = event.angleDelta().y()
130 | if delta > 0:
131 | editor.zoomIn()
132 | else:
133 | editor.zoomOut()
134 | else:
135 | # 调用原始的滚轮事件处理
136 | QTextEdit.wheelEvent(editor, event)
137 |
138 | def initialize(self):
139 | """初始化窗口设置"""
140 | # 设置默认模式
141 | self.mode_combo.setCurrentText("Default")
142 |
143 | # 更新UI状态
144 | update_mode(self) # 确保在显示窗口之前更新UI状态
145 |
146 |
147 | # 主程序入口
148 | if __name__ == "__main__":
149 | app = QApplication(sys.argv)
150 | window = MainWindow()
151 | window.show()
152 | sys.exit(app.exec())
153 |
--------------------------------------------------------------------------------
/src/main_table/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/main_table/__init__.py
--------------------------------------------------------------------------------
/src/main_table/intercept_table.py:
--------------------------------------------------------------------------------
1 | # path: /src/main_table/intercept_table.py
2 |
3 |
4 | from PyQt6.QtCore import QDateTime
5 | from PyQt6.QtWidgets import QTableWidgetItem
6 |
7 | class PacketTableUpdater:
8 | def __init__(self, window):
9 | self.window = window # 保存窗口对象,以便后续更新表格
10 |
11 | # 更新 intercept_table 中的字段
12 | def update_packet_table(self, data):
13 | """ 更新 QTableWidget 中的数据显示 """
14 | current_time = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
15 |
16 | row_position = self.window.packet_table.rowCount() # 获取当前表格的行数
17 | self.window.packet_table.insertRow(row_position) # 插入新的一行
18 |
19 | # 填充数据
20 | self.window.packet_table.setItem(row_position, 0, QTableWidgetItem(current_time))
21 | self.window.packet_table.setItem(row_position, 1, QTableWidgetItem(data['type']))
22 | self.window.packet_table.setItem(row_position, 2, QTableWidgetItem(data['direction'])) # 显示方向
23 | self.window.packet_table.setItem(row_position, 3, QTableWidgetItem(data['method']))
24 | self.window.packet_table.setItem(row_position, 4, QTableWidgetItem(data['url']))
25 | self.window.packet_table.setItem(row_position, 5, QTableWidgetItem(str(data['status_code'])))
26 | self.window.packet_table.setItem(row_position, 6, QTableWidgetItem(str(data['length'])))
27 |
--------------------------------------------------------------------------------
/src/mode/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/mode/__init__.py
--------------------------------------------------------------------------------
/src/mode/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/mode/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/mode/__pycache__/mode.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/mode/__pycache__/mode.cpython-39.pyc
--------------------------------------------------------------------------------
/src/mode/mode.py:
--------------------------------------------------------------------------------
1 | # path:/src/mode/mode.py
2 |
3 | # 初始化加密模式,并调整按钮更新
4 | def init_mode(window):
5 | """初始化模式相关的UI元素"""
6 |
7 | # 初始化显示状态
8 | update_mode(window)
9 |
10 | # 初始化Default模式的命令
11 | if hasattr(window, 'script_loader'):
12 | command = window.script_loader.generate_command(window)
13 | if command and hasattr(window, 'proxy_thread'):
14 | window.proxy_thread.command = command
15 |
16 |
17 | def update_mode(window):
18 | """根据当前模式更新UI状态"""
19 | current_mode = window.mode_combo.currentText()
20 |
21 | # 基础控制按钮只在Default模式显示
22 | control_buttons = [window.intercept_btn, window.forward_btn, window.drop_btn]
23 |
24 | if current_mode == "Default":
25 | window.start_btn.hide() # 在Default模式下隐藏Start Proxy按钮
26 | for btn in control_buttons:
27 | btn.show() # 显示基础控制按钮
28 | else:
29 | window.start_btn.show() # 在其他模式下显示Start Proxy按钮
30 | for btn in control_buttons:
31 | btn.hide() # 隐藏基础控制按钮
32 |
33 | # 更新加密参数输入框显示状态
34 | encrypt_params_label = window.encrypt_params_label
35 | encrypt_params_input = window.encrypt_params_input
36 |
37 | # 获取所有key和iv相关控件
38 | dec_key_label = window.dec_key_label
39 | dec_key_input = window.dec_key_input
40 | dec_iv_label = window.dec_iv_label
41 | dec_iv_input = window.dec_iv_input
42 | enc_key_label = window.enc_key_label
43 | enc_key_input = window.enc_key_input
44 | enc_iv_label = window.enc_iv_label
45 | enc_iv_input = window.enc_iv_input
46 |
47 | # 获取端口相关控件
48 | dec_port_label = window.label # dec_Listen Port label
49 | dec_port_input = window.lineEdit # dec_Listen Port input
50 | enc_port_label = window.listen_port_label # enc_Listen Port label
51 | enc_port_input = window.listen_port_input # enc_Listen Port input
52 |
53 | if current_mode == "Default":
54 | # 只显示监听端口
55 | dec_port_label.show()
56 | dec_port_input.show()
57 | dec_port_label.setText('Listen Port:') # 默认模式显示为 Listen Port
58 |
59 | # 隐藏其他所有控件
60 | encrypt_params_label.hide()
61 | encrypt_params_input.hide()
62 | dec_key_label.hide()
63 | dec_key_input.hide()
64 | dec_iv_label.hide()
65 | dec_iv_input.hide()
66 | enc_key_label.hide()
67 | enc_key_input.hide()
68 | enc_iv_label.hide()
69 | enc_iv_input.hide()
70 | window.upstream_label.hide()
71 | window.upstream_input.hide()
72 | enc_port_label.hide()
73 | enc_port_input.hide()
74 |
75 | elif current_mode == "Encrypt":
76 | # 显示加密相关控件
77 | encrypt_params_label.show()
78 | encrypt_params_input.show()
79 | enc_key_label.show()
80 | enc_key_input.show()
81 | enc_iv_label.show()
82 | enc_iv_input.show()
83 | enc_port_label.show()
84 | enc_port_input.show()
85 | enc_port_label.setText('Enc Listen Port:') # 加密模式显示为 Enc Listen Port
86 |
87 | # 隐藏解密相关控件
88 | dec_key_label.hide()
89 | dec_key_input.hide()
90 | dec_iv_label.hide()
91 | dec_iv_input.hide()
92 | window.upstream_label.hide()
93 | window.upstream_input.hide()
94 | dec_port_label.hide()
95 | dec_port_input.hide()
96 |
97 | elif current_mode == "Decrypt":
98 | # 显示解密相关控件
99 | encrypt_params_label.show()
100 | encrypt_params_input.show()
101 | dec_key_label.show()
102 | dec_key_input.show()
103 | dec_iv_label.show()
104 | dec_iv_input.show()
105 | dec_port_label.show()
106 | dec_port_input.show()
107 | dec_port_label.setText('Dec Listen Port:') # 解密模式显示为 Dec Listen Port
108 | window.upstream_label.show()
109 | window.upstream_input.show()
110 |
111 | # 隐藏加密相关控件
112 | enc_key_label.hide()
113 | enc_key_input.hide()
114 | enc_iv_label.hide()
115 | enc_iv_input.hide()
116 | enc_port_label.hide()
117 | enc_port_input.hide()
118 |
119 | elif current_mode == "Both":
120 | # 显示所有控件
121 | encrypt_params_label.show()
122 | encrypt_params_input.show()
123 | dec_key_label.show()
124 | dec_key_input.show()
125 | dec_iv_label.show()
126 | dec_iv_input.show()
127 | enc_key_label.show()
128 | enc_key_input.show()
129 | enc_iv_label.show()
130 | enc_iv_input.show()
131 | window.upstream_label.show()
132 | window.upstream_input.show()
133 | dec_port_label.show()
134 | dec_port_input.show()
135 | enc_port_label.show()
136 | enc_port_input.show()
137 |
138 | # Both模式下更新端口标签
139 | dec_port_label.setText('Dec Listen Port:') # 解密端口显示为 Dec Listen Port
140 | enc_port_label.setText('Enc Listen Port:') # 加密端口显示为 Enc Listen Port
141 |
142 | def setup_mode_connections(window):
143 | """设置模式相关的信号连接"""
144 | window.mode_combo.currentTextChanged.connect(lambda: update_mode(window))
145 |
--------------------------------------------------------------------------------
/src/network/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/network/__init__.py
--------------------------------------------------------------------------------
/src/network/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/network/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/network/__pycache__/mitmproxy_packet_capture.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/network/__pycache__/mitmproxy_packet_capture.cpython-39.pyc
--------------------------------------------------------------------------------
/src/network/__pycache__/shard.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/network/__pycache__/shard.cpython-39.pyc
--------------------------------------------------------------------------------
/src/network/mitmproxy_packet_capture.py:
--------------------------------------------------------------------------------
1 | # path:/src/network/mitmproxy_packet_capture.py
2 |
3 |
4 | import logging
5 | from mitmproxy import http
6 | from shard import * # 假设你已经正确配置了共享数据结构,如 packet_queue
7 |
8 | logging.basicConfig(level=logging.INFO)
9 |
10 |
11 | class MyAddon():
12 | def __init__(self):
13 | self.active_flows = {}
14 |
15 | def request(self, flow: http.HTTPFlow) -> None:
16 | try:
17 | # 在MyAddon的request方法首行添加
18 | print(f"🔥 Intercepted: {flow.request.url}")
19 |
20 | # 构建类似Burp的请求格式
21 | raw_request = (
22 | f"{flow.request.method} {flow.request.url} {flow.request.http_version}\n"
23 | f"{self.format_headers(flow.request.headers)}\n\n" # 格式化请求头
24 | f"{flow.request.text}" # 请求体(如果有的话)
25 | )
26 |
27 | # 只传递必要元数据,不要传递flow对象
28 | packet_queue.put({
29 | "flow_id": id(flow),
30 | "raw": raw_request,
31 | "meta": { # 添加可序列化元数据
32 | "host": flow.request.host,
33 | "port": flow.request.port,
34 | "scheme": flow.request.scheme
35 | }
36 | })
37 | # 输出队列信息
38 | logging.info(f"flow_start\n{packet_queue.get()}\nflow_end") # 格式化输出抓到的请求
39 |
40 | except Exception as e:
41 | logging.error(f"Error capturing request: {str(e)}")
42 |
43 | def format_headers(self, headers):
44 | """格式化请求头为类似Burp的格式"""
45 | formatted_headers = ""
46 | for header, value in headers.items():
47 | formatted_headers += f"{header}: {value}\n"
48 | return formatted_headers
49 |
50 |
51 | # 注册插件
52 | addons = [MyAddon()]
53 |
--------------------------------------------------------------------------------
/src/network/shard.py:
--------------------------------------------------------------------------------
1 | # path:/src/network/shared.py
2 | from multiprocessing import Queue
3 |
4 |
5 | packet_queue = Queue()
6 |
--------------------------------------------------------------------------------
/src/otherTools/QueryStringParser.py:
--------------------------------------------------------------------------------
1 | # path: src/otherTools/QueryStringParser.py
2 |
3 | import re
4 |
5 |
6 | class QueryStringParser:
7 | def __init__(self, query_string: str):
8 | self.query_string = query_string
9 |
10 | # 将请求参数解析成为字典形式
11 | def parse_request_params(self):
12 | """使用正则表达式解析查询字符串"""
13 | params = {}
14 | # 使用正则解析查询参数(包括空值的参数)
15 | pattern = re.compile(r'([^&=]+)=?([^&]*)')
16 | for match in pattern.finditer(self.query_string):
17 | key = match.group(1)
18 | value = match.group(2) or '' # 如果没有值,设置为空字符串
19 | if key in params:
20 | params[key].append(value)
21 | else:
22 | params[key] = [value]
23 | return params
24 |
--------------------------------------------------------------------------------
/src/otherTools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/otherTools/__init__.py
--------------------------------------------------------------------------------
/src/otherTools/__pycache__/QueryStringParser.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/otherTools/__pycache__/QueryStringParser.cpython-39.pyc
--------------------------------------------------------------------------------
/src/otherTools/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/otherTools/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/otherTools/__pycache__/rsa_handler.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/otherTools/__pycache__/rsa_handler.cpython-39.pyc
--------------------------------------------------------------------------------
/src/otherTools/__pycache__/script_loader.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/otherTools/__pycache__/script_loader.cpython-39.pyc
--------------------------------------------------------------------------------
/src/otherTools/rsa_handler.py:
--------------------------------------------------------------------------------
1 | import os
2 | import textwrap
3 |
4 |
5 | def handle_rsa_keys(window, mode, key):
6 | """处理RSA密钥并将其保存为本地文件
7 |
8 | 此函数根据用户输入的RSA密钥,将其保存为PEM格式的文件。
9 | 根据模式(加密或解密),选择保存公钥或私钥。
10 |
11 | 参数:
12 | window: 窗口对象,用于访问脚本加载器
13 | mode: 模式,'Encrypt' 或 'Decrypt'
14 | key: RSA密钥内容
15 |
16 | 返回:
17 | tuple: 包含密钥路径和错误信息的元组
18 | """
19 | try:
20 | if not key: # 添加空值检查
21 | return None, "密钥不能为空"
22 |
23 | # 获取正确的目录路径 - 注意这里改为 decryptTools
24 | script_dir = os.path.join(window.script_loader.root_path, "src", "scripts", "decryptTools")
25 | # 根据模式选择保存的文件名
26 | pem_file_path = os.path.join(script_dir, "rsa_public_key.pem" if mode == "Encrypt" else "rsa_private_key.pem")
27 |
28 | # 确保密钥内容是正确的PEM格式
29 | key_content = key.strip()
30 | if mode == "Encrypt":
31 | if "-----BEGIN PUBLIC KEY-----" not in key_content:
32 | key_content = ("-----BEGIN PUBLIC KEY-----\n" +
33 | "\n".join(textwrap.wrap(key_content, 64)) +
34 | "\n-----END PUBLIC KEY-----")
35 | elif mode == "Decrypt":
36 | if "-----BEGIN RSA PRIVATE KEY-----" not in key_content:
37 | key_content = ("-----BEGIN RSA PRIVATE KEY-----\n" +
38 | "\n".join(textwrap.wrap(key_content, 64)) +
39 | "\n-----END RSA PRIVATE KEY-----")
40 |
41 | # 保存PEM格式的密钥到文件
42 | with open(pem_file_path, "w") as f:
43 | f.write(key_content)
44 |
45 | # 使用正斜杠路径,确保兼容性
46 | pem_file_path = pem_file_path.replace('\\', '/')
47 | print(f"密钥已保存到: {pem_file_path}") # 添加调试信息
48 | return pem_file_path, ""
49 |
50 | except Exception as e:
51 | error_msg = f"保存RSA密钥失败: {str(e)}"
52 | print(error_msg) # 打印错误信息
53 | window.packet_detail.append(f"❌ {error_msg}")
54 | return None, error_msg
55 |
--------------------------------------------------------------------------------
/src/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/__init__.py
--------------------------------------------------------------------------------
/src/scripts/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/__pycache__/script_config.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/__pycache__/script_config.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/bothTools/__pycache__/aes_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/bothTools/__pycache__/aes_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/bothTools/__pycache__/base64.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/bothTools/__pycache__/base64.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/bothTools/__pycache__/des_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/bothTools/__pycache__/des_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/bothTools/__pycache__/rsa.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/bothTools/__pycache__/rsa.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/bothTools/aes_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | AES CBC 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s aes_cbc.py --ssl-insecure field=password key=your_key iv=your_iv
6 | 解密: mitmdump -p 8888 -s aes_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password key=your_key iv=your_iv
7 |
8 | 参数说明:
9 | field: 需要处理的字段,多个字段用逗号分隔
10 | key: AES密钥
11 | iv: 初始化向量(CBC模式需要)
12 | """
13 | import base64
14 | import sys
15 | from mitmproxy import http
16 | import logging
17 | from Crypto.Cipher import AES
18 | from Crypto.Util.Padding import pad, unpad
19 | import json
20 | from urllib.parse import parse_qs, urlencode
21 |
22 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
23 |
24 | def get_fields():
25 | """获取需要处理的字段"""
26 | all_args = sys.argv
27 | fields = []
28 | for arg in all_args:
29 | if arg.startswith('field='):
30 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
31 | break
32 | return fields or ['password']
33 |
34 | def get_key_iv():
35 | """获取密钥和IV"""
36 | all_args = sys.argv
37 | key = None
38 | iv = None
39 | for arg in all_args:
40 | if arg.startswith('key='):
41 | key = arg.replace('key=', '').strip().encode('utf-8')
42 | elif arg.startswith('iv='):
43 | iv = arg.replace('iv=', '').strip().encode('utf-8')
44 | return key, iv
45 |
46 | def is_encrypt_mode():
47 | """判断是加密还是解密模式"""
48 | return '--mode' not in ' '.join(sys.argv)
49 |
50 | class AESCBCProcessor:
51 | def __init__(self, fields):
52 | self.fields = fields
53 | self.is_encrypt = is_encrypt_mode()
54 | logging.info(f"初始化 AES CBC {'加密' if self.is_encrypt else '解密'}处理器")
55 |
56 | def process_value(self, value: str) -> str:
57 | """处理单个值"""
58 | key, iv = get_key_iv()
59 | cipher = AES.new(key, AES.MODE_CBC, iv)
60 | if self.is_encrypt:
61 | return base64.b64encode(cipher.encrypt(pad(value.encode('utf-8'), AES.block_size))).decode('utf-8')
62 | else:
63 | return unpad(cipher.decrypt(base64.b64decode(value)), AES.block_size).decode('utf-8')
64 |
65 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
66 | """处理JSON数据"""
67 | modified = False
68 | for field in self.fields:
69 | if field in json_data:
70 | json_data[field] = self.process_value(json_data[field])
71 | modified = True
72 | return json_data, modified
73 |
74 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
75 | """处理表单数据"""
76 | params = parse_qs(form_data, keep_blank_values=True)
77 | modified = False
78 | for field in self.fields:
79 | if field in params:
80 | params[field] = [self.process_value(value) for value in params[field]]
81 | modified = True
82 | return urlencode(params), modified
83 |
84 | def request(self, flow: http.HTTPFlow) -> None:
85 | """处理请求"""
86 | # 处理请求逻辑...
87 | pass
88 |
89 | # 获取配置并注册插件
90 | fields = get_fields()
91 | addons = [AESCBCProcessor(fields)]
--------------------------------------------------------------------------------
/src/scripts/bothTools/aes_ecb.py:
--------------------------------------------------------------------------------
1 | """
2 | AES ECB 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s aes_ecb.py --ssl-insecure field=password key=your_key
6 | 解密: mitmdump -p 8888 -s aes_ecb.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password key=your_key
7 |
8 | 参数说明:
9 | field: 需要处理的字段,多个字段用逗号分隔
10 | key: AES密钥(必须为16、24或32字节)
11 |
12 | 注意事项:
13 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
14 | 2. 支持单个或多个字段处理
15 | 3. 自动检测运行模式(加密/解密)
16 | """
17 |
18 | import sys
19 | import logging
20 | import json
21 | from mitmproxy import http
22 | from Crypto.Cipher import AES
23 | from Crypto.Util.Padding import pad, unpad
24 | import base64
25 | from urllib.parse import parse_qs, urlencode
26 |
27 | # 配置日志记录
28 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
29 |
30 | def get_fields_and_key():
31 | """获取需要处理的字段和密钥"""
32 | all_args = sys.argv
33 | fields = []
34 | key = None
35 |
36 | for arg in all_args:
37 | if arg.startswith('field='):
38 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
39 | elif arg.startswith('key='):
40 | key = arg.split('=', 1)[1].strip()
41 |
42 | if not fields:
43 | fields = ['password'] # 默认字段
44 |
45 | if not key or len(key) not in (16, 24, 32):
46 | logging.error("请提供有效的 AES 密钥(16、24 或 32 字节)")
47 | sys.exit(1)
48 |
49 | logging.info(f"需要处理的字段: {fields}")
50 | return fields, key
51 |
52 | def is_encrypt_mode():
53 | """判断是加密还是解密模式"""
54 | return '--mode' not in ' '.join(sys.argv)
55 |
56 | class AESECBProcessor:
57 | def __init__(self, fields, key):
58 | self.fields = fields
59 | self.is_encrypt = is_encrypt_mode()
60 | self.key = key.encode('utf-8')
61 | mode = "加密" if self.is_encrypt else "解密"
62 | logging.info(f"初始化 AES ECB {mode}处理器")
63 |
64 | def process_value(self, value: str) -> str:
65 | """处理单个值"""
66 | cipher = AES.new(self.key, AES.MODE_ECB)
67 | if self.is_encrypt:
68 | padded_value = pad(value.encode('utf-8'), AES.block_size)
69 | return base64.b64encode(cipher.encrypt(padded_value)).decode('utf-8')
70 | else:
71 | decrypted_value = unpad(cipher.decrypt(base64.b64decode(value)), AES.block_size)
72 | return decrypted_value.decode('utf-8')
73 |
74 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
75 | """处理JSON数据"""
76 | modified = False
77 | for field in self.fields:
78 | if field in json_data:
79 | json_data[field] = self.process_value(json_data[field])
80 | modified = True
81 | return json_data, modified
82 |
83 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
84 | """处理表单数据"""
85 | params = parse_qs(form_data, keep_blank_values=True)
86 | modified = False
87 | for field in self.fields:
88 | if field in params:
89 | params[field] = [self.process_value(value) for value in params[field]]
90 | modified = True
91 | return urlencode(params), modified
92 |
93 | def request(self, flow: http.HTTPFlow) -> None:
94 | """处理请求"""
95 | content_type = flow.request.headers.get("Content-Type", "")
96 | logging.info("=" * 50)
97 | logging.info(f"请求URL: {flow.request.pretty_url}")
98 | logging.info(f"请求方法: {flow.request.method}")
99 | logging.info(f"Content-Type: {content_type}")
100 |
101 | modified = False
102 | if "application/json" in content_type:
103 | json_data = json.loads(flow.request.content)
104 | json_data, modified = self.process_json_data(json_data)
105 | if modified:
106 | flow.request.content = json.dumps(json_data).encode('utf-8')
107 |
108 | elif "application/x-www-form-urlencoded" in content_type:
109 | form_data = flow.request.content.decode('utf-8')
110 | new_content, modified = self.process_form_data(form_data)
111 | if modified:
112 | flow.request.content = new_content.encode('utf-8')
113 |
114 | if modified:
115 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
116 | logging.info(f"处理后的请求数据: {flow.request.content.decode('utf-8')}")
117 |
118 | logging.info("=" * 50)
119 |
120 | # 获取配置并注册插件
121 | fields, key = get_fields_and_key()
122 | addons = [AESECBProcessor(fields, key)]
--------------------------------------------------------------------------------
/src/scripts/bothTools/aes_gcm.py:
--------------------------------------------------------------------------------
1 | """
2 | AES GCM 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s aes_gcm.py --ssl-insecure field=password key=your_key
6 | 解密: mitmdump -p 8888 -s aes_gcm.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password key=your_key
7 |
8 | 参数说明:
9 | field: 需要处理的字段,多个字段用逗号分隔
10 | key: AES密钥(必须为16、24或32字节)
11 |
12 | 注意事项:
13 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
14 | 2. 支持单个或多个字段处理
15 | 3. 自动检测运行模式(加密/解密)
16 | """
17 |
18 | import sys
19 | from mitmproxy import http
20 | import logging
21 | from Crypto.Cipher import AES
22 | from Crypto.Util import Counter
23 | import base64
24 | import json
25 | from urllib.parse import parse_qs, urlencode
26 |
27 | # 配置日志记录
28 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
29 |
30 | def get_fields():
31 | """获取需要处理的字段"""
32 | all_args = sys.argv
33 | fields = []
34 | for arg in all_args:
35 | if arg.startswith('field='):
36 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
37 | break
38 | return fields or ['password']
39 |
40 | def get_key():
41 | """获取密钥"""
42 | all_args = sys.argv
43 | key = None
44 | for arg in all_args:
45 | if arg.startswith('key='):
46 | key = arg.split('=', 1)[1].strip()
47 | if not key or len(key) not in (16, 24, 32):
48 | logging.error("请提供有效的 AES 密钥(16、24 或 32 字节)")
49 | sys.exit(1)
50 | return key.encode('utf-8')
51 |
52 | def is_encrypt_mode():
53 | """判断是加密还是解密模式"""
54 | return '--mode' not in ' '.join(sys.argv)
55 |
56 | class AesGCMProcessor:
57 | def __init__(self, fields, key):
58 | self.fields = fields
59 | self.is_encrypt = is_encrypt_mode()
60 | self.key = key
61 | mode = "加密" if self.is_encrypt else "解密"
62 | logging.info(f"初始化 AES GCM {mode}处理器")
63 |
64 | def process_value(self, value: str) -> str:
65 | """处理单个值"""
66 | cipher = AES.new(self.key, AES.MODE_GCM)
67 | if self.is_encrypt:
68 | nonce = cipher.nonce
69 | ciphertext, tag = cipher.encrypt_and_digest(value.encode('utf-8'))
70 | return base64.b64encode(nonce + tag + ciphertext).decode('utf-8')
71 | else:
72 | data = base64.b64decode(value)
73 | nonce, tag, ciphertext = data[:16], data[16:32], data[32:]
74 | cipher = AES.new(self.key, AES.MODE_GCM, nonce=nonce)
75 | return cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8')
76 |
77 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
78 | """处理JSON数据"""
79 | modified = False
80 | for field in self.fields:
81 | if field in json_data:
82 | json_data[field] = self.process_value(json_data[field])
83 | modified = True
84 | return json_data, modified
85 |
86 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
87 | """处理表单数据"""
88 | params = parse_qs(form_data, keep_blank_values=True)
89 | modified = False
90 | for field in self.fields:
91 | if field in params:
92 | params[field] = [self.process_value(value) for value in params[field]]
93 | modified = True
94 | return urlencode(params), modified
95 |
96 | def request(self, flow: http.HTTPFlow) -> None:
97 | """处理请求"""
98 | content_type = flow.request.headers.get("Content-Type", "")
99 | logging.info("=" * 50)
100 | logging.info(f"请求URL: {flow.request.pretty_url}")
101 | logging.info(f"请求方法: {flow.request.method}")
102 | logging.info(f"Content-Type: {content_type}")
103 |
104 | modified = False
105 | if "application/json" in content_type:
106 | json_data = json.loads(flow.request.content)
107 | json_data, modified = self.process_json_data(json_data)
108 | if modified:
109 | flow.request.content = json.dumps(json_data).encode('utf-8')
110 |
111 | elif "application/x-www-form-urlencoded" in content_type:
112 | form_data = flow.request.content.decode('utf-8')
113 | new_content, modified = self.process_form_data(form_data)
114 | if modified:
115 | flow.request.content = new_content.encode('utf-8')
116 |
117 | if modified:
118 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
119 | logging.info(f"处理后的请求数据: {flow.request.content.decode('utf-8')}")
120 |
121 | logging.info("=" * 50)
122 |
123 | # 获取配置并注册插件
124 | fields = get_fields()
125 | key = get_key()
126 | addons = [AesGCMProcessor(fields, key)]
--------------------------------------------------------------------------------
/src/scripts/bothTools/base64.py:
--------------------------------------------------------------------------------
1 | """
2 | Base64 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s base64.py --ssl-insecure field=password
6 | 解密: mitmdump -p 8888 -s base64.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password
7 |
8 | 参数说明:
9 | field=password: 需要处理的字段,多个字段用逗号分隔
10 |
11 | 注意事项:
12 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
13 | 2. 支持单个或多个字段处理
14 | 3. 自动检测运行模式(加密/解密)
15 | """
16 |
17 | import sys
18 | from mitmproxy import http
19 | import base64
20 | import logging
21 | import json
22 | from urllib.parse import parse_qs, urlencode
23 |
24 | # 配置日志记录
25 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
26 |
27 | def get_fields():
28 | """获取需要处理的字段"""
29 | all_args = sys.argv
30 | fields = []
31 |
32 | for arg in all_args:
33 | if arg.startswith('field='):
34 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
35 | break
36 |
37 | if not fields:
38 | fields = ['password'] # 默认字段
39 |
40 | logging.info(f"需要处理的字段: {fields}")
41 | return fields
42 |
43 | def is_encrypt_mode():
44 | """判断是加密还是解密模式"""
45 | return '--mode' not in ' '.join(sys.argv)
46 |
47 | class Base64Processor:
48 | def __init__(self, fields):
49 | self.fields = fields
50 | self.is_encrypt = is_encrypt_mode()
51 | mode = "加密" if self.is_encrypt else "解密"
52 | logging.info(f"初始化 Base64 {mode}处理器")
53 |
54 | def process_value(self, value: str) -> str:
55 | """处理单个值"""
56 | try:
57 | if self.is_encrypt:
58 | return base64.b64encode(value.encode('utf-8')).decode('utf-8')
59 | else:
60 | return base64.b64decode(value).decode('utf-8')
61 | except Exception as e:
62 | logging.error(f"处理失败: {e}")
63 | return value
64 |
65 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
66 | """处理JSON数据"""
67 | modified = False
68 | for field in self.fields:
69 | if field in json_data:
70 | try:
71 | value = str(json_data[field])
72 | mode = "加密" if self.is_encrypt else "解密"
73 | logging.info(f"JSON字段 {field} 待{mode}值: {value}")
74 | json_data[field] = self.process_value(value)
75 | modified = True
76 | logging.info(f"JSON字段 {field} {mode}完成")
77 | except Exception as e:
78 | logging.error(f"处理字段 {field} 失败: {e}")
79 | return json_data, modified
80 |
81 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
82 | """处理表单数据"""
83 | params = parse_qs(form_data, keep_blank_values=True)
84 | modified = False
85 |
86 | for field in self.fields:
87 | if field in params:
88 | try:
89 | values = params[field]
90 | mode = "加密" if self.is_encrypt else "解密"
91 | if isinstance(values, list):
92 | processed_values = []
93 | for value in values:
94 | logging.info(f"表单字段 {field} 待{mode}值: {value}")
95 | processed_values.append(self.process_value(value))
96 | params[field] = processed_values
97 | else:
98 | logging.info(f"表单字段 {field} 待{mode}值: {values}")
99 | params[field] = self.process_value(values)
100 | modified = True
101 | logging.info(f"表单字段 {field} {mode}完成")
102 | except Exception as e:
103 | logging.error(f"处理字段 {field} 失败: {e}")
104 |
105 | for key in params:
106 | if isinstance(params[key], list) and len(params[key]) == 1:
107 | params[key] = params[key][0]
108 |
109 | return urlencode(params), modified
110 |
111 | def request(self, flow: http.HTTPFlow) -> None:
112 | """处理请求"""
113 | try:
114 | content_type = flow.request.headers.get("Content-Type", "")
115 | mode = "加密" if self.is_encrypt else "解密"
116 | logging.info("=" * 50)
117 | logging.info(f"请求URL: {flow.request.pretty_url}")
118 | logging.info(f"请求方法: {flow.request.method}")
119 | logging.info(f"Content-Type: {content_type}")
120 | logging.info(f"运行模式: {mode}")
121 |
122 | modified = False
123 | if "application/json" in content_type:
124 | json_data = json.loads(flow.request.content)
125 | json_data, modified = self.process_json_data(json_data)
126 | if modified:
127 | new_content = json.dumps(json_data, separators=(',', ':'))
128 | flow.request.content = new_content.encode('utf-8')
129 |
130 | elif "application/x-www-form-urlencoded" in content_type:
131 | form_data = flow.request.content.decode('utf-8')
132 | new_content, modified = self.process_form_data(form_data)
133 | if modified:
134 | flow.request.content = new_content.encode('utf-8')
135 |
136 | if modified:
137 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
138 | logging.info(f"{mode}后的请求数据: {flow.request.content.decode('utf-8')}")
139 |
140 | logging.info("=" * 50)
141 |
142 | except Exception as e:
143 | logging.error(f"处理请求失败: {e}")
144 | import traceback
145 | logging.error(traceback.format_exc())
146 |
147 | # 获取配置并注册插件
148 | fields = get_fields()
149 | addons = [Base64Processor(fields)]
--------------------------------------------------------------------------------
/src/scripts/bothTools/des3_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | 3DES CBC 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s des3_cbc.py --ssl-insecure field=password key=your_key iv=your_iv
6 | 解密: mitmdump -p 8888 -s des3_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password key=your_key iv=your_iv
7 |
8 | 参数说明:
9 | field: 需要处理的字段,多个字段用逗号分隔
10 | key: 3DES密钥(必须为24字节)
11 | iv: 初始化向量(CBC模式需要)
12 |
13 | 注意事项:
14 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
15 | 2. 支持单个或多个字段处理
16 | 3. 自动检测运行模式(加密/解密)
17 | """
18 |
19 | import sys
20 | from mitmproxy import http
21 | import logging
22 | from Crypto.Cipher import DES3
23 | from Crypto.Util.Padding import pad, unpad
24 | import base64
25 | import json
26 | from urllib.parse import parse_qs, urlencode
27 |
28 | # 配置日志记录
29 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
30 |
31 | def get_fields():
32 | """获取需要处理的字段"""
33 | all_args = sys.argv
34 | fields = []
35 | for arg in all_args:
36 | if arg.startswith('field='):
37 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
38 | break
39 | return fields or ['password']
40 |
41 | def get_key_iv():
42 | """获取密钥和IV"""
43 | all_args = sys.argv
44 | key = None
45 | iv = None
46 | for arg in all_args:
47 | if arg.startswith('key='):
48 | key = arg.replace('key=', '').strip().encode('utf-8')
49 | elif arg.startswith('iv='):
50 | iv = arg.replace('iv=', '').strip().encode('utf-8')
51 | return key, iv
52 |
53 | def is_encrypt_mode():
54 | """判断是加密还是解密模式"""
55 | return '--mode' not in ' '.join(sys.argv)
56 |
57 | class DES3CBCProcessor:
58 | def __init__(self, fields):
59 | self.fields = fields
60 | self.is_encrypt = is_encrypt_mode()
61 | logging.info(f"初始化 3DES CBC {'加密' if self.is_encrypt else '解密'}处理器")
62 |
63 | def process_value(self, value: str) -> str:
64 | """处理单个值"""
65 | key, iv = get_key_iv()
66 | cipher = DES3.new(key, DES3.MODE_CBC, iv)
67 | if self.is_encrypt:
68 | return base64.b64encode(cipher.encrypt(pad(value.encode('utf-8'), DES3.block_size))).decode('utf-8')
69 | else:
70 | return unpad(cipher.decrypt(base64.b64decode(value)), DES3.block_size).decode('utf-8')
71 |
72 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
73 | """处理JSON数据"""
74 | modified = False
75 | for field in self.fields:
76 | if field in json_data:
77 | json_data[field] = self.process_value(json_data[field])
78 | modified = True
79 | return json_data, modified
80 |
81 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
82 | """处理表单数据"""
83 | params = parse_qs(form_data, keep_blank_values=True)
84 | modified = False
85 | for field in self.fields:
86 | if field in params:
87 | params[field] = [self.process_value(value) for value in params[field]]
88 | modified = True
89 | return urlencode(params), modified
90 |
91 | def request(self, flow: http.HTTPFlow) -> None:
92 | """处理请求"""
93 | content_type = flow.request.headers.get("Content-Type", "")
94 | logging.info("=" * 50)
95 | logging.info(f"请求URL: {flow.request.pretty_url}")
96 | logging.info(f"请求方法: {flow.request.method}")
97 | logging.info(f"Content-Type: {content_type}")
98 |
99 | modified = False
100 | if "application/json" in content_type:
101 | json_data = json.loads(flow.request.content)
102 | json_data, modified = self.process_json_data(json_data)
103 | if modified:
104 | flow.request.content = json.dumps(json_data).encode('utf-8')
105 |
106 | elif "application/x-www-form-urlencoded" in content_type:
107 | form_data = flow.request.content.decode('utf-8')
108 | new_content, modified = self.process_form_data(form_data)
109 | if modified:
110 | flow.request.content = new_content.encode('utf-8')
111 |
112 | if modified:
113 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
114 | logging.info(f"处理后的请求数据: {flow.request.content.decode('utf-8')}")
115 |
116 | logging.info("=" * 50)
117 |
118 | # 获取配置并注册插件
119 | fields = get_fields()
120 | addons = [DES3CBCProcessor(fields)]
--------------------------------------------------------------------------------
/src/scripts/bothTools/des_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | DES CBC 双向加解密脚本
3 |
4 | 使用方法:
5 | 加密: mitmdump -p 9999 -s des_cbc.py --ssl-insecure field=password key=your_key iv=your_iv
6 | 解密: mitmdump -p 8888 -s des_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password key=your_key iv=your_iv
7 | """
8 | import base64
9 | import sys
10 | from mitmproxy import http
11 | import logging
12 | from Crypto.Cipher import DES
13 | from Crypto.Util.Padding import pad, unpad
14 | import json
15 | from urllib.parse import parse_qs, urlencode
16 |
17 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
18 |
19 | def get_fields():
20 | """获取需要处理的字段"""
21 | all_args = sys.argv
22 | fields = []
23 | for arg in all_args:
24 | if arg.startswith('field='):
25 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
26 | break
27 | return fields or ['password']
28 |
29 | def get_key_iv():
30 | """获取密钥和IV"""
31 | all_args = sys.argv
32 | key = None
33 | iv = None
34 | for arg in all_args:
35 | if arg.startswith('key='):
36 | key = arg.replace('key=', '').strip().encode('utf-8')
37 | elif arg.startswith('iv='):
38 | iv = arg.replace('iv=', '').strip().encode('utf-8')
39 | return key, iv
40 |
41 | def is_encrypt_mode():
42 | """判断是加密还是解密模式"""
43 | return '--mode' not in ' '.join(sys.argv)
44 |
45 | class DESCBCProcessor:
46 | def __init__(self, fields):
47 | self.fields = fields
48 | self.is_encrypt = is_encrypt_mode()
49 | logging.info(f"初始化 DES CBC {'加密' if self.is_encrypt else '解密'}处理器")
50 |
51 | def process_value(self, value: str) -> str:
52 | """处理单个值"""
53 | key, iv = get_key_iv()
54 | cipher = DES.new(key, DES.MODE_CBC, iv)
55 | if self.is_encrypt:
56 | return base64.b64encode(cipher.encrypt(pad(value.encode('utf-8'), DES.block_size))).decode('utf-8')
57 | else:
58 | return unpad(cipher.decrypt(base64.b64decode(value)), DES.block_size).decode('utf-8')
59 |
60 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
61 | """处理JSON数据"""
62 | modified = False
63 | for field in self.fields:
64 | if field in json_data:
65 | json_data[field] = self.process_value(json_data[field])
66 | modified = True
67 | return json_data, modified
68 |
69 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
70 | """处理表单数据"""
71 | params = parse_qs(form_data, keep_blank_values=True)
72 | modified = False
73 | for field in self.fields:
74 | if field in params:
75 | params[field] = [self.process_value(value) for value in params[field]]
76 | modified = True
77 | return urlencode(params), modified
78 |
79 | def request(self, flow: http.HTTPFlow) -> None:
80 | """处理请求"""
81 | # 处理请求逻辑...
82 | pass
83 |
84 | # 获取配置并注册插件
85 | fields = get_fields()
86 | addons = [DESCBCProcessor(fields)]
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__init__.py
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/aes_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/aes_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/aes_ecb.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/aes_ecb.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/aes_gcm.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/aes_gcm.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/base64.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/base64.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/des3_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/des3_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/des_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/des_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/__pycache__/rsa.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/decryptTools/__pycache__/rsa.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/decryptTools/aes_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | AES-CBC 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s aes_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=data key=1234567890123456 iv=1234567890123456
6 |
7 | 参数说明:
8 | -p 8888: 监听端口
9 | -s aes_cbc.py: 指定脚本文件
10 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 需要解密的字段名称,多个字段用逗号分隔
13 | key: AES密钥,必须是16字节(128位)、24字节(192位)或32字节(256位)
14 | iv: 初始化向量,必须是16字节
15 | """
16 |
17 | import sys
18 | from mitmproxy import http
19 | from Crypto.Cipher import AES
20 | from Crypto.Util.Padding import unpad
21 | import base64
22 | import logging
23 | import json
24 | from urllib.parse import parse_qs, urlencode
25 |
26 | # 配置日志记录
27 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
28 |
29 | def get_decryption_fields():
30 | """获取解密配置"""
31 | all_args = sys.argv[1:]
32 | decryption_fields = []
33 | key = None
34 | iv = None
35 |
36 | for arg in all_args:
37 | if not arg.startswith('-'):
38 | if 'key=' in arg:
39 | key = arg.split('=')[1]
40 | elif 'iv=' in arg:
41 | iv = arg.split('=')[1]
42 | elif 'field=' in arg:
43 | fields = arg.split('=', 1)[1].strip().split(',')
44 | decryption_fields.extend([field.strip() for field in fields if field.strip()])
45 |
46 | if not key or not iv:
47 | raise ValueError("必须提供key和iv参数")
48 | if len(key) not in [16, 24, 32]:
49 | raise ValueError("AES密钥必须是16/24/32字节长度")
50 | if len(iv) != 16:
51 | raise ValueError("IV必须是16字节长度")
52 |
53 | logging.info(f"需要解密的字段: {decryption_fields}")
54 | return decryption_fields, key, iv
55 |
56 | class AesCbcDecryptInterceptor:
57 | def __init__(self, decryption_fields, key, iv):
58 | self.decryption_fields = decryption_fields
59 | self.key = key.encode('utf-8')
60 | self.iv = iv.encode('utf-8')
61 |
62 | def decrypt_value(self, encrypted_text: str) -> str:
63 | """解密单个值"""
64 | try:
65 | encrypted_data = base64.b64decode(encrypted_text)
66 | cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
67 | decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size)
68 | return decrypted_data.decode('utf-8')
69 | except Exception as e:
70 | logging.error(f"解密失败: {e}")
71 | return encrypted_text
72 |
73 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
74 | """处理JSON数据"""
75 | modified = False
76 | for field in self.decryption_fields:
77 | if field in json_data:
78 | try:
79 | encrypted_value = json_data[field]
80 | logging.info(f"JSON字段 {field} 待解密值: {encrypted_value}")
81 | decrypted_value = self.decrypt_value(encrypted_value)
82 |
83 | try:
84 | # 尝试将解密后的字符串解析为 JSON 对象
85 | json_data[field] = json.loads(decrypted_value)
86 | except json.JSONDecodeError:
87 | # 如果不是有效的 JSON,则保持为字符串
88 | json_data[field] = decrypted_value
89 |
90 | modified = True
91 | logging.info(f"JSON字段 {field} 解密完成")
92 | except Exception as e:
93 | logging.error(f"解密字段 {field} 失败: {e}")
94 | return json_data, modified
95 |
96 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
97 | """处理表单数据"""
98 | params = parse_qs(form_data, keep_blank_values=True)
99 | modified = False
100 |
101 | for field in self.decryption_fields:
102 | if field in params:
103 | try:
104 | values = params[field]
105 | if isinstance(values, list):
106 | decrypted_values = []
107 | for value in values:
108 | logging.info(f"表单字段 {field} 待解密值: {value}")
109 | decrypted_values.append(self.decrypt_value(value))
110 | params[field] = decrypted_values
111 | else:
112 | logging.info(f"表单字段 {field} 待解密值: {values}")
113 | params[field] = self.decrypt_value(values)
114 | modified = True
115 | logging.info(f"表单字段 {field} 解密完成")
116 | except Exception as e:
117 | logging.error(f"解密字段 {field} 失败: {e}")
118 |
119 | for key in params:
120 | if isinstance(params[key], list) and len(params[key]) == 1:
121 | params[key] = params[key][0]
122 |
123 | return urlencode(params), modified
124 |
125 | def request(self, flow: http.HTTPFlow) -> None:
126 | """处理请求"""
127 | try:
128 | content_type = flow.request.headers.get("Content-Type", "")
129 | logging.info("=" * 50)
130 | logging.info(f"请求URL: {flow.request.pretty_url}")
131 | logging.info(f"请求方法: {flow.request.method}")
132 | logging.info(f"Content-Type: {content_type}")
133 |
134 | modified = False
135 | if "application/json" in content_type:
136 | json_data = json.loads(flow.request.content)
137 | json_data, modified = self.process_json_data(json_data)
138 | if modified:
139 | new_content = json.dumps(json_data, separators=(',', ':'))
140 | flow.request.content = new_content.encode('utf-8')
141 |
142 | elif "application/x-www-form-urlencoded" in content_type:
143 | form_data = flow.request.content.decode('utf-8')
144 | new_content, modified = self.process_form_data(form_data)
145 | if modified:
146 | flow.request.content = new_content.encode('utf-8')
147 |
148 | if modified:
149 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
150 | logging.info(f"解密后的请求数据: {flow.request.content.decode('utf-8')}")
151 |
152 | logging.info("=" * 50)
153 |
154 | except Exception as e:
155 | logging.error(f"处理请求失败: {e}")
156 | import traceback
157 | logging.error(traceback.format_exc())
158 |
159 | # 获取解密配置
160 | decryption_fields, key, iv = get_decryption_fields()
161 |
162 | # 注册插件
163 | addons = [AesCbcDecryptInterceptor(decryption_fields, key, iv)]
--------------------------------------------------------------------------------
/src/scripts/decryptTools/aes_ecb.py:
--------------------------------------------------------------------------------
1 | """
2 | AES-ECB 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 9090 -s aes_ecb.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=data key=1234567890123456
6 |
7 | 参数说明:
8 | -p 9090: 监听端口
9 | -s aes_ecb.py: 指定脚本文件
10 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 需要解密的字段名称,多个字段用逗号分隔
13 | key: AES密钥,必须是16字节(128位)、24字节(192位)或32字节(256位)
14 |
15 | 注意:ECB模式不需要IV,但安全性较低,建议使用CBC或GCM模式
16 | """
17 |
18 | import sys
19 | from mitmproxy import http
20 | from Crypto.Cipher import AES
21 | from Crypto.Util.Padding import unpad
22 | import base64
23 | import logging
24 | import json
25 | from urllib.parse import parse_qs, urlencode
26 |
27 | # 配置日志记录
28 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
29 |
30 | def get_decryption_fields():
31 | """获取解密配置"""
32 | all_args = sys.argv[1:]
33 | decryption_fields = []
34 | key = None
35 |
36 | for arg in all_args:
37 | if not arg.startswith('-'):
38 | if 'key=' in arg:
39 | key = arg.split('=')[1]
40 | elif 'field=' in arg: # 明确检查 field= 前缀
41 | fields = arg.split('=')[1]
42 | decryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
43 |
44 | if not key:
45 | raise ValueError("必须提供key参数")
46 | if len(key) not in [16, 24, 32]:
47 | raise ValueError("AES密钥必须是16/24/32字节长度")
48 |
49 | logging.info(f"需要解密的字段: {decryption_fields}")
50 | return decryption_fields, key
51 |
52 | class AesEcbDecryptInterceptor:
53 | def __init__(self, decryption_fields, key):
54 | self.decryption_fields = decryption_fields
55 | self.key = key.encode('utf-8')
56 |
57 | def decrypt_value(self, encrypted_text: str) -> str:
58 | """解密单个值"""
59 | try:
60 | encrypted_data = base64.b64decode(encrypted_text)
61 | cipher = AES.new(self.key, AES.MODE_ECB)
62 | decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size)
63 | return decrypted_data.decode('utf-8')
64 | except Exception as e:
65 | logging.error(f"解密失败: {e}")
66 | return encrypted_text
67 |
68 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
69 | """处理JSON数据"""
70 | modified = False
71 | for field in self.decryption_fields:
72 | if field in json_data:
73 | try:
74 | encrypted_value = json_data[field]
75 | logging.info(f"JSON字段 {field} 待解密值: {encrypted_value}")
76 | decrypted_value = self.decrypt_value(encrypted_value)
77 |
78 | try:
79 | # 尝试将解密后的字符串解析为 JSON 对象
80 | json_data[field] = json.loads(decrypted_value)
81 | except json.JSONDecodeError:
82 | # 如果不是有效的 JSON,则保持为字符串
83 | json_data[field] = decrypted_value
84 |
85 | modified = True
86 | logging.info(f"JSON字段 {field} 解密完成")
87 | except Exception as e:
88 | logging.error(f"解密字段 {field} 失败: {e}")
89 | return json_data, modified
90 |
91 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
92 | """处理表单数据"""
93 | params = parse_qs(form_data, keep_blank_values=True)
94 | modified = False
95 |
96 | for field in self.decryption_fields:
97 | if field in params:
98 | try:
99 | values = params[field]
100 | if isinstance(values, list):
101 | decrypted_values = []
102 | for value in values:
103 | logging.info(f"表单字段 {field} 待解密值: {value}")
104 | decrypted_values.append(self.decrypt_value(value))
105 | params[field] = decrypted_values
106 | else:
107 | logging.info(f"表单字段 {field} 待解密值: {values}")
108 | params[field] = self.decrypt_value(values)
109 | modified = True
110 | logging.info(f"表单字段 {field} 解密完成")
111 | except Exception as e:
112 | logging.error(f"解密字段 {field} 失败: {e}")
113 |
114 | for key in params:
115 | if isinstance(params[key], list) and len(params[key]) == 1:
116 | params[key] = params[key][0]
117 |
118 | return urlencode(params), modified
119 |
120 | def request(self, flow: http.HTTPFlow) -> None:
121 | """处理请求"""
122 | try:
123 | content_type = flow.request.headers.get("Content-Type", "")
124 | logging.info("=" * 50)
125 | logging.info(f"请求URL: {flow.request.pretty_url}")
126 | logging.info(f"请求方法: {flow.request.method}")
127 | logging.info(f"Content-Type: {content_type}")
128 |
129 | # 显示原始请求数据包
130 | logging.info(f"原始请求数据包: {flow.request.content.decode('utf-8')}")
131 |
132 | modified = False
133 | if "application/json" in content_type:
134 | json_data = json.loads(flow.request.content)
135 | json_data, modified = self.process_json_data(json_data)
136 | if modified:
137 | flow.request.content = json.dumps(json_data).encode('utf-8')
138 |
139 | elif "application/x-www-form-urlencoded" in content_type:
140 | form_data = flow.request.content.decode('utf-8')
141 | new_content, modified = self.process_form_data(form_data)
142 | if modified:
143 | flow.request.content = new_content.encode('utf-8')
144 |
145 | if modified:
146 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
147 | logging.info("\n解密后的请求数据包:")
148 | logging.info(f"{flow.request.content.decode('utf-8')}")
149 |
150 | logging.info("=" * 50)
151 |
152 | except Exception as e:
153 | logging.error(f"处理请求失败: {e}")
154 | import traceback
155 | logging.error(traceback.format_exc())
156 |
157 | # 获取解密配置
158 | decryption_fields, key = get_decryption_fields()
159 |
160 | # 注册插件
161 | addons = [AesEcbDecryptInterceptor(decryption_fields, key)]
--------------------------------------------------------------------------------
/src/scripts/decryptTools/aes_gcm.py:
--------------------------------------------------------------------------------
1 | """
2 | AES-GCM 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s aes_gcm.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=data key=32byteslongsecretkeyforaes256!aa iv=16byteslongiv456
6 |
7 | 参数说明:
8 | -p 8888: 监听端口
9 | -s aes_gcm.py: 指定脚本文件
10 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 需要解密的字段名称,多个字段用逗号分隔
13 | key: AES密钥,必须是16字节(128位)、24字节(192位)或32字节(256位)
14 | iv: GCM模式的初始化向量,必须是16字节长度(与客户端保持一致)
15 | """
16 |
17 | import sys
18 | import os
19 | from mitmproxy import http
20 | from Crypto.Cipher import AES
21 | import base64
22 | import logging
23 | import json
24 | from urllib.parse import parse_qs, urlencode
25 |
26 | # 配置日志记录
27 | logging.basicConfig(
28 | level=logging.INFO,
29 | format='%(asctime)s - %(levelname)s - %(message)s'
30 | )
31 |
32 | def get_decryption_fields():
33 | """获取解密配置"""
34 | all_args = sys.argv[1:]
35 | decryption_fields = []
36 | key = None
37 | iv = None
38 |
39 | for arg in all_args:
40 | if not arg.startswith('-'):
41 | if 'key=' in arg:
42 | key = arg.split('=')[1]
43 | elif 'iv=' in arg:
44 | iv = arg.split('=')[1]
45 | elif 'field=' in arg: # 明确检查 field= 前缀
46 | fields = arg.split('=')[1]
47 | decryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
48 |
49 | if not key or not iv:
50 | raise ValueError("必须提供key和iv参数")
51 | if len(key) not in [16, 24, 32]:
52 | raise ValueError("AES密钥必须是16/24/32字节长度")
53 | if len(iv) != 16: # 修改为16字节,与客户端保持一致
54 | raise ValueError("IV必须是16字节长度")
55 |
56 | logging.info(f"需要解密的字段: {decryption_fields}")
57 | return decryption_fields, key, iv
58 |
59 | def get_fields():
60 | """获取需要处理的字段"""
61 | all_args = sys.argv
62 | fields = []
63 | for arg in all_args:
64 | if arg.startswith('field='):
65 | fields = [field.strip() for field in arg.replace('field=', '').split(',') if field.strip()]
66 | break
67 | return fields or ['password'] # 默认字段
68 |
69 | # 获取所有参数
70 | try:
71 | decryption_fields, key, iv = get_decryption_fields()
72 | except Exception as e:
73 | logging.error(f"参数错误: {e}")
74 | sys.exit(1)
75 |
76 | class AesGcmDecryptInterceptor:
77 | def __init__(self, decryption_fields, key, iv):
78 | self.decryption_fields = decryption_fields
79 | self.key = key.encode('utf-8')
80 | self.iv = iv.encode('utf-8')
81 | self.tag_length = 16 # GCM认证标签长度(字节)
82 |
83 | def decrypt_value(self, encrypted_text: str) -> str:
84 | """解密单个值"""
85 | try:
86 | # Base64解码
87 | encrypted_data = base64.b64decode(encrypted_text)
88 |
89 | # 分离密文和认证标签(与客户端一致)
90 | ciphertext = encrypted_data[:-self.tag_length]
91 | tag = encrypted_data[-self.tag_length:]
92 |
93 | # 创建解密器
94 | cipher = AES.new(self.key, AES.MODE_GCM, nonce=self.iv)
95 |
96 | # 解密并验证
97 | decrypted_data = cipher.decrypt_and_verify(ciphertext, tag)
98 | return decrypted_data.decode('utf-8')
99 | except Exception as e:
100 | logging.error(f"解密失败: {e}")
101 | logging.error(f"密钥长度: {len(self.key)}")
102 | logging.error(f"IV长度: {len(self.iv)}")
103 | logging.error(f"加密数据长度: {len(encrypted_data)}")
104 | return encrypted_text
105 |
106 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
107 | """处理JSON数据"""
108 | modified = False
109 | for field in self.decryption_fields:
110 | if field in json_data:
111 | try:
112 | encrypted_value = json_data[field]
113 | logging.info(f"JSON字段 {field} 待解密值: {encrypted_value}")
114 | decrypted_value = self.decrypt_value(encrypted_value)
115 |
116 | try:
117 | # 尝试将解密后的字符串解析为 JSON 对象
118 | json_data[field] = json.loads(decrypted_value)
119 | except json.JSONDecodeError:
120 | # 如果不是有效的 JSON,则保持为字符串
121 | json_data[field] = decrypted_value
122 |
123 | modified = True
124 | logging.info(f"JSON字段 {field} 解密完成")
125 | except Exception as e:
126 | logging.error(f"解密字段 {field} 失败: {e}")
127 | return json_data, modified
128 |
129 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
130 | """处理表单数据"""
131 | params = parse_qs(form_data, keep_blank_values=True)
132 | modified = False
133 |
134 | for field in self.decryption_fields:
135 | if field in params:
136 | try:
137 | values = params[field]
138 | if isinstance(values, list):
139 | decrypted_values = []
140 | for value in values:
141 | logging.info(f"表单字段 {field} 待解密值: {value}")
142 | decrypted_values.append(self.decrypt_value(value))
143 | params[field] = decrypted_values
144 | else:
145 | logging.info(f"表单字段 {field} 待解密值: {values}")
146 | params[field] = self.decrypt_value(values)
147 | modified = True
148 | logging.info(f"表单字段 {field} 解密完成")
149 | except Exception as e:
150 | logging.error(f"解密字段 {field} 失败: {e}")
151 |
152 | for key in params:
153 | if isinstance(params[key], list) and len(params[key]) == 1:
154 | params[key] = params[key][0]
155 |
156 | return urlencode(params), modified
157 |
158 | def request(self, flow: http.HTTPFlow) -> None:
159 | """处理请求"""
160 | try:
161 | content_type = flow.request.headers.get("Content-Type", "")
162 | logging.info("=" * 50)
163 | logging.info(f"原始请求数据包:\n{flow.request.method} {flow.request.pretty_url}")
164 | logging.info(f"Content-Type: {content_type}")
165 | logging.info(f"{flow.request.content.decode('utf-8')}")
166 |
167 | modified = False
168 | if "application/json" in content_type:
169 | json_data = json.loads(flow.request.content)
170 | json_data, modified = self.process_json_data(json_data)
171 | if modified:
172 | new_content = json.dumps(json_data, separators=(',', ':'))
173 | flow.request.content = new_content.encode('utf-8')
174 |
175 | elif "application/x-www-form-urlencoded" in content_type:
176 | form_data = flow.request.content.decode('utf-8')
177 | new_content, modified = self.process_form_data(form_data)
178 | if modified:
179 | flow.request.content = new_content.encode('utf-8')
180 |
181 | if modified:
182 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
183 | logging.info("\n解密后的请求数据包:")
184 | logging.info(f"{flow.request.content.decode('utf-8')}")
185 |
186 | logging.info("=" * 50)
187 |
188 | except Exception as e:
189 | logging.error(f"处理请求失败: {e}")
190 | import traceback
191 | logging.error(traceback.format_exc())
192 |
193 | # 注册插件
194 | addons = [AesGcmDecryptInterceptor(decryption_fields, key, iv)]
--------------------------------------------------------------------------------
/src/scripts/decryptTools/base64.py:
--------------------------------------------------------------------------------
1 | """
2 | Base64 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s base64.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password
6 | mitmdump -p 8888 -s base64.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s base64.py: 指定脚本文件
11 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
12 | --ssl-insecure: 忽略 SSL 证书验证
13 | field=password: 单个解密字段
14 | field=password,username: 多个解密字段,用逗号分隔
15 | """
16 |
17 | import sys
18 | from mitmproxy import http
19 | import base64
20 | import logging
21 | import json
22 | from urllib.parse import parse_qs, urlencode
23 |
24 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
25 |
26 | def get_decryption_fields():
27 | """
28 | 从命令行参数获取解密配置
29 |
30 | Returns:
31 | list: 需要解密的字段名称列表
32 | """
33 | all_args = sys.argv
34 | decryption_fields = []
35 |
36 | # 遍历所有参数
37 | for arg in all_args:
38 | if arg.startswith('field='):
39 | # 提取 field= 后面的值
40 | fields = arg.replace('field=', '')
41 | decryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
42 | break
43 |
44 | if not decryption_fields:
45 | decryption_fields = ['password'] # 默认解密字段
46 |
47 | logging.info(f"需要解密的字段: {decryption_fields}")
48 | return decryption_fields
49 |
50 | class Base64DecodeInterceptor:
51 | def __init__(self, decryption_fields):
52 | self.decryption_fields = decryption_fields
53 | logging.info("成功初始化Base64解密器")
54 |
55 | def decode_value(self, encoded_text: str) -> str:
56 | """Base64解码"""
57 | try:
58 | decoded_bytes = base64.b64decode(encoded_text)
59 | return decoded_bytes.decode('utf-8')
60 | except Exception as e:
61 | logging.error(f"解码失败: {e}")
62 | return encoded_text
63 |
64 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
65 | """处理JSON数据"""
66 | modified = False
67 | for field in self.decryption_fields:
68 | if field in json_data:
69 | try:
70 | encoded_value = json_data[field]
71 | logging.info(f"JSON字段 {field} 待解码值: {encoded_value}")
72 | decoded_value = self.decode_value(encoded_value)
73 |
74 | try:
75 | json_data[field] = json.loads(decoded_value)
76 | except json.JSONDecodeError:
77 | json_data[field] = decoded_value
78 |
79 | modified = True
80 | logging.info(f"JSON字段 {field} 解码完成")
81 | except Exception as e:
82 | logging.error(f"解码字段 {field} 失败: {e}")
83 | return json_data, modified
84 |
85 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
86 | """处理表单数据"""
87 | params = parse_qs(form_data, keep_blank_values=True)
88 | modified = False
89 |
90 | for field in self.decryption_fields:
91 | if field in params:
92 | try:
93 | values = params[field]
94 | if isinstance(values, list):
95 | decoded_values = []
96 | for value in values:
97 | logging.info(f"表单字段 {field} 待解码值: {value}")
98 | decoded_values.append(self.decode_value(value))
99 | params[field] = decoded_values
100 | else:
101 | logging.info(f"表单字段 {field} 待解码值: {values}")
102 | params[field] = self.decode_value(values)
103 | modified = True
104 | logging.info(f"表单字段 {field} 解码完成")
105 | except Exception as e:
106 | logging.error(f"解码字段 {field} 失败: {e}")
107 |
108 | for key in params:
109 | if isinstance(params[key], list) and len(params[key]) == 1:
110 | params[key] = params[key][0]
111 |
112 | return urlencode(params), modified
113 |
114 | def request(self, flow: http.HTTPFlow) -> None:
115 | """处理请求"""
116 | try:
117 | content_type = flow.request.headers.get("Content-Type", "")
118 | logging.info("=" * 50)
119 | logging.info(f"原始请求数据包:\n{flow.request.method} {flow.request.pretty_url}")
120 | logging.info(f"Content-Type: {content_type}")
121 | logging.info(f"{flow.request.content.decode('utf-8')}")
122 |
123 | modified = False
124 | if "application/json" in content_type:
125 | json_data = json.loads(flow.request.content)
126 | json_data, modified = self.process_json_data(json_data)
127 | if modified:
128 | new_content = json.dumps(json_data, separators=(',', ':'))
129 | flow.request.content = new_content.encode('utf-8')
130 |
131 | elif "application/x-www-form-urlencoded" in content_type:
132 | form_data = flow.request.content.decode('utf-8')
133 | new_content, modified = self.process_form_data(form_data)
134 | if modified:
135 | flow.request.content = new_content.encode('utf-8')
136 |
137 | if modified:
138 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
139 | logging.info("\n解码后的请求数据包:")
140 | logging.info(f"{flow.request.content.decode('utf-8')}")
141 |
142 | logging.info("=" * 50)
143 |
144 | except Exception as e:
145 | logging.error(f"处理请求失败: {e}")
146 | import traceback
147 | logging.error(traceback.format_exc())
148 |
149 | # 获取解密配置
150 | decryption_fields = get_decryption_fields()
151 |
152 | # 注册插件
153 | addons = [Base64DecodeInterceptor(decryption_fields)]
--------------------------------------------------------------------------------
/src/scripts/decryptTools/des3_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | 3DES-CBC 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s des3_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=data key=12345678 iv=12345678
6 |
7 | 参数说明:
8 | -p 8888: 监听端口
9 | -s des3_cbc.py: 指定脚本文件
10 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 需要解密的字段名称,多个字段用逗号分隔
13 | key: 3DES密钥,必须是24字节长度
14 | iv: 初始化向量,必须是8字节长度
15 |
16 | 注意事项:
17 | 1. 3DES密钥必须是24字节长度,IV必须是8字节长度
18 | 2. 支持 application/json 和 application/x-www-form-urlencoded 格式
19 | 3. 解密前数据需为 Base64 编码
20 | """
21 |
22 | import sys
23 | from mitmproxy import http
24 | from Crypto.Cipher import DES3
25 | from Crypto.Util.Padding import unpad
26 | import base64
27 | import logging
28 | import json
29 | from urllib.parse import parse_qs, urlencode
30 |
31 | # 配置日志记录
32 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
33 |
34 |
35 | def get_decryption_fields():
36 | """获取解密配置"""
37 | all_args = sys.argv[1:]
38 | decryption_fields = []
39 | key = None
40 | iv = None
41 |
42 | for arg in all_args:
43 | if not arg.startswith('-'):
44 | if 'key=' in arg:
45 | key = arg.split('=')[1]
46 | elif 'iv=' in arg:
47 | iv = arg.split('=')[1]
48 | elif 'field=' in arg: # 明确检查 field= 前缀
49 | fields = arg.split('=')[1]
50 | decryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 |
52 | logging.info(f"需要解密的字段: {decryption_fields}")
53 | return decryption_fields, key, iv
54 |
55 |
56 | class Des3DecryptInterceptor:
57 | def __init__(self, decryption_fields, key, iv):
58 | self.decryption_fields = decryption_fields
59 | self.key = key.encode('utf-8')
60 | self.iv = iv.encode('utf-8')
61 |
62 | def decrypt_value(self, encrypted_text: str) -> str:
63 | """解密单个值"""
64 | try:
65 | # 确保数据是 Base64 编码的
66 | encrypted_data = base64.b64decode(encrypted_text)
67 | cipher = DES3.new(self.key, DES3.MODE_CBC, self.iv)
68 | decrypted_data = unpad(cipher.decrypt(encrypted_data), DES3.block_size)
69 | return decrypted_data.decode('utf-8')
70 | except Exception as e:
71 | logging.error(f"解密失败: {e}")
72 | return encrypted_text
73 |
74 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
75 | """处理JSON数据"""
76 | modified = False
77 | for field in self.decryption_fields:
78 | if field in json_data:
79 | try:
80 | encrypted_value = json_data[field]
81 | logging.info(f"JSON字段 {field} 待解密值: {encrypted_value}")
82 | decrypted_value = self.decrypt_value(encrypted_value)
83 |
84 | # 解析解密后的字符串为 JSON 对象
85 | json_data[field] = json.loads(decrypted_value) # 确保将解密后的字符串解析为 JSON 对象
86 | modified = True
87 | logging.info(f"JSON字段 {field} 解密完成")
88 | except Exception as e:
89 | logging.error(f"解密字段 {field} 失败: {e}")
90 | return json_data, modified
91 |
92 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
93 | """处理表单数据"""
94 | params = parse_qs(form_data, keep_blank_values=True)
95 | modified = False
96 |
97 | for field in self.decryption_fields:
98 | if field in params:
99 | try:
100 | values = params[field]
101 | if isinstance(values, list):
102 | decrypted_values = []
103 | for value in values:
104 | logging.info(f"表单字段 {field} 待解密值: {value}")
105 | decrypted_values.append(self.decrypt_value(value))
106 | params[field] = decrypted_values
107 | else:
108 | logging.info(f"表单字段 {field} 待解密值: {values}")
109 | params[field] = self.decrypt_value(values)
110 | modified = True
111 | logging.info(f"表单字段 {field} 解密完成")
112 | except Exception as e:
113 | logging.error(f"解密字段 {field} 失败: {e}")
114 |
115 | for key in params:
116 | if isinstance(params[key], list) and len(params[key]) == 1:
117 | params[key] = params[key][0]
118 |
119 | return urlencode(params), modified
120 |
121 | def request(self, flow: http.HTTPFlow) -> None:
122 | """处理请求"""
123 | try:
124 | content_type = flow.request.headers.get("Content-Type", "")
125 | logging.info("=" * 50)
126 | logging.info(f"请求URL: {flow.request.pretty_url}")
127 | logging.info(f"请求方法: {flow.request.method}")
128 | logging.info(f"Content-Type: {content_type}")
129 |
130 | # 显示原始请求数据包
131 | logging.info(f"原始请求数据包: {flow.request.content.decode('utf-8')}")
132 |
133 | modified = False
134 | if "application/json" in content_type:
135 | json_data = json.loads(flow.request.content)
136 | json_data, modified = self.process_json_data(json_data)
137 | if modified:
138 | flow.request.content = json.dumps(json_data).encode('utf-8')
139 |
140 | elif "application/x-www-form-urlencoded" in content_type:
141 | form_data = flow.request.content.decode('utf-8')
142 | new_content, modified = self.process_form_data(form_data)
143 | if modified:
144 | flow.request.content = new_content.encode('utf-8')
145 |
146 | if modified:
147 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
148 | logging.info("\n解密后的请求数据包:")
149 | logging.info(f"{flow.request.content.decode('utf-8')}")
150 |
151 | logging.info("=" * 50)
152 |
153 | except Exception as e:
154 | logging.error(f"处理请求失败: {e}")
155 | import traceback
156 | logging.error(traceback.format_exc())
157 |
158 |
159 | # 获取解密配置
160 | decryption_fields, key, iv = get_decryption_fields()
161 |
162 | # 注册插件
163 | addons = [Des3DecryptInterceptor(decryption_fields, key, iv)]
164 |
--------------------------------------------------------------------------------
/src/scripts/decryptTools/des_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | DES-CBC 解密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s des_cbc.py --mode upstream:http://127.0.0.1:8080 --ssl-insecure field=data key=12345678 iv=12345678
6 |
7 | 参数说明:
8 | -p 8888: 监听端口
9 | -s des_cbc.py: 指定脚本文件
10 | --mode upstream:http://127.0.0.1:8080: 指定代理服务器
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 需要解密的字段名称,多个字段用逗号分隔
13 | key: DES密钥,必须是8字节长度
14 | iv: 初始化向量,必须是8字节长度
15 |
16 | 注意事项:
17 | 1. DES密钥和IV必须是8字节长度
18 | 2. 支持 application/json 和 application/x-www-form-urlencoded 格式
19 | 3. 解密前数据需为 Base64 编码
20 | """
21 |
22 | import sys
23 | from mitmproxy import http
24 | from Crypto.Cipher import DES
25 | from Crypto.Util.Padding import unpad
26 | import base64
27 | import logging
28 | import json
29 | from urllib.parse import parse_qs, urlencode
30 |
31 | # 配置日志记录
32 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
33 |
34 |
35 | def get_decryption_fields():
36 | """获取解密配置"""
37 | all_args = sys.argv[1:]
38 | decryption_fields = []
39 | key = None
40 | iv = None
41 |
42 | for arg in all_args:
43 | if not arg.startswith('-'):
44 | if 'key=' in arg:
45 | key = arg.split('=')[1]
46 | elif 'iv=' in arg:
47 | iv = arg.split('=')[1]
48 | elif 'field=' in arg: # 修改这里,明确检查 field= 前缀
49 | fields = arg.split('=')[1]
50 | decryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 |
52 | logging.info(f"需要解密的字段: {decryption_fields}")
53 | return decryption_fields, key, iv
54 |
55 |
56 | class DesDecryptInterceptor:
57 | def __init__(self, decryption_fields, key, iv):
58 | self.decryption_fields = decryption_fields
59 | self.key = key.encode('utf-8')
60 | self.iv = iv.encode('utf-8')
61 |
62 | def decrypt_value(self, encrypted_text: str) -> str:
63 | """解密单个值"""
64 | try:
65 | # 确保数据是 Base64 编码的
66 | encrypted_data = base64.b64decode(encrypted_text)
67 | cipher = DES.new(self.key, DES.MODE_CBC, self.iv)
68 | decrypted_data = unpad(cipher.decrypt(encrypted_data), DES.block_size)
69 | return decrypted_data.decode('utf-8')
70 | except Exception as e:
71 | logging.error(f"解密失败: {e}")
72 | return encrypted_text
73 |
74 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
75 | """处理JSON数据"""
76 | modified = False
77 | for field in self.decryption_fields:
78 | if field in json_data:
79 | try:
80 | encrypted_value = json_data[field]
81 | logging.info(f"JSON字段 {field} 待解密值: {encrypted_value}")
82 | decrypted_value = self.decrypt_value(encrypted_value)
83 |
84 | # 解析解密后的字符串为 JSON 对象
85 | json_data[field] = json.loads(decrypted_value) # 确保将解密后的字符串解析为 JSON 对象
86 | modified = True
87 | logging.info(f"JSON字段 {field} 解密完成")
88 | except Exception as e:
89 | logging.error(f"解密字段 {field} 失败: {e}")
90 | return json_data, modified
91 |
92 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
93 | """处理表单数据"""
94 | params = parse_qs(form_data, keep_blank_values=True)
95 | modified = False
96 |
97 | for field in self.decryption_fields:
98 | if field in params:
99 | try:
100 | values = params[field]
101 | if isinstance(values, list):
102 | decrypted_values = []
103 | for value in values:
104 | logging.info(f"表单字段 {field} 待解密值: {value}")
105 | decrypted_values.append(self.decrypt_value(value))
106 | params[field] = decrypted_values
107 | else:
108 | logging.info(f"表单字段 {field} 待解密值: {values}")
109 | params[field] = self.decrypt_value(values)
110 | modified = True
111 | logging.info(f"表单字段 {field} 解密完成")
112 | except Exception as e:
113 | logging.error(f"解密字段 {field} 失败: {e}")
114 |
115 | for key in params:
116 | if isinstance(params[key], list) and len(params[key]) == 1:
117 | params[key] = params[key][0]
118 |
119 | return urlencode(params), modified
120 |
121 | def request(self, flow: http.HTTPFlow) -> None:
122 | """处理请求"""
123 | try:
124 | content_type = flow.request.headers.get("Content-Type", "")
125 | logging.info("=" * 50)
126 | logging.info(f"请求URL: {flow.request.pretty_url}")
127 | logging.info(f"请求方法: {flow.request.method}")
128 | logging.info(f"Content-Type: {content_type}")
129 |
130 | # 显示原始请求数据包
131 | logging.info(f"原始请求数据包: {flow.request.content.decode('utf-8')}")
132 |
133 | modified = False
134 | if "application/json" in content_type:
135 | json_data = json.loads(flow.request.content)
136 | json_data, modified = self.process_json_data(json_data)
137 | if modified:
138 | flow.request.content = json.dumps(json_data).encode('utf-8')
139 |
140 | elif "application/x-www-form-urlencoded" in content_type:
141 | form_data = flow.request.content.decode('utf-8')
142 | new_content, modified = self.process_form_data(form_data)
143 | if modified:
144 | flow.request.content = new_content.encode('utf-8')
145 |
146 | if modified:
147 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
148 | logging.info("\n解密后的请求数据包:")
149 | logging.info(f"{flow.request.content.decode('utf-8')}")
150 |
151 | logging.info("=" * 50)
152 |
153 | except Exception as e:
154 | logging.error(f"处理请求失败: {e}")
155 | import traceback
156 | logging.error(traceback.format_exc())
157 |
158 |
159 | # 获取解密配置
160 | decryption_fields, key, iv = get_decryption_fields()
161 |
162 | # 注册插件
163 | addons = [DesDecryptInterceptor(decryption_fields, key, iv)]
164 |
--------------------------------------------------------------------------------
/src/scripts/decryptTools/private.pem:
--------------------------------------------------------------------------------
1 | MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKt+pi/bvygO+t6iFl5H5QyI1IkLYUbi7x1I0L+GPzyXDt5QtA6K5Sexnh6Kd54U6q5dySOGSHUAmx3zv43PVlAHrV1jc2ZVHlOT7bAf+Q12JUKhGttQuzb1OazXsjKtllT1ZAVBsHEL+DqfnPCnpJP+yIZF8cDBVVur6JxxB92nAgMBAAECgYAghb2lcNKBGcooo2uDiLXe2SoZLT/O7iVzk8YGtEJUzr7imUJ0SZHoo639U7wYjhXtaFrHMmWWTr2cAggvMAVJi5fZYYJLbYdc8O5QCKi6PzV2J2NxYyuABL5yarvy4Ji0twnDjlqBYqrjOsxJbeMv58CHLKqduIZuxppGGOoRQQJBANTV3JEg6xJdPXsF9ztOf03BNkvpibuUSNbTssTdzEtLMQW7zd5y1qTCwUbf+e2UsRIYPn5DwOlTu8SaE97Zz8ECQQDORm7szA0WL1OTYob0U1NSSFDn8Jg7FyX5md6ndL3KNTKBDBfe3hNpauLi01lTMbO3MoriOWsFiN++6dZAdwdnAkEAq6PcwN1/Ncwj7Lae7yEa4SXUF9w6yx+GrlkDbmhAfOginLEcES0jlLPLEtFFySeEtUb//uu9A24XmzF2nN2jAQJABgL7fJ89ymW6s9LtR/WdugotgXT7ms1D6BBZ8ttuJJSEUkp975rdSfc5gY7TTZ9nM3GfppQx0El66994xQwzBQJAct1HPeCVROxyEHNwsiRH9wqR5P4B59Mo1714R7ozsdTpVx8FWmqi+OQIJt+IizYgRyQ09qORAFei9AHeQtxKiw==
--------------------------------------------------------------------------------
/src/scripts/decryptTools/rsa_private_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | 1
3 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/src/scripts/decryptTools/rsa_public_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | 1
3 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__init__.py
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/aes.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/aes.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/aes_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/aes_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/aes_ecb.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/aes_ecb.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/base64.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/base64.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/des3_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/des3_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/des_cbc.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/des_cbc.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/md5.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/md5.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/rsa.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/rsa.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/sha1.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/sha1.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/sha256.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/sha256.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/sha384.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/sha384.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/__pycache__/sha512.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/encryptTools/__pycache__/sha512.cpython-39.pyc
--------------------------------------------------------------------------------
/src/scripts/encryptTools/aes_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | AES-CBC 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s aes_cbc.py --ssl-insecure field=password key=1234567890123456 iv=1234567890123456
6 | mitmdump -p 8888 -s aes_cbc.py --ssl-insecure field=password,username key=1234567890123456 iv=1234567890123456
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s aes_cbc.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 单个加密字段或多个加密字段,用逗号分隔
13 | key: AES密钥,必须是16字节(128位)、24字节(192位)或32字节(256位)
14 | iv: 初始化向量,必须是16字节
15 |
16 | 注意事项:
17 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
18 | 2. 支持单个或多个字段加密
19 | 3. AES密钥必须是16/24/32字节长度
20 | 4. IV必须是16字节长度
21 | 5. 加密结果使用 Base64 编码
22 | """
23 |
24 | import sys
25 | import os
26 | from mitmproxy import http
27 | from Crypto.Cipher import AES
28 | from Crypto.Util.Padding import pad
29 | import base64
30 | import logging
31 | import json
32 | from urllib.parse import parse_qs, urlencode
33 |
34 | # 配置日志记录
35 | logging.basicConfig(
36 | level=logging.INFO,
37 | format='%(asctime)s - %(levelname)s - %(message)s'
38 | )
39 |
40 | def get_encryption_fields():
41 | """从命令行参数获取加密配置"""
42 | all_args = sys.argv
43 | encryption_fields = []
44 | key = None
45 | iv = None
46 |
47 | for arg in all_args:
48 | if not arg.startswith('-'):
49 | if 'key=' in arg:
50 | key = arg.split('=')[1]
51 | elif 'iv=' in arg:
52 | iv = arg.split('=')[1]
53 | elif 'field=' in arg:
54 | fields = arg.split('=', 1)[1].strip().split(',')
55 | encryption_fields.extend([field.strip() for field in fields if field.strip()])
56 | else:
57 | try:
58 | float(arg)
59 | except ValueError:
60 | continue
61 |
62 | if not encryption_fields:
63 | encryption_fields = ['password']
64 |
65 |
66 | logging.info(f"需要加密的字段: {encryption_fields}")
67 | return encryption_fields, key, iv
68 |
69 | # 获取加密配置
70 | encryption_fields, key, iv = get_encryption_fields()
71 |
72 | class AesCbcEncryptInterceptor:
73 | """AES-CBC 加密拦截器"""
74 |
75 | def __init__(self, encryption_fields, key, iv):
76 | self.encryption_fields = encryption_fields
77 | self.key = key.encode('utf-8')
78 | self.iv = iv.encode('utf-8')
79 | logging.info("成功初始化AES-CBC加密器")
80 |
81 | def encrypt_value(self, plain_text: str) -> str:
82 | """加密单个值"""
83 | try:
84 | cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
85 | padded_data = pad(plain_text.encode('utf-8'), AES.block_size)
86 | encrypted_data = cipher.encrypt(padded_data)
87 | return base64.b64encode(encrypted_data).decode('utf-8')
88 | except Exception as e:
89 | logging.error(f"加密失败: {e}")
90 | return plain_text
91 |
92 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
93 | """处理JSON数据"""
94 | modified = False
95 | for field in self.encryption_fields:
96 | if field in json_data:
97 | try:
98 | # 如果是字典,先转换为 JSON 字符串
99 | if isinstance(json_data[field], (dict, list)):
100 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
101 | else:
102 | plain_text = str(json_data[field])
103 |
104 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
105 | json_data[field] = self.encrypt_value(plain_text)
106 | modified = True
107 | logging.info(f"JSON字段 {field} 加密完成")
108 | except Exception as e:
109 | logging.error(f"加密字段 {field} 失败: {e}")
110 | return json_data, modified
111 |
112 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
113 | """处理表单数据"""
114 | params = parse_qs(form_data, keep_blank_values=True)
115 | modified = False
116 |
117 | for field in self.encryption_fields:
118 | if field in params:
119 | try:
120 | values = params[field]
121 | if isinstance(values, list):
122 | encrypted_values = []
123 | for value in values:
124 | logging.info(f"表单字段 {field} 待加密值: {value}")
125 | encrypted_values.append(self.encrypt_value(value))
126 | params[field] = encrypted_values
127 | else:
128 | logging.info(f"表单字段 {field} 待加密值: {values}")
129 | params[field] = self.encrypt_value(values)
130 | modified = True
131 | logging.info(f"表单字段 {field} 加密完成")
132 | except Exception as e:
133 | logging.error(f"加密字段 {field} 失败: {e}")
134 |
135 | for key in params:
136 | if isinstance(params[key], list) and len(params[key]) == 1:
137 | params[key] = params[key][0]
138 |
139 | return urlencode(params), modified
140 |
141 | def request(self, flow: http.HTTPFlow) -> None:
142 | """处理请求"""
143 | try:
144 | content_type = flow.request.headers.get("Content-Type", "")
145 | logging.info("=" * 50)
146 | logging.info(f"请求URL: {flow.request.pretty_url}")
147 | logging.info(f"请求方法: {flow.request.method}")
148 | logging.info(f"Content-Type: {content_type}")
149 |
150 | modified = False
151 | if "application/json" in content_type:
152 | json_data = json.loads(flow.request.content)
153 | json_data, modified = self.process_json_data(json_data)
154 | if modified:
155 | new_content = json.dumps(json_data, separators=(',', ':'))
156 | flow.request.content = new_content.encode('utf-8')
157 |
158 | elif "application/x-www-form-urlencoded" in content_type:
159 | form_data = flow.request.content.decode('utf-8')
160 | new_content, modified = self.process_form_data(form_data)
161 | if modified:
162 | flow.request.content = new_content.encode('utf-8')
163 |
164 | if modified:
165 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
166 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
167 |
168 | logging.info("=" * 50)
169 |
170 | except Exception as e:
171 | logging.error(f"处理请求失败: {e}")
172 | import traceback
173 | logging.error(traceback.format_exc())
174 |
175 | # 注册插件
176 | addons = [AesCbcEncryptInterceptor(encryption_fields, key, iv)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/aes_ecb.py:
--------------------------------------------------------------------------------
1 | """
2 | AES-ECB 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s aes_ecb.py --ssl-insecure field=password key=1234567890123456
6 | mitmdump -p 8888 -s aes_ecb.py --ssl-insecure field=password,username key=1234567890123456
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s aes_ecb.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field=password: 单个加密字段
13 | field=password,username: 多个加密字段,用逗号分隔
14 | key=1234567890123456: AES密钥,必须是16/24/32字节
15 |
16 | 注意事项:
17 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
18 | 2. 支持单个或多个字段加密
19 | 3. AES密钥必须是16/24/32字节长度
20 | 4. 加密结果使用 Base64 编码
21 | """
22 |
23 | import sys
24 | import os
25 | from mitmproxy import http
26 | from Crypto.Cipher import AES
27 | from Crypto.Util.Padding import pad
28 | import base64
29 | import logging
30 | import json
31 | from urllib.parse import parse_qs, urlencode
32 |
33 | # 配置日志记录
34 | logging.basicConfig(
35 | level=logging.INFO,
36 | format='%(asctime)s - %(levelname)s - %(message)s'
37 | )
38 |
39 | def get_encryption_fields():
40 | """
41 | 从命令行参数获取加密配置
42 |
43 | Returns:
44 | tuple: (加密字段列表, 密钥)
45 | """
46 | all_args = sys.argv
47 | encryption_fields = []
48 | key = None
49 |
50 | # 遍历所有参数
51 | for arg in all_args:
52 | if arg.startswith('field='):
53 | fields = arg.replace('field=', '')
54 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
55 | elif arg.startswith('key='):
56 | key = arg.replace('key=', '')
57 |
58 |
59 | logging.info(f"需要加密的字段: {encryption_fields}")
60 | return encryption_fields, key
61 |
62 | # 获取加密配置
63 | encryption_fields, key = get_encryption_fields()
64 |
65 | class AesEcbEncryptInterceptor:
66 | """AES-ECB 加密拦截器"""
67 |
68 | def __init__(self, encryption_fields, key):
69 | """
70 | 初始化加密器
71 |
72 | Args:
73 | encryption_fields (list): 需要加密的字段名称列表
74 | key (str): AES密钥,16/24/32字节
75 | """
76 | self.encryption_fields = encryption_fields
77 | self.key = key.encode('utf-8')
78 | logging.info("成功初始化AES-ECB加密器")
79 |
80 | def encrypt_value(self, plain_text: str) -> str:
81 | """
82 | 加密单个值
83 |
84 | Args:
85 | plain_text (str): 待加密的文本
86 |
87 | Returns:
88 | str: Base64编码的加密结果
89 | """
90 | try:
91 | cipher = AES.new(self.key, AES.MODE_ECB)
92 | padded_data = pad(plain_text.encode('utf-8'), AES.block_size)
93 | encrypted_data = cipher.encrypt(padded_data)
94 | return base64.b64encode(encrypted_data).decode('utf-8')
95 | except Exception as e:
96 | logging.error(f"加密失败: {e}")
97 | return plain_text
98 |
99 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
100 | """处理JSON数据"""
101 | modified = False
102 | for field in self.encryption_fields:
103 | if field in json_data:
104 | try:
105 | # 将字段值转换为标准 JSON 字符串(使用双引号)
106 | if isinstance(json_data[field], (dict, list)):
107 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
108 | else:
109 | plain_text = str(json_data[field])
110 |
111 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
112 | json_data[field] = self.encrypt_value(plain_text)
113 | modified = True
114 | logging.info(f"JSON字段 {field} 加密完成")
115 | except Exception as e:
116 | logging.error(f"加密字段 {field} 失败: {e}")
117 | return json_data, modified
118 |
119 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
120 | """处理表单数据"""
121 | params = parse_qs(form_data, keep_blank_values=True)
122 | modified = False
123 |
124 | for field in self.encryption_fields:
125 | if field in params:
126 | try:
127 | values = params[field]
128 | if isinstance(values, list):
129 | encrypted_values = []
130 | for value in values:
131 | logging.info(f"表单字段 {field} 待加密值: {value}")
132 | encrypted_values.append(self.encrypt_value(value))
133 | params[field] = encrypted_values
134 | else:
135 | logging.info(f"表单字段 {field} 待加密值: {values}")
136 | params[field] = self.encrypt_value(values)
137 | modified = True
138 | logging.info(f"表单字段 {field} 加密完成")
139 | except Exception as e:
140 | logging.error(f"加密字段 {field} 失败: {e}")
141 |
142 | for key in params:
143 | if isinstance(params[key], list) and len(params[key]) == 1:
144 | params[key] = params[key][0]
145 |
146 | return urlencode(params), modified
147 |
148 | def request(self, flow: http.HTTPFlow) -> None:
149 | """
150 | 处理请求
151 |
152 | Args:
153 | flow: mitmproxy的请求流对象
154 | """
155 | try:
156 | content_type = flow.request.headers.get("Content-Type", "")
157 | logging.info("=" * 50)
158 | logging.info(f"请求URL: {flow.request.pretty_url}")
159 | logging.info(f"请求方法: {flow.request.method}")
160 | logging.info(f"Content-Type: {content_type}")
161 |
162 | modified = False
163 | if "application/json" in content_type:
164 | json_data = json.loads(flow.request.content)
165 | json_data, modified = self.process_json_data(json_data)
166 | if modified:
167 | new_content = json.dumps(json_data, separators=(',', ':'))
168 | flow.request.content = new_content.encode('utf-8')
169 |
170 | elif "application/x-www-form-urlencoded" in content_type:
171 | form_data = flow.request.content.decode('utf-8')
172 | new_content, modified = self.process_form_data(form_data)
173 | if modified:
174 | flow.request.content = new_content.encode('utf-8')
175 |
176 | if modified:
177 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
178 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
179 |
180 | logging.info("=" * 50)
181 |
182 | except Exception as e:
183 | logging.error(f"处理请求失败: {e}")
184 | import traceback
185 | logging.error(traceback.format_exc())
186 |
187 | # 注册插件
188 | addons = [AesEcbEncryptInterceptor(encryption_fields, key)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/base64.py:
--------------------------------------------------------------------------------
1 | """
2 | Base64 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s base64.py --ssl-insecure field=password
6 | mitmdump -p 8888 -s base64.py --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s base64.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | password: 单个加密字段
13 | password,username: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. 加密结果为标准Base64编码
19 | """
20 |
21 | import sys
22 | from mitmproxy import http
23 | import base64
24 | import logging
25 | import json
26 | from urllib.parse import parse_qs, urlencode
27 |
28 | # 配置日志记录
29 | logging.basicConfig(
30 | level=logging.INFO,
31 | format='%(asctime)s - %(levelname)s - %(message)s'
32 | )
33 |
34 | def get_encryption_fields():
35 | """
36 | 从命令行参数获取加密配置
37 |
38 | Returns:
39 | list: 需要加密的字段名称列表
40 | """
41 | all_args = sys.argv
42 | encryption_fields = []
43 |
44 | # 遍历所有参数
45 | for arg in all_args:
46 | if arg.startswith('field='):
47 | # 提取 field= 后面的值
48 | fields = arg.replace('field=', '')
49 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
50 | break
51 |
52 | logging.info(f"需要加密的字段: {encryption_fields}")
53 | return encryption_fields
54 |
55 | # 获取加密配置
56 | encryption_fields = get_encryption_fields()
57 |
58 | class Base64EncryptInterceptor:
59 | """Base64 加密拦截器"""
60 |
61 | def __init__(self, encryption_fields):
62 | """
63 | 初始化加密器
64 |
65 | Args:
66 | encryption_fields (list): 需要加密的字段名称列表
67 | """
68 | self.encryption_fields = encryption_fields
69 | logging.info("成功初始化Base64加密器")
70 |
71 | def encrypt_value(self, plain_text: str) -> str:
72 | """
73 | 加密单个值
74 |
75 | Args:
76 | plain_text (str): 待加密的文本
77 |
78 | Returns:
79 | str: Base64编码结果
80 | """
81 | try:
82 | return base64.b64encode(plain_text.encode('utf-8')).decode('utf-8')
83 | except Exception as e:
84 | logging.error(f"加密失败: {e}")
85 | return plain_text
86 |
87 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
88 | """处理JSON数据"""
89 | modified = False
90 | for field in self.encryption_fields:
91 | if field in json_data:
92 | try:
93 | plain_text = str(json_data[field])
94 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
95 | json_data[field] = self.encrypt_value(plain_text)
96 | modified = True
97 | logging.info(f"JSON字段 {field} 加密完成")
98 | except Exception as e:
99 | logging.error(f"加密字段 {field} 失败: {e}")
100 | return json_data, modified
101 |
102 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
103 | """处理表单数据"""
104 | params = parse_qs(form_data, keep_blank_values=True)
105 | modified = False
106 |
107 | for field in self.encryption_fields:
108 | if field in params:
109 | try:
110 | values = params[field]
111 | if isinstance(values, list):
112 | encrypted_values = []
113 | for value in values:
114 | logging.info(f"表单字段 {field} 待加密值: {value}")
115 | encrypted_values.append(self.encrypt_value(value))
116 | params[field] = encrypted_values
117 | else:
118 | logging.info(f"表单字段 {field} 待加密值: {values}")
119 | params[field] = self.encrypt_value(values)
120 | modified = True
121 | logging.info(f"表单字段 {field} 加密完成")
122 | except Exception as e:
123 | logging.error(f"加密字段 {field} 失败: {e}")
124 |
125 | for key in params:
126 | if isinstance(params[key], list) and len(params[key]) == 1:
127 | params[key] = params[key][0]
128 |
129 | return urlencode(params), modified
130 |
131 | def request(self, flow: http.HTTPFlow) -> None:
132 | """
133 | 处理请求
134 |
135 | Args:
136 | flow: mitmproxy的请求流对象
137 | """
138 | try:
139 | content_type = flow.request.headers.get("Content-Type", "")
140 | logging.info("=" * 50)
141 | logging.info(f"请求URL: {flow.request.pretty_url}")
142 | logging.info(f"请求方法: {flow.request.method}")
143 | logging.info(f"Content-Type: {content_type}")
144 |
145 | modified = False
146 | if "application/json" in content_type:
147 | json_data = json.loads(flow.request.content)
148 | json_data, modified = self.process_json_data(json_data)
149 | if modified:
150 | new_content = json.dumps(json_data, separators=(',', ':'))
151 | flow.request.content = new_content.encode('utf-8')
152 |
153 | elif "application/x-www-form-urlencoded" in content_type:
154 | form_data = flow.request.content.decode('utf-8')
155 | new_content, modified = self.process_form_data(form_data)
156 | if modified:
157 | flow.request.content = new_content.encode('utf-8')
158 |
159 | if modified:
160 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
161 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
162 |
163 | logging.info("=" * 50)
164 |
165 | except Exception as e:
166 | logging.error(f"处理请求失败: {e}")
167 | import traceback
168 | logging.error(traceback.format_exc())
169 |
170 | # 注册插件
171 | addons = [Base64EncryptInterceptor(encryption_fields)]
172 |
--------------------------------------------------------------------------------
/src/scripts/encryptTools/des3_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | 3DES-CBC 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s des3_cbc.py --ssl-insecure field=data key=123456789012345678901234 iv=12345678
6 |
7 | 参数说明:
8 | -p 8888: 监听端口
9 | -s des3_cbc.py: 指定脚本文件
10 | --ssl-insecure: 忽略 SSL 证书验证
11 | field: 需要加密的字段名称,多个字段用逗号分隔
12 | key: 3DES密钥,必须是16字节(128位)或24字节(192位)
13 | iv: 初始化向量,必须是8字节长度
14 |
15 | 注意事项:
16 | 1. 3DES密钥必须是16字节或24字节长度
17 | 2. 支持 application/json 和 application/x-www-form-urlencoded 格式
18 | 3. 加密结果使用 Base64 编码
19 | """
20 |
21 | import sys
22 | from mitmproxy import http
23 | from Crypto.Cipher import DES3
24 | from Crypto.Util.Padding import pad
25 | import base64
26 | import logging
27 | import json
28 | from urllib.parse import parse_qs, urlencode
29 | import traceback
30 |
31 | # 配置日志记录
32 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
33 |
34 |
35 | def get_encryption_fields():
36 | """从命令行参数获取加密配置"""
37 | all_args = sys.argv
38 | encryption_fields = []
39 | key = None
40 | iv = None
41 |
42 | for arg in all_args:
43 | if not arg.startswith('-'):
44 | if 'key=' in arg:
45 | key = arg.split('=')[1]
46 | elif 'iv=' in arg:
47 | iv = arg.split('=')[1]
48 | elif 'field=' in arg:
49 | fields = arg.split('=', 1)[1].strip().split(',')
50 | encryption_fields.extend([field.strip() for field in fields if field.strip()])
51 | else:
52 | try:
53 | float(arg)
54 | except ValueError:
55 | continue
56 |
57 | if not encryption_fields:
58 | encryption_fields = ['data']
59 |
60 | logging.info(f"需要加密的字段: {encryption_fields}")
61 | return encryption_fields, key, iv
62 |
63 |
64 | # 获取加密配置
65 | encryption_fields, key, iv = get_encryption_fields()
66 |
67 |
68 | class Des3EncryptInterceptor:
69 | """3DES-CBC 加密拦截器"""
70 |
71 | def __init__(self, encryption_fields, key, iv):
72 | self.encryption_fields = encryption_fields
73 | self.key = key.encode('utf-8')
74 | self.iv = iv.encode('utf-8')
75 | logging.info("成功初始化3DES-CBC加密器")
76 |
77 | def encrypt_value(self, plain_text: str) -> str:
78 | """加密单个值"""
79 | try:
80 | # 使用与 CryptoJS.TripleDES 相同的加密方式
81 | cipher = DES3.new(
82 | self.key,
83 | DES3.MODE_CBC,
84 | self.iv,
85 | padmode=None # 使用手动填充
86 | )
87 |
88 | # 手动实现 PKCS7 填充
89 | block_size = DES3.block_size
90 | padding_length = block_size - (len(plain_text.encode()) % block_size)
91 | padded_data = plain_text.encode() + bytes([padding_length] * padding_length)
92 |
93 | # 加密
94 | encrypted_data = cipher.encrypt(padded_data)
95 | return base64.b64encode(encrypted_data).decode('utf-8')
96 | except Exception as e:
97 | logging.error(f"加密失败: {e}")
98 | return plain_text
99 |
100 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
101 | """处理JSON数据"""
102 | modified = False
103 | for field in self.encryption_fields:
104 | if field in json_data:
105 | try:
106 | # 将字段值转换为标准 JSON 字符串(使用双引号)
107 | if isinstance(json_data[field], (dict, list)):
108 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
109 | else:
110 | plain_text = str(json_data[field])
111 |
112 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
113 | json_data[field] = self.encrypt_value(plain_text)
114 | modified = True
115 | logging.info(f"JSON字段 {field} 加密完成")
116 | except Exception as e:
117 | logging.error(f"加密字段 {field} 失败: {e}")
118 | logging.error(traceback.format_exc())
119 | return json_data, modified
120 |
121 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
122 | """处理表单数据"""
123 | params = parse_qs(form_data, keep_blank_values=True)
124 | modified = False
125 |
126 | for field in self.encryption_fields:
127 | if field in params:
128 | try:
129 | values = params[field]
130 | if isinstance(values, list):
131 | encrypted_values = []
132 | for value in values:
133 | logging.info(f"表单字段 {field} 待加密值: {value}")
134 | encrypted_values.append(self.encrypt_value(value))
135 | params[field] = encrypted_values
136 | else:
137 | logging.info(f"表单字段 {field} 待加密值: {values}")
138 | params[field] = self.encrypt_value(values)
139 | modified = True
140 | logging.info(f"表单字段 {field} 加密完成")
141 | except Exception as e:
142 | logging.error(f"加密字段 {field} 失败: {e}")
143 |
144 | for key in params:
145 | if isinstance(params[key], list) and len(params[key]) == 1:
146 | params[key] = params[key][0]
147 |
148 | return urlencode(params), modified
149 |
150 | def request(self, flow: http.HTTPFlow) -> None:
151 | """处理请求"""
152 | try:
153 | content_type = flow.request.headers.get("Content-Type", "")
154 | logging.info("=" * 50)
155 | logging.info(f"请求URL: {flow.request.pretty_url}")
156 | logging.info(f"请求方法: {flow.request.method}")
157 | logging.info(f"Content-Type: {content_type}")
158 |
159 | modified = False
160 | if "application/json" in content_type:
161 | json_data = json.loads(flow.request.content)
162 | json_data, modified = self.process_json_data(json_data)
163 | if modified:
164 | new_content = json.dumps(json_data, separators=(',', ':'))
165 | flow.request.content = new_content.encode('utf-8')
166 |
167 | elif "application/x-www-form-urlencoded" in content_type:
168 | form_data = flow.request.content.decode('utf-8')
169 | new_content, modified = self.process_form_data(form_data)
170 | if modified:
171 | flow.request.content = new_content.encode('utf-8')
172 |
173 | if modified:
174 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
175 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
176 |
177 | logging.info("=" * 50)
178 |
179 | except Exception as e:
180 | logging.error(f"处理请求失败: {e}")
181 | import traceback
182 | logging.error(traceback.format_exc())
183 |
184 |
185 | # 注册插件
186 | addons = [Des3EncryptInterceptor(encryption_fields, key, iv)]
187 |
--------------------------------------------------------------------------------
/src/scripts/encryptTools/des_cbc.py:
--------------------------------------------------------------------------------
1 | """
2 | DES-CBC 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s des_cbc.py --ssl-insecure field=password key=12345678 iv=12345678
6 | mitmdump -p 8888 -s des_cbc.py --ssl-insecure field=password,username key=12345678 iv=12345678
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s des_cbc.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field: 单个加密字段或多个加密字段,用逗号分隔
13 | key: DES密钥,必须是8字节长度
14 | iv: 初始化向量,必须是8字节长度
15 |
16 | 注意事项:
17 | 1. DES密钥和IV必须是8字节长度
18 | 2. 支持 application/json 和 application/x-www-form-urlencoded 格式
19 | 3. 加密结果使用 Base64 编码
20 | """
21 |
22 | import sys
23 | from mitmproxy import http
24 | from Crypto.Cipher import DES
25 | from Crypto.Util.Padding import pad
26 | import base64
27 | import logging
28 | import json
29 | from urllib.parse import parse_qs, urlencode
30 |
31 | # 配置日志记录
32 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
33 |
34 | def get_encryption_fields():
35 | """从命令行参数获取加密配置"""
36 | all_args = sys.argv
37 | encryption_fields = []
38 | key = None
39 | iv = None
40 |
41 | for arg in all_args:
42 | if not arg.startswith('-'):
43 | if 'key=' in arg:
44 | key = arg.split('=')[1]
45 | elif 'iv=' in arg:
46 | iv = arg.split('=')[1]
47 | elif 'field=' in arg:
48 | fields = arg.split('=', 1)[1].strip().split(',')
49 | encryption_fields.extend([field.strip() for field in fields if field.strip()])
50 | else:
51 | try:
52 | float(arg)
53 | except ValueError:
54 | continue
55 |
56 | if not encryption_fields:
57 | encryption_fields = ['data']
58 |
59 | logging.info(f"需要加密的字段: {encryption_fields}")
60 | return encryption_fields, key, iv
61 |
62 | # 获取加密配置
63 | encryption_fields, key, iv = get_encryption_fields()
64 |
65 | class DesEncryptInterceptor:
66 | """DES-CBC 加密拦截器"""
67 |
68 | def __init__(self, encryption_fields, key, iv):
69 | self.encryption_fields = encryption_fields
70 | self.key = key.encode('utf-8')
71 | self.iv = iv.encode('utf-8')
72 | logging.info("成功初始化DES-CBC加密器")
73 |
74 | def encrypt_value(self, plain_text: str) -> str:
75 | """加密单个值"""
76 | try:
77 | cipher = DES.new(self.key, DES.MODE_CBC, self.iv)
78 | padded_data = pad(plain_text.encode('utf-8'), DES.block_size)
79 | encrypted_data = cipher.encrypt(padded_data)
80 | return base64.b64encode(encrypted_data).decode('utf-8')
81 | except Exception as e:
82 | logging.error(f"加密失败: {e}")
83 | return plain_text
84 |
85 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
86 | """处理JSON数据"""
87 | modified = False
88 | for field in self.encryption_fields:
89 | if field in json_data:
90 | try:
91 | # 将字段值转换为标准 JSON 字符串(使用双引号)
92 | if isinstance(json_data[field], (dict, list)):
93 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
94 | else:
95 | plain_text = str(json_data[field])
96 |
97 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
98 | json_data[field] = self.encrypt_value(plain_text)
99 | modified = True
100 | logging.info(f"JSON字段 {field} 加密完成")
101 | except Exception as e:
102 | logging.error(f"加密字段 {field} 失败: {e}")
103 | return json_data, modified
104 |
105 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
106 | """处理表单数据"""
107 | params = parse_qs(form_data, keep_blank_values=True)
108 | modified = False
109 |
110 | for field in self.encryption_fields:
111 | if field in params:
112 | try:
113 | values = params[field]
114 | if isinstance(values, list):
115 | encrypted_values = []
116 | for value in values:
117 | logging.info(f"表单字段 {field} 待加密值: {value}")
118 | encrypted_values.append(self.encrypt_value(value))
119 | params[field] = encrypted_values
120 | else:
121 | logging.info(f"表单字段 {field} 待加密值: {values}")
122 | params[field] = self.encrypt_value(values)
123 | modified = True
124 | logging.info(f"表单字段 {field} 加密完成")
125 | except Exception as e:
126 | logging.error(f"加密字段 {field} 失败: {e}")
127 |
128 | for key in params:
129 | if isinstance(params[key], list) and len(params[key]) == 1:
130 | params[key] = params[key][0]
131 |
132 | return urlencode(params), modified
133 |
134 | def request(self, flow: http.HTTPFlow) -> None:
135 | """处理请求"""
136 | try:
137 | content_type = flow.request.headers.get("Content-Type", "")
138 | logging.info("=" * 50)
139 | logging.info(f"请求URL: {flow.request.pretty_url}")
140 | logging.info(f"请求方法: {flow.request.method}")
141 | logging.info(f"Content-Type: {content_type}")
142 |
143 | modified = False
144 | if "application/json" in content_type:
145 | json_data = json.loads(flow.request.content)
146 | json_data, modified = self.process_json_data(json_data)
147 | if modified:
148 | new_content = json.dumps(json_data, separators=(',', ':'))
149 | flow.request.content = new_content.encode('utf-8')
150 |
151 | elif "application/x-www-form-urlencoded" in content_type:
152 | form_data = flow.request.content.decode('utf-8')
153 | new_content, modified = self.process_form_data(form_data)
154 | if modified:
155 | flow.request.content = new_content.encode('utf-8')
156 |
157 | if modified:
158 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
159 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
160 |
161 | logging.info("=" * 50)
162 |
163 | except Exception as e:
164 | logging.error(f"处理请求失败: {e}")
165 | import traceback
166 | logging.error(traceback.format_exc())
167 |
168 | # 注册插件
169 | addons = [DesEncryptInterceptor(encryption_fields, key, iv)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/md5.py:
--------------------------------------------------------------------------------
1 | """
2 | MD5 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s md5.py --ssl-insecure password
6 | mitmdump -p 8888 -s md5.py --ssl-insecure password,username,token
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s md5.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | password: 单个加密字段
13 | password,username,token: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. MD5加密结果为32位小写字符串
19 | """
20 |
21 | import sys
22 | import os
23 | from mitmproxy import http
24 | import hashlib
25 | import logging
26 | import json
27 | from urllib.parse import parse_qs, urlencode
28 |
29 | # 修改导入路径的设置
30 | current_dir = os.path.dirname(os.path.abspath(__file__))
31 | project_root = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))
32 | sys.path.insert(0, project_root)
33 |
34 |
35 | # 配置日志记录
36 | logging.basicConfig(
37 | level=logging.INFO,
38 | format='%(asctime)s - %(levelname)s - %(message)s'
39 | )
40 |
41 | def get_encryption_fields():
42 | """从命令行参数获取加密配置"""
43 | all_args = sys.argv
44 | encryption_fields = []
45 |
46 | for arg in all_args:
47 | if not arg.startswith('-'):
48 | if 'field=' in arg:
49 | fields = arg.split('=', 1)[1].strip().split(',')
50 | encryption_fields.extend([field.strip() for field in fields if field.strip()])
51 | else:
52 | try:
53 | float(arg)
54 | except ValueError:
55 | continue
56 |
57 | if not encryption_fields:
58 | encryption_fields = ['password'] # 默认加密字段
59 |
60 | logging.info(f"需要加密的字段: {encryption_fields}")
61 | return encryption_fields
62 |
63 | encryption_fields = get_encryption_fields()
64 |
65 | class MD5EncryptInterceptor:
66 | """MD5 加密拦截器"""
67 |
68 | def __init__(self, field_names):
69 | """
70 | 初始化加密器
71 |
72 | Args:
73 | field_names (list): 需要加密的字段名称列表
74 | """
75 | self.field_names = field_names
76 | logging.info(f"加密目标字段: {self.field_names}")
77 |
78 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
79 | """处理JSON数据"""
80 | modified = False
81 | for field in self.field_names:
82 | if field in json_data:
83 | try:
84 | # 将字段值转换为标准 JSON 字符串(使用双引号)
85 | if isinstance(json_data[field], (dict, list)):
86 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
87 | else:
88 | plain_text = str(json_data[field])
89 |
90 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
91 | json_data[field] = self.encrypt_value(plain_text)
92 | modified = True
93 | logging.info(f"JSON字段 {field} 加密完成")
94 | except Exception as e:
95 | logging.error(f"加密字段 {field} 失败: {e}")
96 | return json_data, modified
97 |
98 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
99 | """处理表单数据"""
100 | params = parse_qs(form_data, keep_blank_values=True)
101 | modified = False
102 |
103 | for field in self.field_names:
104 | if field in params:
105 | try:
106 | values = params[field]
107 | if isinstance(values, list):
108 | encrypted_values = []
109 | for value in values:
110 | logging.info(f"表单字段 {field} 待加密值: {value}")
111 | md5_hash = hashlib.md5()
112 | md5_hash.update(value.encode('utf-8'))
113 | encrypted_values.append(md5_hash.hexdigest())
114 | params[field] = encrypted_values
115 | else:
116 | logging.info(f"表单字段 {field} 待加密值: {values}")
117 | md5_hash = hashlib.md5()
118 | md5_hash.update(values.encode('utf-8'))
119 | params[field] = md5_hash.hexdigest()
120 | modified = True
121 | logging.info(f"表单字段 {field} 加密完成")
122 | except Exception as e:
123 | logging.error(f"加密字段 {field} 失败: {e}")
124 |
125 | for key in params:
126 | if isinstance(params[key], list) and len(params[key]) == 1:
127 | params[key] = params[key][0]
128 |
129 | return urlencode(params), modified
130 |
131 | def request(self, flow: http.HTTPFlow) -> None:
132 | """
133 | 处理请求
134 |
135 | Args:
136 | flow: mitmproxy的请求流对象
137 | """
138 | try:
139 | content_type = flow.request.headers.get("Content-Type", "")
140 | logging.info("=" * 50)
141 | logging.info(f"请求URL: {flow.request.pretty_url}")
142 | logging.info(f"请求方法: {flow.request.method}")
143 | logging.info(f"Content-Type: {content_type}")
144 |
145 | modified = False
146 | if "application/json" in content_type:
147 | json_data = json.loads(flow.request.content)
148 | json_data, modified = self.process_json_data(json_data)
149 | if modified:
150 | new_content = json.dumps(json_data, separators=(',', ':'))
151 | flow.request.content = new_content.encode('utf-8')
152 |
153 | elif "application/x-www-form-urlencoded" in content_type:
154 | form_data = flow.request.content.decode('utf-8')
155 | new_content, modified = self.process_form_data(form_data)
156 | if modified:
157 | flow.request.content = new_content.encode('utf-8')
158 |
159 | if modified:
160 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
161 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
162 |
163 | logging.info("=" * 50)
164 |
165 | except Exception as e:
166 | logging.error(f"处理请求失败: {e}")
167 | import traceback
168 | logging.error(traceback.format_exc())
169 |
170 | # 注册插件
171 | addons = [MD5EncryptInterceptor(encryption_fields)]
172 |
--------------------------------------------------------------------------------
/src/scripts/encryptTools/rsa_private_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQC0Llg1bVZhnyslfezwfeOkvnXWq59bDtmQyHvxkP/38Fw8QQXB
3 | fROCgzGc+Te6pOPl6Ye+vQ1rAnisBaP3rMk40i3OpallzVkuwRKydek3V9ufPpZE
4 | EH4eBgInMSDiMsggTWxcI/Lvag6eHjkSc67RTrj96oxj0ipVRqjxW4X6HQIDAQAB
5 | AoGAEE2pOZxdFpQ6aTgNum0Jrhx1uSjqUGj1kr4xSNhf8OVU0zbm+G0C2OpaEOQU
6 | ANVusZ0B5WZh0m700EvqXDzMMCsa9QhKPP4z9Nd09RHdcQtysbSXnWc2VKDYxiqy
7 | bIsnnlHRemCqHzQVqLaoKa0OVGFouunSqKFiVbXZ9bb/aMECQQDhYD97TI5CpHxU
8 | 7tW67uphUD4xoND3v5ENE//9mgjjJsxnNarpYQDcZgPN2DNMSVmBzuItiiTBuLBE
9 | uXDSBoGFAkEAzKn7H7Aa9G6hLfvHBfxVYtOuybqQwxsdXpQ6kH14dH2a+2A2tIw9
10 | M2U4/pNz89nLC0pzWaYwCgNXHsmeBjYtuQJAYxT5U6+Ya1v8/Sny9LfMevPYI+Fb
11 | fU/O6Tz9sfRiK9sGyekiNm/a/Qosafa+tq8YlqTpcrPk7PXRKKWOIAeUMQJAZDqO
12 | eBtHaBNRrfJSqnTD4C0ouTQ7tsDtpibTc3Vu6yWkI50fzVWslyHoQow1yeMME9B3
13 | Ix1HA3BVVweH8yTPSQJBAKY6NQgHEonErU0k7KzYQFncUAwp3k/TztZYVe86WNjk
14 | 3Ans1T2Dexf5w8pu0TStXxrBNI0MjP9OstFUSR8v92o=
15 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/src/scripts/encryptTools/rsa_public_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 |
3 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/src/scripts/encryptTools/sha1.py:
--------------------------------------------------------------------------------
1 | """
2 | SHA1 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s sha1.py --ssl-insecure field=password
6 | mitmdump -p 8888 -s sha1.py --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s sha1.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field=password: 单个加密字段
13 | field=password,username: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. SHA1加密结果为40位小写字符串
19 | """
20 |
21 | import sys
22 | import os
23 | from mitmproxy import http
24 | import hashlib
25 | import logging
26 | import json
27 | from urllib.parse import parse_qs, urlencode
28 |
29 | # 配置日志记录
30 | logging.basicConfig(
31 | level=logging.INFO,
32 | format='%(asctime)s - %(levelname)s - %(message)s'
33 | )
34 |
35 | def get_encryption_fields():
36 | """
37 | 从命令行参数获取加密配置
38 |
39 | Returns:
40 | list: 需要加密的字段名称列表
41 | """
42 | all_args = sys.argv
43 | encryption_fields = []
44 |
45 | # 遍历所有参数
46 | for arg in all_args:
47 | if arg.startswith('field='):
48 | # 提取 field= 后面的值
49 | fields = arg.replace('field=', '')
50 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 | break
52 |
53 | logging.info(f"需要加密的字段: {encryption_fields}")
54 | return encryption_fields
55 |
56 | # 获取加密配置
57 | encryption_fields = get_encryption_fields()
58 |
59 | class SHA1EncryptInterceptor:
60 | """SHA1 加密拦截器"""
61 |
62 | def __init__(self, encryption_fields):
63 | """
64 | 初始化加密器
65 |
66 | Args:
67 | encryption_fields (list): 需要加密的字段名称列表
68 | """
69 | self.encryption_fields = encryption_fields
70 | logging.info("成功初始化SHA1加密器")
71 |
72 | def encrypt_value(self, plain_text: str) -> str:
73 | """
74 | 加密单个值
75 |
76 | Args:
77 | plain_text (str): 待加密的文本
78 |
79 | Returns:
80 | str: SHA1加密结果
81 | """
82 | try:
83 | sha1_hash = hashlib.sha1()
84 | sha1_hash.update(plain_text.encode('utf-8'))
85 | return sha1_hash.hexdigest()
86 | except Exception as e:
87 | logging.error(f"加密失败: {e}")
88 | return plain_text
89 |
90 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
91 | """处理JSON数据"""
92 | modified = False
93 | for field in self.encryption_fields:
94 | if field in json_data:
95 | try:
96 | # 将字段值转换为标准 JSON 字符串(使用双引号)
97 | if isinstance(json_data[field], (dict, list)):
98 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
99 | else:
100 | plain_text = str(json_data[field])
101 |
102 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
103 | json_data[field] = self.encrypt_value(plain_text)
104 | modified = True
105 | logging.info(f"JSON字段 {field} 加密完成")
106 | except Exception as e:
107 | logging.error(f"加密字段 {field} 失败: {e}")
108 | return json_data, modified
109 |
110 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
111 | """处理表单数据"""
112 | params = parse_qs(form_data, keep_blank_values=True)
113 | modified = False
114 |
115 | for field in self.encryption_fields:
116 | if field in params:
117 | try:
118 | values = params[field]
119 | if isinstance(values, list):
120 | encrypted_values = []
121 | for value in values:
122 | logging.info(f"表单字段 {field} 待加密值: {value}")
123 | encrypted_values.append(self.encrypt_value(value))
124 | params[field] = encrypted_values
125 | else:
126 | logging.info(f"表单字段 {field} 待加密值: {values}")
127 | params[field] = self.encrypt_value(values)
128 | modified = True
129 | logging.info(f"表单字段 {field} 加密完成")
130 | except Exception as e:
131 | logging.error(f"加密字段 {field} 失败: {e}")
132 |
133 | for key in params:
134 | if isinstance(params[key], list) and len(params[key]) == 1:
135 | params[key] = params[key][0]
136 |
137 | return urlencode(params), modified
138 |
139 | def request(self, flow: http.HTTPFlow) -> None:
140 | """
141 | 处理请求
142 |
143 | Args:
144 | flow: mitmproxy的请求流对象
145 | """
146 | try:
147 | content_type = flow.request.headers.get("Content-Type", "")
148 | logging.info("=" * 50)
149 | logging.info(f"请求URL: {flow.request.pretty_url}")
150 | logging.info(f"请求方法: {flow.request.method}")
151 | logging.info(f"Content-Type: {content_type}")
152 |
153 | modified = False
154 | if "application/json" in content_type:
155 | json_data = json.loads(flow.request.content)
156 | json_data, modified = self.process_json_data(json_data)
157 | if modified:
158 | new_content = json.dumps(json_data, separators=(',', ':'))
159 | flow.request.content = new_content.encode('utf-8')
160 |
161 | elif "application/x-www-form-urlencoded" in content_type:
162 | form_data = flow.request.content.decode('utf-8')
163 | new_content, modified = self.process_form_data(form_data)
164 | if modified:
165 | flow.request.content = new_content.encode('utf-8')
166 |
167 | if modified:
168 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
169 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
170 |
171 | logging.info("=" * 50)
172 |
173 | except Exception as e:
174 | logging.error(f"处理请求失败: {e}")
175 | import traceback
176 | logging.error(traceback.format_exc())
177 |
178 | # 注册插件
179 | addons = [SHA1EncryptInterceptor(encryption_fields)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/sha256.py:
--------------------------------------------------------------------------------
1 | """
2 | SHA256 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s sha256.py --ssl-insecure field=password
6 | mitmdump -p 8888 -s sha256.py --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s sha256.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field=password: 单个加密字段
13 | field=password,username: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. SHA256加密结果为64位小写字符串
19 | """
20 |
21 | import sys
22 | import os
23 | from mitmproxy import http
24 | import hashlib
25 | import logging
26 | import json
27 | from urllib.parse import parse_qs, urlencode
28 |
29 | # 配置日志记录
30 | logging.basicConfig(
31 | level=logging.INFO,
32 | format='%(asctime)s - %(levelname)s - %(message)s'
33 | )
34 |
35 | def get_encryption_fields():
36 | """
37 | 从命令行参数获取加密配置
38 |
39 | Returns:
40 | list: 需要加密的字段名称列表
41 | """
42 | all_args = sys.argv
43 | encryption_fields = []
44 |
45 | # 遍历所有参数
46 | for arg in all_args:
47 | if arg.startswith('field='):
48 | # 提取 field= 后面的值
49 | fields = arg.replace('field=', '')
50 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 | break
52 |
53 | logging.info(f"需要加密的字段: {encryption_fields}")
54 | return encryption_fields
55 |
56 | # 获取加密配置
57 | encryption_fields = get_encryption_fields()
58 |
59 | class SHA256EncryptInterceptor:
60 | """SHA256 加密拦截器"""
61 |
62 | def __init__(self, encryption_fields):
63 | """
64 | 初始化加密器
65 |
66 | Args:
67 | encryption_fields (list): 需要加密的字段名称列表
68 | """
69 | self.encryption_fields = encryption_fields
70 | logging.info("成功初始化SHA256加密器")
71 |
72 | def encrypt_value(self, plain_text: str) -> str:
73 | """
74 | 加密单个值
75 |
76 | Args:
77 | plain_text (str): 待加密的文本
78 |
79 | Returns:
80 | str: SHA256加密结果
81 | """
82 | try:
83 | sha256_hash = hashlib.sha256()
84 | sha256_hash.update(plain_text.encode('utf-8'))
85 | return sha256_hash.hexdigest()
86 | except Exception as e:
87 | logging.error(f"加密失败: {e}")
88 | return plain_text
89 |
90 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
91 | """处理JSON数据"""
92 | modified = False
93 | for field in self.encryption_fields:
94 | if field in json_data:
95 | try:
96 | # 将字段值转换为标准 JSON 字符串(使用双引号)
97 | if isinstance(json_data[field], (dict, list)):
98 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
99 | else:
100 | plain_text = str(json_data[field])
101 |
102 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
103 | json_data[field] = self.encrypt_value(plain_text)
104 | modified = True
105 | logging.info(f"JSON字段 {field} 加密完成")
106 | except Exception as e:
107 | logging.error(f"加密字段 {field} 失败: {e}")
108 | return json_data, modified
109 |
110 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
111 | """处理表单数据"""
112 | params = parse_qs(form_data, keep_blank_values=True)
113 | modified = False
114 |
115 | for field in self.encryption_fields:
116 | if field in params:
117 | try:
118 | values = params[field]
119 | if isinstance(values, list):
120 | encrypted_values = []
121 | for value in values:
122 | logging.info(f"表单字段 {field} 待加密值: {value}")
123 | encrypted_values.append(self.encrypt_value(value))
124 | params[field] = encrypted_values
125 | else:
126 | logging.info(f"表单字段 {field} 待加密值: {values}")
127 | params[field] = self.encrypt_value(values)
128 | modified = True
129 | logging.info(f"表单字段 {field} 加密完成")
130 | except Exception as e:
131 | logging.error(f"加密字段 {field} 失败: {e}")
132 |
133 | for key in params:
134 | if isinstance(params[key], list) and len(params[key]) == 1:
135 | params[key] = params[key][0]
136 |
137 | return urlencode(params), modified
138 |
139 | def request(self, flow: http.HTTPFlow) -> None:
140 | """
141 | 处理请求
142 |
143 | Args:
144 | flow: mitmproxy的请求流对象
145 | """
146 | try:
147 | content_type = flow.request.headers.get("Content-Type", "")
148 | logging.info("=" * 50)
149 | logging.info(f"请求URL: {flow.request.pretty_url}")
150 | logging.info(f"请求方法: {flow.request.method}")
151 | logging.info(f"Content-Type: {content_type}")
152 |
153 | modified = False
154 | if "application/json" in content_type:
155 | json_data = json.loads(flow.request.content)
156 | json_data, modified = self.process_json_data(json_data)
157 | if modified:
158 | new_content = json.dumps(json_data, separators=(',', ':'))
159 | flow.request.content = new_content.encode('utf-8')
160 |
161 | elif "application/x-www-form-urlencoded" in content_type:
162 | form_data = flow.request.content.decode('utf-8')
163 | new_content, modified = self.process_form_data(form_data)
164 | if modified:
165 | flow.request.content = new_content.encode('utf-8')
166 |
167 | if modified:
168 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
169 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
170 |
171 | logging.info("=" * 50)
172 |
173 | except Exception as e:
174 | logging.error(f"处理请求失败: {e}")
175 | import traceback
176 | logging.error(traceback.format_exc())
177 |
178 | # 注册插件
179 | addons = [SHA256EncryptInterceptor(encryption_fields)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/sha384.py:
--------------------------------------------------------------------------------
1 | """
2 | SHA384 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s sha384.py --ssl-insecure field=password
6 | mitmdump -p 8888 -s sha384.py --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s sha384.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field=password: 单个加密字段
13 | field=password,username: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. SHA384加密结果为96位小写字符串
19 | """
20 |
21 | import sys
22 | import os
23 | from mitmproxy import http
24 | import hashlib
25 | import logging
26 | import json
27 | from urllib.parse import parse_qs, urlencode
28 |
29 | # 配置日志记录
30 | logging.basicConfig(
31 | level=logging.INFO,
32 | format='%(asctime)s - %(levelname)s - %(message)s'
33 | )
34 |
35 | def get_encryption_fields():
36 | """
37 | 从命令行参数获取加密配置
38 |
39 | Returns:
40 | list: 需要加密的字段名称列表
41 | """
42 | all_args = sys.argv
43 | encryption_fields = []
44 |
45 | # 遍历所有参数
46 | for arg in all_args:
47 | if arg.startswith('field='):
48 | # 提取 field= 后面的值
49 | fields = arg.replace('field=', '')
50 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 | break
52 |
53 | logging.info(f"需要加密的字段: {encryption_fields}")
54 | return encryption_fields
55 |
56 | # 获取加密配置
57 | encryption_fields = get_encryption_fields()
58 |
59 | class SHA384EncryptInterceptor:
60 | """SHA384 加密拦截器"""
61 |
62 | def __init__(self, encryption_fields):
63 | """
64 | 初始化加密器
65 |
66 | Args:
67 | encryption_fields (list): 需要加密的字段名称列表
68 | """
69 | self.encryption_fields = encryption_fields
70 | logging.info("成功初始化SHA384加密器")
71 |
72 | def encrypt_value(self, plain_text: str) -> str:
73 | """
74 | 加密单个值
75 |
76 | Args:
77 | plain_text (str): 待加密的文本
78 |
79 | Returns:
80 | str: SHA384加密结果
81 | """
82 | try:
83 | sha384_hash = hashlib.sha384()
84 | sha384_hash.update(plain_text.encode('utf-8'))
85 | return sha384_hash.hexdigest()
86 | except Exception as e:
87 | logging.error(f"加密失败: {e}")
88 | return plain_text
89 |
90 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
91 | """处理JSON数据"""
92 | modified = False
93 | for field in self.encryption_fields:
94 | if field in json_data:
95 | try:
96 | # 将字段值转换为标准 JSON 字符串(使用双引号)
97 | if isinstance(json_data[field], (dict, list)):
98 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
99 | else:
100 | plain_text = str(json_data[field])
101 |
102 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
103 | json_data[field] = self.encrypt_value(plain_text)
104 | modified = True
105 | logging.info(f"JSON字段 {field} 加密完成")
106 | except Exception as e:
107 | logging.error(f"加密字段 {field} 失败: {e}")
108 | return json_data, modified
109 |
110 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
111 | """处理表单数据"""
112 | params = parse_qs(form_data, keep_blank_values=True)
113 | modified = False
114 |
115 | for field in self.encryption_fields:
116 | if field in params:
117 | try:
118 | values = params[field]
119 | if isinstance(values, list):
120 | encrypted_values = []
121 | for value in values:
122 | logging.info(f"表单字段 {field} 待加密值: {value}")
123 | encrypted_values.append(self.encrypt_value(value))
124 | params[field] = encrypted_values
125 | else:
126 | logging.info(f"表单字段 {field} 待加密值: {values}")
127 | params[field] = self.encrypt_value(values)
128 | modified = True
129 | logging.info(f"表单字段 {field} 加密完成")
130 | except Exception as e:
131 | logging.error(f"加密字段 {field} 失败: {e}")
132 |
133 | for key in params:
134 | if isinstance(params[key], list) and len(params[key]) == 1:
135 | params[key] = params[key][0]
136 |
137 | return urlencode(params), modified
138 |
139 | def request(self, flow: http.HTTPFlow) -> None:
140 | """
141 | 处理请求
142 |
143 | Args:
144 | flow: mitmproxy的请求流对象
145 | """
146 | try:
147 | content_type = flow.request.headers.get("Content-Type", "")
148 | logging.info("=" * 50)
149 | logging.info(f"请求URL: {flow.request.pretty_url}")
150 | logging.info(f"请求方法: {flow.request.method}")
151 | logging.info(f"Content-Type: {content_type}")
152 |
153 | modified = False
154 | if "application/json" in content_type:
155 | json_data = json.loads(flow.request.content)
156 | json_data, modified = self.process_json_data(json_data)
157 | if modified:
158 | new_content = json.dumps(json_data, separators=(',', ':'))
159 | flow.request.content = new_content.encode('utf-8')
160 |
161 | elif "application/x-www-form-urlencoded" in content_type:
162 | form_data = flow.request.content.decode('utf-8')
163 | new_content, modified = self.process_form_data(form_data)
164 | if modified:
165 | flow.request.content = new_content.encode('utf-8')
166 |
167 | if modified:
168 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
169 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
170 |
171 | logging.info("=" * 50)
172 |
173 | except Exception as e:
174 | logging.error(f"处理请求失败: {e}")
175 | import traceback
176 | logging.error(traceback.format_exc())
177 |
178 | # 注册插件
179 | addons = [SHA384EncryptInterceptor(encryption_fields)]
--------------------------------------------------------------------------------
/src/scripts/encryptTools/sha512.py:
--------------------------------------------------------------------------------
1 | """
2 | SHA512 加密脚本
3 |
4 | 使用方法:
5 | mitmdump -p 8888 -s sha512.py --ssl-insecure field=password
6 | mitmdump -p 8888 -s sha512.py --ssl-insecure field=password,username
7 |
8 | 参数说明:
9 | -p 8888: 监听端口
10 | -s sha512.py: 指定脚本文件
11 | --ssl-insecure: 忽略 SSL 证书验证
12 | field=password: 单个加密字段
13 | field=password,username: 多个加密字段,用逗号分隔
14 |
15 | 注意事项:
16 | 1. 支持 application/json 和 application/x-www-form-urlencoded 格式
17 | 2. 支持单个或多个字段加密
18 | 3. SHA512加密结果为128位小写字符串
19 | """
20 |
21 | import sys
22 | import os
23 | from mitmproxy import http
24 | import hashlib
25 | import logging
26 | import json
27 | from urllib.parse import parse_qs, urlencode
28 |
29 | # 配置日志记录
30 | logging.basicConfig(
31 | level=logging.INFO,
32 | format='%(asctime)s - %(levelname)s - %(message)s'
33 | )
34 |
35 | def get_encryption_fields():
36 | """
37 | 从命令行参数获取加密配置
38 |
39 | Returns:
40 | list: 需要加密的字段名称列表
41 | """
42 | all_args = sys.argv
43 | encryption_fields = []
44 |
45 | # 遍历所有参数
46 | for arg in all_args:
47 | if arg.startswith('field='):
48 | # 提取 field= 后面的值
49 | fields = arg.replace('field=', '')
50 | encryption_fields = [field.strip() for field in fields.split(',') if field.strip()]
51 | break
52 |
53 | logging.info(f"需要加密的字段: {encryption_fields}")
54 | return encryption_fields
55 |
56 | # 获取加密配置
57 | encryption_fields = get_encryption_fields()
58 |
59 | class SHA512EncryptInterceptor:
60 | """SHA512 加密拦截器"""
61 |
62 | def __init__(self, encryption_fields):
63 | """
64 | 初始化加密器
65 |
66 | Args:
67 | encryption_fields (list): 需要加密的字段名称列表
68 | """
69 | self.encryption_fields = encryption_fields
70 | logging.info("成功初始化SHA512加密器")
71 |
72 | def encrypt_value(self, plain_text: str) -> str:
73 | """
74 | 加密单个值
75 |
76 | Args:
77 | plain_text (str): 待加密的文本
78 |
79 | Returns:
80 | str: SHA512加密结果
81 | """
82 | try:
83 | sha512_hash = hashlib.sha512()
84 | sha512_hash.update(plain_text.encode('utf-8'))
85 | return sha512_hash.hexdigest()
86 | except Exception as e:
87 | logging.error(f"加密失败: {e}")
88 | return plain_text
89 |
90 | def process_json_data(self, json_data: dict) -> tuple[dict, bool]:
91 | """处理JSON数据"""
92 | modified = False
93 | for field in self.encryption_fields:
94 | if field in json_data:
95 | try:
96 | # 将字段值转换为标准 JSON 字符串(使用双引号)
97 | if isinstance(json_data[field], (dict, list)):
98 | plain_text = json.dumps(json_data[field], ensure_ascii=False)
99 | else:
100 | plain_text = str(json_data[field])
101 |
102 | logging.info(f"JSON字段 {field} 待加密值: {plain_text}")
103 | json_data[field] = self.encrypt_value(plain_text)
104 | modified = True
105 | logging.info(f"JSON字段 {field} 加密完成")
106 | except Exception as e:
107 | logging.error(f"加密字段 {field} 失败: {e}")
108 | return json_data, modified
109 |
110 | def process_form_data(self, form_data: str) -> tuple[str, bool]:
111 | """处理表单数据"""
112 | params = parse_qs(form_data, keep_blank_values=True)
113 | modified = False
114 |
115 | for field in self.encryption_fields:
116 | if field in params:
117 | try:
118 | values = params[field]
119 | if isinstance(values, list):
120 | encrypted_values = []
121 | for value in values:
122 | logging.info(f"表单字段 {field} 待加密值: {value}")
123 | encrypted_values.append(self.encrypt_value(value))
124 | params[field] = encrypted_values
125 | else:
126 | logging.info(f"表单字段 {field} 待加密值: {values}")
127 | params[field] = self.encrypt_value(values)
128 | modified = True
129 | logging.info(f"表单字段 {field} 加密完成")
130 | except Exception as e:
131 | logging.error(f"加密字段 {field} 失败: {e}")
132 |
133 | for key in params:
134 | if isinstance(params[key], list) and len(params[key]) == 1:
135 | params[key] = params[key][0]
136 |
137 | return urlencode(params), modified
138 |
139 | def request(self, flow: http.HTTPFlow) -> None:
140 | """
141 | 处理请求
142 |
143 | Args:
144 | flow: mitmproxy的请求流对象
145 | """
146 | try:
147 | content_type = flow.request.headers.get("Content-Type", "")
148 | logging.info("=" * 50)
149 | logging.info(f"请求URL: {flow.request.pretty_url}")
150 | logging.info(f"请求方法: {flow.request.method}")
151 | logging.info(f"Content-Type: {content_type}")
152 |
153 | modified = False
154 | if "application/json" in content_type:
155 | json_data = json.loads(flow.request.content)
156 | json_data, modified = self.process_json_data(json_data)
157 | if modified:
158 | new_content = json.dumps(json_data, separators=(',', ':'))
159 | flow.request.content = new_content.encode('utf-8')
160 |
161 | elif "application/x-www-form-urlencoded" in content_type:
162 | form_data = flow.request.content.decode('utf-8')
163 | new_content, modified = self.process_form_data(form_data)
164 | if modified:
165 | flow.request.content = new_content.encode('utf-8')
166 |
167 | if modified:
168 | flow.request.headers["Content-Length"] = str(len(flow.request.content))
169 | logging.info(f"加密后的请求数据: {flow.request.content.decode('utf-8')}")
170 |
171 | logging.info("=" * 50)
172 |
173 | except Exception as e:
174 | logging.error(f"处理请求失败: {e}")
175 | import traceback
176 | logging.error(traceback.format_exc())
177 |
178 | # 注册插件
179 | addons = [SHA512EncryptInterceptor(encryption_fields)]
--------------------------------------------------------------------------------
/src/scripts/hookTools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/scripts/hookTools/__init__.py
--------------------------------------------------------------------------------
/src/scripts/hookTools/test.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 开发中,敬请期待
--------------------------------------------------------------------------------
/src/scripts/test/des3_cbc_test.py:
--------------------------------------------------------------------------------
1 | """
2 | 3DES-CBC 加密/解密测试脚本
3 |
4 | 使用方法:
5 | python des3_cbc_test.py
6 |
7 | 功能:
8 | 1. 使用与前端相同的加密参数
9 | 2. 支持用户输入字符串进行加密测试
10 | 3. 显示加密前后的数据对比
11 | """
12 |
13 | from Crypto.Cipher import DES3
14 | from Crypto.Util.Padding import pad, unpad
15 | import base64
16 | import json
17 |
18 | def encrypt_des3_cbc(plain_text: str, key: str = "24byteslongKeyfordes3!aa", iv: str = "8bytesIv") -> str:
19 | """3DES-CBC 加密函数"""
20 | try:
21 | # 确保密钥长度为24字节(192位)
22 | if len(key) < 24:
23 | key = key + (24 - len(key)) * '\0'
24 | elif len(key) > 24:
25 | key = key[:24]
26 |
27 | # 确保IV长度为8字节
28 | if len(iv) < 8:
29 | iv = iv + (8 - len(iv)) * '\0'
30 | elif len(iv) > 8:
31 | iv = iv[:8]
32 |
33 | cipher = DES3.new(key.encode('utf-8'), DES3.MODE_CBC, iv.encode('utf-8'))
34 | padded_data = pad(plain_text.encode('utf-8'), DES3.block_size)
35 | encrypted_data = cipher.encrypt(padded_data)
36 | return base64.b64encode(encrypted_data).decode('utf-8')
37 | except Exception as e:
38 | print(f"加密错误: {e}")
39 | return None
40 |
41 | def decrypt_des3_cbc(encrypted_text: str, key: str = "24byteslongKeyfordes3!aa", iv: str = "8bytesIv") -> str:
42 | """3DES-CBC 解密函数"""
43 | try:
44 | # 确保密钥长度为24字节
45 | if len(key) < 24:
46 | key = key + (24 - len(key)) * '\0'
47 | elif len(key) > 24:
48 | key = key[:24]
49 |
50 | # 确保IV长度为8字节
51 | if len(iv) < 8:
52 | iv = iv + (8 - len(iv)) * '\0'
53 | elif len(iv) > 8:
54 | iv = iv[:8]
55 |
56 | encrypted_data = base64.b64decode(encrypted_text)
57 | cipher = DES3.new(key.encode('utf-8'), DES3.MODE_CBC, iv.encode('utf-8'))
58 | decrypted_data = cipher.decrypt(encrypted_data)
59 | unpadded_data = unpad(decrypted_data, DES3.block_size)
60 | return unpadded_data.decode('utf-8')
61 | except Exception as e:
62 | print(f"解密错误: {e}")
63 | return None
64 |
65 | def main():
66 | print("3DES-CBC 加密/解密测试工具")
67 | print("=" * 50)
68 | print("使用与前端相同的加密参数:")
69 | print("密钥(key): 24byteslongKeyfordes3!aa")
70 | print("初始向量(iv): 8bytesIv")
71 | print("=" * 50)
72 |
73 | while True:
74 | # 获取用户输入
75 | user_input = input("\n请输入要加密的内容 (输入 'q' 退出): ")
76 | if user_input.lower() == 'q':
77 | break
78 |
79 | # 构造与前端相同的数据结构
80 | data = {"username": user_input}
81 | json_data = json.dumps(data, ensure_ascii=False)
82 |
83 | # 加密
84 | encrypted = encrypt_des3_cbc(json_data)
85 |
86 | if encrypted:
87 | print("\n加密结果:")
88 | print("-" * 50)
89 | print(f"原始数据: {json_data}")
90 | print(f"加密后: {encrypted}")
91 |
92 | # 解密验证
93 | decrypted = decrypt_des3_cbc(encrypted)
94 | print(f"\n解密验证:")
95 | print(f"解密后: {decrypted}")
96 | print("-" * 50)
97 |
98 | # 构造完整的请求数据
99 | request_data = {"data": encrypted}
100 | print(f"\n完整的请求数据:")
101 | print(json.dumps(request_data, indent=2, ensure_ascii=False))
102 |
103 | # 测试前端传来的加密数据
104 | print("\n是否要测试解密前端数据? (y/n)")
105 | test_frontend = input().lower()
106 | if test_frontend == 'y':
107 | frontend_data = input("请输入前端加密的数据: ")
108 | decrypted_frontend = decrypt_des3_cbc(frontend_data)
109 | if decrypted_frontend:
110 | print(f"\n前端数据解密结果:")
111 | print(f"解密后: {decrypted_frontend}")
112 |
113 | if __name__ == "__main__":
114 | main()
--------------------------------------------------------------------------------
/src/scripts/test/des_cbc_test.py:
--------------------------------------------------------------------------------
1 | """
2 | DES-CBC 加密/解密测试脚本
3 |
4 | 使用方法:
5 | python des_cbc_test.py
6 |
7 | 功能:
8 | 1. 使用与前端相同的加密参数
9 | 2. 支持用户输入字符串进行加密测试
10 | 3. 显示加密前后的数据对比
11 | """
12 |
13 | from Crypto.Cipher import DES
14 | from Crypto.Util.Padding import pad, unpad
15 | import base64
16 | import json
17 |
18 |
19 | def encrypt_des_cbc(plain_text: str, key: str = "12345678", iv: str = "12345678") -> str:
20 | """
21 | DES-CBC 加密函数
22 |
23 | Args:
24 | plain_text: 待加密的文本
25 | key: 密钥(8字节)
26 | iv: 初始化向量(8字节)
27 |
28 | Returns:
29 | str: Base64编码的加密结果
30 | """
31 | try:
32 | # 创建 DES-CBC 加密器
33 | cipher = DES.new(key.encode('utf-8'), DES.MODE_CBC, iv.encode('utf-8'))
34 |
35 | # 对数据进行填充和加密
36 | padded_data = pad(plain_text.encode('utf-8'), DES.block_size)
37 | encrypted_data = cipher.encrypt(padded_data)
38 |
39 | # Base64 编码
40 | return base64.b64encode(encrypted_data).decode('utf-8')
41 | except Exception as e:
42 | print(f"加密错误: {e}")
43 | return None
44 |
45 |
46 | def decrypt_des_cbc(encrypted_text: str, key: str = "12345678", iv: str = "12345678") -> str:
47 | """DES-CBC 解密函数"""
48 | try:
49 | encrypted_data = base64.b64decode(encrypted_text)
50 | cipher = DES.new(key.encode('utf-8'), DES.MODE_CBC, iv.encode('utf-8'))
51 | decrypted_data = cipher.decrypt(encrypted_data)
52 | unpadded_data = unpad(decrypted_data, DES.block_size)
53 | return unpadded_data.decode('utf-8')
54 | except Exception as e:
55 | print(f"解密错误: {e}")
56 | return None
57 |
58 |
59 | def main():
60 | print("DES-CBC 加密/解密测试工具")
61 | print("=" * 50)
62 | print("使用与前端相同的加密参数:")
63 | print("密钥(key): 12345678")
64 | print("初始向量(iv): 12345678")
65 | print("=" * 50)
66 |
67 | while True:
68 | # 获取用户输入
69 | user_input = input("\n请输入要加密的内容 (输入 'q' 退出): ")
70 | if user_input.lower() == 'q':
71 | break
72 |
73 | # 构造与前端相同的数据结构
74 | data = {"username": user_input}
75 | json_data = json.dumps(data)
76 |
77 | # 加密
78 | encrypted = encrypt_des_cbc(json_data)
79 |
80 | if encrypted:
81 | print("\n加密结果:")
82 | print("-" * 50)
83 | print(f"原始数据: {json_data}")
84 | print(f"加密后: {encrypted}")
85 |
86 | # 解密验证
87 | decrypted = decrypt_des_cbc(encrypted)
88 | print(f"\n解密验证:")
89 | print(f"解密后: {decrypted}")
90 | print("-" * 50)
91 |
92 | # 构造完整的请求数据
93 | request_data = {"data": encrypted}
94 | print(f"\n完整的请求数据:")
95 | print(json.dumps(request_data, indent=2))
96 |
97 | # 测试前端传来的加密数据
98 | print("\n是否要测试解密前端数据? (y/n)")
99 | test_frontend = input().lower()
100 | if test_frontend == 'y':
101 | frontend_data = input("请输入前端加密的数据: ")
102 | decrypted_frontend = decrypt_des_cbc(frontend_data)
103 | if decrypted_frontend:
104 | print(f"\n前端数据解密结果:")
105 | print(f"解密后: {decrypted_frontend}")
106 |
107 |
108 | if __name__ == "__main__":
109 | main()
110 |
--------------------------------------------------------------------------------
/src/themes/__pycache__/theme.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/themes/__pycache__/theme.cpython-39.pyc
--------------------------------------------------------------------------------
/src/themes/theme.py:
--------------------------------------------------------------------------------
1 | # path: /src/themes/theme.py
2 | import os
3 |
4 |
5 | def get_themes(window):
6 | """ 动态加载 /resources/themes 下的 .qss 文件,并添加到 theme_combo 下拉框中 """
7 |
8 | # 定义资源目录路径
9 |
10 | theme_dir = os.path.join(os.path.dirname(__file__), '..', '..', 'resource', 'themes') # 使用正确的相对路径
11 |
12 | # 获取所有 .qss 文件
13 | qss_files = [f for f in os.listdir(theme_dir) if f.endswith(".qss")]
14 |
15 | # 清空下拉框并添加主题
16 | window.theme_combo.clear()
17 |
18 | # 将文件名添加到 theme_combo 下拉框
19 | for qss_file in qss_files:
20 | theme_name = qss_file.split('.')[0] # 使用文件名(不包括扩展名)作为主题名
21 | window.theme_combo.addItem(theme_name, userData=qss_file) # 使用 userData 储存文件名
22 |
23 | # 连接下拉框的改变事件,选择后更新主题
24 | window.theme_combo.currentTextChanged.connect(lambda: apply_theme(window))
25 |
26 |
27 | # 当用户切换 theme 的时候,则更换 qss 样式
28 | def apply_theme(window):
29 | """ 应用选中的主题 """
30 | selected_theme = window.theme_combo.currentData() # 获取选中的 .qss 文件名
31 | if selected_theme:
32 | # 获取 qss 的路径
33 | theme_file_path = os.path.join(os.path.dirname(__file__), '..', '..', 'resource', 'themes',
34 | selected_theme) # 使用正确的相对路径
35 | try:
36 | # 指定文件编码为 utf-8
37 | with open(theme_file_path, 'r', encoding='utf-8') as f:
38 | qss = f.read() # 读取 qss 文件内容
39 | # print(qss) # 打印 qss 内容调试
40 | window.setStyleSheet(qss) # 应用主题
41 | # print(f"Applied theme: {selected_theme}")
42 | except Exception as e:
43 | pass
44 | # print(f"Error loading theme '{selected_theme}': {e}")
45 | # 你也可以在这里弹出一个提示框,给用户反馈错误信息
46 |
47 |
48 | # 初始化主题为 dark
49 | def init_themes(window):
50 | """ 初始化并加载主题列表 """
51 |
52 | # 默认选择第一个主题,假设已经有至少一个主题
53 | if window.theme_combo.count() > 0:
54 | window.theme_combo.setCurrentIndex(0)
55 | apply_theme(window)
56 |
--------------------------------------------------------------------------------
/src/thread/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/thread/__init__.py
--------------------------------------------------------------------------------
/src/thread/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/thread/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/thread/__pycache__/mitmproxy_thread.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/thread/__pycache__/mitmproxy_thread.cpython-39.pyc
--------------------------------------------------------------------------------
/src/thread/mitmproxy_thread.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import subprocess
4 | import traceback
5 |
6 | from PyQt6.QtCore import QThread, pyqtSignal
7 |
8 |
9 | class MitmProxyThread(QThread):
10 | new_log = pyqtSignal(str) # 用于发送日志消息的信号
11 | new_packet = pyqtSignal(list) # 用于发送数据包字段信息的信号
12 |
13 | def __init__(self, listen_port=None, command=None):
14 | super().__init__()
15 | self.log = '' # 存储日志信息
16 | self.listen_port = listen_port # 监听端口
17 | self.command = command # 自定义命令
18 | self.process = None # 存储子进程
19 | self.running = False # 线程运行状态
20 | self.script_dir = os.path.dirname(os.path.abspath(__file__)) # 获取当前脚本目录
21 | self.script_path = os.path.join(self.script_dir, "..", "network", "mitmproxy_packet_capture.py") # 默认抓包脚本路径
22 |
23 | def parse_http_request(self, raw_request):
24 | """解析HTTP请求,提取需要的信息"""
25 | try:
26 | # 分割请求行和请求头
27 | lines = raw_request.split('\n')
28 | request_line = lines[0].strip()
29 |
30 | # 解析请求行
31 | method, url, _ = request_line.split(' ')
32 |
33 | # 解析请求头
34 | headers = {}
35 | for line in lines[1:]:
36 | line = line.strip()
37 | if ':' in line:
38 | key, value = line.split(':', 1)
39 | headers[key.strip()] = value.strip()
40 |
41 | # 获取当前时间
42 | from datetime import datetime
43 | current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
44 |
45 | # 构造表格行数据
46 | row_data = [
47 | current_time, # 时间
48 | "Request", # 类型
49 | "->", # 方向
50 | method, # 方法
51 | url, # URL
52 | "200", # 状态码(默认200)
53 | headers.get('Content-Length', '') # 内容长度
54 | ]
55 |
56 | # 添加原始请求数据作为第8个元素
57 | row_data.append(raw_request)
58 |
59 | return row_data
60 |
61 | except Exception as e:
62 | print(f"Error parsing request: {e}")
63 | return None
64 |
65 | def run(self):
66 | """线程运行逻辑"""
67 | try:
68 | # 如果传入命令,则使用自定义命令
69 | if self.command:
70 | print(f"Starting process with command: {self.command}")
71 | self.process = subprocess.Popen(
72 | self.command,
73 | stdout=subprocess.PIPE,
74 | stderr=subprocess.PIPE,
75 | text=True,
76 | encoding="utf-8"
77 | )
78 | else:
79 | # 使用默认的抓包脚本
80 | command = ["mitmdump", "-p", str(self.listen_port), "-s", self.script_path, "--ssl-insecure"]
81 | print(f"Starting process with command: {command}")
82 | self.process = subprocess.Popen(
83 | command,
84 | stdout=subprocess.PIPE,
85 | stderr=subprocess.PIPE,
86 | text=True,
87 | encoding="utf-8"
88 | )
89 |
90 | if self.process is None:
91 | self.new_log.emit("❌ 无法启动 mitmdump 进程。")
92 | return
93 |
94 | self.running = True # 设置运行状态为 True
95 | while self.running:
96 | if self.process.poll() is not None:
97 | # 进程已经终止
98 | error = self.process.stderr.read() # 读取错误信息
99 | if error:
100 | self.new_log.emit(f"❌ 进程错误: {error}")
101 | break
102 |
103 | line = self.process.stdout.readline() # 读取标准输出
104 | if line:
105 | if "error while attempting to bind on address" in line:
106 | self.new_log.emit("❌ 端口被占用,请尝试其他端口或关闭占用端口的程序")
107 | self.stop() # 停止线程
108 | break
109 |
110 | self.log += line # 累加日志
111 | self.new_log.emit(line.strip()) # 发送日志消息
112 |
113 | # Default 模式下解析数据包
114 | if not self.command: # 只在 Default 模式下解析数据包
115 | match = re.search(r"flow_start\n(.*?)\nflow_end", self.log, re.DOTALL)
116 | if match:
117 | full_flow_str = match.group(1)
118 | try:
119 | full_flow = eval(full_flow_str) # 解析流数据
120 | raw_request = full_flow.get('raw', '')
121 |
122 | # 解析请求并发送新信号
123 | row_data = self.parse_http_request(raw_request)
124 | if row_data:
125 | print(f"Sending packet data: {row_data}") # 调试输出
126 | self.new_packet.emit(row_data) # 发送数据包信息
127 |
128 | except Exception as e:
129 | print(f"Error processing flow: {e}")
130 |
131 | self.log = '' # 清空日志
132 |
133 | self.msleep(100) # 暂停100毫秒
134 |
135 | except Exception as e:
136 | self.new_log.emit(f"❌ 线程错误: {str(e)}")
137 | traceback.print_exc() # 打印异常堆栈
138 | finally:
139 | self.cleanup() # 清理资源
140 |
141 | def stop(self):
142 | """安全地停止线程和进程"""
143 | self.running = False # 设置运行状态为 False
144 | if self.process:
145 | self.process.terminate() # 尝试正常终止进程
146 | try:
147 | self.process.wait(timeout=3) # 等待进程结束
148 | except subprocess.TimeoutExpired:
149 | self.process.kill() # 强制结束进程
150 | print("Thread stopped.") # 调试信息
151 | self.quit() # 退出线程
152 |
153 | def cleanup(self):
154 | """清理资源"""
155 | try:
156 | if self.process:
157 | # 尝试正常终止进程
158 | self.process.terminate()
159 | try:
160 | self.process.wait(timeout=3)
161 | except subprocess.TimeoutExpired:
162 | # 如果进程没有及时响应,强制结束它
163 | self.process.kill()
164 | self.process.wait()
165 | finally:
166 | self.process = None # 清空进程引用
167 | except Exception as e:
168 | print(f"清理资源时出错: {e}")
169 | finally:
170 | self.quit() # 退出线程
171 |
172 |
--------------------------------------------------------------------------------
/src/ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/ui/__init__.py
--------------------------------------------------------------------------------
/src/ui/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/ui/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/validator/KeyValidator.py:
--------------------------------------------------------------------------------
1 | from constants.encryption_constants import EncryptionConstants
2 | from constants.error_messages import ErrorMessages
3 |
4 |
5 | def validate_key_length(window, script, key):
6 | """验证密钥长度是否符合要求
7 |
8 | Args:
9 | window: 主窗口实例
10 | script: 选择的加密/解密脚本
11 | key: 输入的密钥
12 |
13 | Returns:
14 | bool: 验证是否通过
15 | """
16 | # 检查是否需要密钥
17 | if not key and script not in EncryptionConstants.NO_KEY_ALGORITHMS:
18 | window.packet_detail.append(ErrorMessages.KEY_REQUIRED)
19 | return False
20 | print(key,script)
21 | # 根据选择的脚本进行密钥长度检查
22 | if script in EncryptionConstants.AES_ALGORITHMS:
23 | if len(key) not in EncryptionConstants.AES_KEY_LENGTHS:
24 | window.packet_detail.append(ErrorMessages.AES_KEY_LENGTH_ERROR)
25 | return False
26 | elif script in EncryptionConstants.DES_ALGORITHMS:
27 | if len(key) not in EncryptionConstants.DES_KEY_LENGTH:
28 | print(len(key))
29 | window.packet_detail.append(ErrorMessages.DES_KEY_LENGTH_ERROR)
30 | return False
31 |
32 | return True
33 |
--------------------------------------------------------------------------------
/src/validator/PortValidator.py:
--------------------------------------------------------------------------------
1 | # path: src/validator/PortValidator.py
2 | import os
3 | import re
4 | import sys
5 | from typing import Dict, Union
6 |
7 |
8 | class PortValidator:
9 | """端口配置验证器,支持全场景校验"""
10 |
11 | @staticmethod
12 | def validate(port_str: str) -> Dict[str, Union[bool, str, int]]:
13 | """
14 | 综合验证端口配置
15 |
16 | :return: 包含校验结果的字典 {
17 | "valid": bool, # 是否合法
18 | "value": int, # 转换后的端口号(仅当valid=True时存在)
19 | "warning": str, # 警告信息(如需要root权限)
20 | "error": str # 错误描述(仅当valid=False时存在)
21 | }
22 | """
23 | # 基础清洗
24 | cleaned = port_str.strip()
25 | if not cleaned:
26 | return {"valid": False, "error": "端口不能为空"}
27 |
28 | # 格式校验
29 | if not re.match(r'^\d+$', cleaned):
30 | return {"valid": False, "error": "必须为纯数字"}
31 |
32 | # 数值转换
33 | try:
34 | port = int(cleaned)
35 | except ValueError:
36 | return {"valid": False, "error": "无效数字格式"}
37 |
38 | # 范围校验
39 | if not (0 <= port <= 65535):
40 | return {"valid": False, "error": "端口范围0-65535"}
41 |
42 | # 特殊端口警告
43 | result = {"valid": True, "value": port}
44 | if 1 <= port <= 1023 and not PortValidator._has_root():
45 | result["warning"] = "需管理员权限(Linux/Mac需sudo)"
46 |
47 | return result
48 |
49 | @staticmethod
50 | def _has_root() -> bool:
51 | """检查是否具有管理员权限"""
52 | try:
53 | return (sys.platform == 'win32') or (os.geteuid() == 0)
54 | except AttributeError:
55 | # Windows无euid概念
56 | return False
57 |
--------------------------------------------------------------------------------
/src/validator/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/validator/__init__.py
--------------------------------------------------------------------------------
/src/validator/__pycache__/KeyValidator.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/validator/__pycache__/KeyValidator.cpython-39.pyc
--------------------------------------------------------------------------------
/src/validator/__pycache__/PortValidator.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/validator/__pycache__/PortValidator.cpython-39.pyc
--------------------------------------------------------------------------------
/src/validator/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackguest007/mitmproxy-gui/33f0cd5c63323d6780ad69d883c26f12cd13394b/src/validator/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------