bidoytu 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. bidoytu-1.1.0/LICENSE +21 -0
  2. bidoytu-1.1.0/PKG-INFO +198 -0
  3. bidoytu-1.1.0/README.md +160 -0
  4. bidoytu-1.1.0/pyproject.toml +62 -0
  5. bidoytu-1.1.0/setup.cfg +4 -0
  6. bidoytu-1.1.0/src/bidoytu/__init__.py +11 -0
  7. bidoytu-1.1.0/src/bidoytu/__main__.py +5 -0
  8. bidoytu-1.1.0/src/bidoytu/app.py +65 -0
  9. bidoytu-1.1.0/src/bidoytu/assets/logo.ico +0 -0
  10. bidoytu-1.1.0/src/bidoytu/assets/logo.png +0 -0
  11. bidoytu-1.1.0/src/bidoytu/config.py +132 -0
  12. bidoytu-1.1.0/src/bidoytu/http_utils.py +218 -0
  13. bidoytu-1.1.0/src/bidoytu/net/__init__.py +5 -0
  14. bidoytu-1.1.0/src/bidoytu/net/async_sender.py +190 -0
  15. bidoytu-1.1.0/src/bidoytu/net/attack.py +228 -0
  16. bidoytu-1.1.0/src/bidoytu/net/interactsh.py +498 -0
  17. bidoytu-1.1.0/src/bidoytu/net/payloads.py +288 -0
  18. bidoytu-1.1.0/src/bidoytu/proxy/__init__.py +5 -0
  19. bidoytu-1.1.0/src/bidoytu/proxy/capture_addon.py +245 -0
  20. bidoytu-1.1.0/src/bidoytu/proxy/engine.py +213 -0
  21. bidoytu-1.1.0/src/bidoytu/resources.py +28 -0
  22. bidoytu-1.1.0/src/bidoytu/storage/__init__.py +7 -0
  23. bidoytu-1.1.0/src/bidoytu/storage/body_store.py +46 -0
  24. bidoytu-1.1.0/src/bidoytu/storage/models.py +119 -0
  25. bidoytu-1.1.0/src/bidoytu/storage/repository.py +176 -0
  26. bidoytu-1.1.0/src/bidoytu/ui/__init__.py +1 -0
  27. bidoytu-1.1.0/src/bidoytu/ui/attack_runner.py +233 -0
  28. bidoytu-1.1.0/src/bidoytu/ui/body_format.py +429 -0
  29. bidoytu-1.1.0/src/bidoytu/ui/ca_dialog.py +130 -0
  30. bidoytu-1.1.0/src/bidoytu/ui/collaborator_model.py +201 -0
  31. bidoytu-1.1.0/src/bidoytu/ui/collaborator_tab.py +722 -0
  32. bidoytu-1.1.0/src/bidoytu/ui/detail_view.py +120 -0
  33. bidoytu-1.1.0/src/bidoytu/ui/find_bar.py +121 -0
  34. bidoytu-1.1.0/src/bidoytu/ui/flow_layout.py +96 -0
  35. bidoytu-1.1.0/src/bidoytu/ui/flow_table_model.py +119 -0
  36. bidoytu-1.1.0/src/bidoytu/ui/group_dialog.py +150 -0
  37. bidoytu-1.1.0/src/bidoytu/ui/highlighter.py +73 -0
  38. bidoytu-1.1.0/src/bidoytu/ui/history_delegate.py +82 -0
  39. bidoytu-1.1.0/src/bidoytu/ui/history_view.py +278 -0
  40. bidoytu-1.1.0/src/bidoytu/ui/intercept_activity_model.py +204 -0
  41. bidoytu-1.1.0/src/bidoytu/ui/intercept_view.py +716 -0
  42. bidoytu-1.1.0/src/bidoytu/ui/intruder_results_model.py +183 -0
  43. bidoytu-1.1.0/src/bidoytu/ui/intruder_session.py +834 -0
  44. bidoytu-1.1.0/src/bidoytu/ui/intruder_tab.py +185 -0
  45. bidoytu-1.1.0/src/bidoytu/ui/main_window.py +403 -0
  46. bidoytu-1.1.0/src/bidoytu/ui/marker_highlighter.py +47 -0
  47. bidoytu-1.1.0/src/bidoytu/ui/message_view.py +245 -0
  48. bidoytu-1.1.0/src/bidoytu/ui/payload_editor.py +363 -0
  49. bidoytu-1.1.0/src/bidoytu/ui/proxy_tab.py +136 -0
  50. bidoytu-1.1.0/src/bidoytu/ui/repeater_session.py +707 -0
  51. bidoytu-1.1.0/src/bidoytu/ui/repeater_tab.py +573 -0
  52. bidoytu-1.1.0/src/bidoytu/ui/theme.py +843 -0
  53. bidoytu-1.1.0/src/bidoytu/ui/wrapping_tab_bar.py +361 -0
  54. bidoytu-1.1.0/src/bidoytu.egg-info/PKG-INFO +198 -0
  55. bidoytu-1.1.0/src/bidoytu.egg-info/SOURCES.txt +57 -0
  56. bidoytu-1.1.0/src/bidoytu.egg-info/dependency_links.txt +1 -0
  57. bidoytu-1.1.0/src/bidoytu.egg-info/entry_points.txt +2 -0
  58. bidoytu-1.1.0/src/bidoytu.egg-info/requires.txt +10 -0
  59. bidoytu-1.1.0/src/bidoytu.egg-info/top_level.txt +1 -0
bidoytu-1.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bidoytu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
bidoytu-1.1.0/PKG-INFO ADDED
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: bidoytu
3
+ Version: 1.1.0
4
+ Summary: An intercepting HTTP proxy tool built with PySide6 and mitmproxy.
5
+ Author-email: Bidoytu <hello@swarnimbandekar.in>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Bidoytu/Bidoytu
8
+ Project-URL: Repository, https://github.com/Bidoytu/Bidoytu
9
+ Project-URL: Issues, https://github.com/Bidoytu/Bidoytu/issues
10
+ Keywords: proxy,mitm,http,security,pentest,pyside6,mitmproxy
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: X11 Applications :: Qt
13
+ Classifier: Environment :: Win32 (MS Windows)
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Internet :: Proxy Servers
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Software Development :: Testing
25
+ Requires-Python: >=3.11
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: PySide6>=6.6
29
+ Requires-Dist: mitmproxy>=11.0
30
+ Requires-Dist: httpx>=0.27
31
+ Requires-Dist: cryptography>=42.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pyinstaller>=6.0; extra == "dev"
34
+ Requires-Dist: nuitka>=2.0; extra == "dev"
35
+ Requires-Dist: build>=1.0; extra == "dev"
36
+ Requires-Dist: twine>=5.0; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # Bidoytu
40
+
41
+ An intercepting HTTP proxy tool for inspecting, modifying, and replaying web
42
+ traffic, built in Python. This repository currently contains the **base
43
+ architecture** only - a working skeleton you can run and build on.
44
+
45
+ ## Architecture
46
+
47
+ | Concern | Choice |
48
+ | --- | --- |
49
+ | Language | Python 3.11+ |
50
+ | Proxy / MITM engine | [mitmproxy](https://mitmproxy.org) used as a library (`DumpMaster`) |
51
+ | Desktop UI | [PySide6](https://doc.qt.io/qtforpython/) (Qt for Python) |
52
+ | Request/response editor | `QPlainTextEdit` + custom `QSyntaxHighlighter` |
53
+ | Database | SQLite via stdlib `sqlite3`, WAL mode, custom `QAbstractTableModel` |
54
+ | Large bodies | Stored as content-addressed files, referenced by path (not BLOBs) |
55
+ | Concurrency | `QThread` hosts mitmproxy on its own asyncio loop; UI updated via signals |
56
+ | Packaging | PyInstaller (dev), Nuitka (release) |
57
+
58
+ ### A note on the editor widget
59
+
60
+ QScintilla is a Riverbank project bound to PyQt and has **no official PySide6
61
+ binding** (licensing/ABI incompatibility). To keep the whole app on the
62
+ official PySide6 binding, the base uses `QPlainTextEdit` + a custom
63
+ `QSyntaxHighlighter`. This is isolated in `ui/message_view.py` and
64
+ `ui/highlighter.py`, so it can be swapped for a QScintilla or Monaco-in-
65
+ QWebEngineView approach later without touching the rest of the app.
66
+
67
+ ## Features (base)
68
+
69
+ - **Top-level tabs:** Proxy, Repeater, Intruder.
70
+ - **Proxy tab** with two sub-tabs:
71
+ - *HTTP History* - live traffic table + request/response detail.
72
+ - *Intercept* - pause in-flight requests; edit the raw request; **Forward**
73
+ or **Drop**; a toggle turns interception on/off. Requests queue while one
74
+ is held.
75
+ - **Repeater** - load a request (from history), edit it, resend via an async
76
+ `httpx` client, and view the response.
77
+ - **Intruder** - skeleton: request template with `§payload§` markers + payload
78
+ list. The attack runner is the documented next step.
79
+ - **Send to Repeater (Ctrl+R) / Send to Intruder (Ctrl+I)** via right-click on a
80
+ history row (or the keyboard shortcut when the table is focused). The Intercept
81
+ request editor has the same right-click actions.
82
+ - **Soft wrap** on all request/response views, toggleable per detail view.
83
+ - **Pretty-printed bodies** - JSON, XML/HTML, and URL-encoded forms are
84
+ formatted for display (raw request text stays verbatim for editing).
85
+ - **Configurable listen host/port** from the Proxy tab.
86
+ - **CA certificate export** for trusting HTTPS interception (Proxy tab →
87
+ *CA Certificate*).
88
+
89
+ ## Project layout
90
+
91
+ ```
92
+ src/bidoytu/
93
+ app.py # entry point (QApplication + MainWindow)
94
+ __main__.py # python -m bidoytu
95
+ config.py # paths + proxy/app configuration
96
+ http_utils.py # parse/build raw HTTP text <-> parts
97
+ proxy/
98
+ engine.py # ProxyEngine: QThread hosting mitmproxy DumpMaster
99
+ capture_addon.py # flow -> FlowRecord mapping + interception (pause/forward/drop)
100
+ net/
101
+ async_sender.py # AsyncHttpSender: httpx.AsyncClient on its own loop/thread
102
+ storage/
103
+ models.py # FlowRecord dataclass (framework-free)
104
+ repository.py # SQLite (WAL) CRUD
105
+ body_store.py # content-addressed large-body file store
106
+ ui/
107
+ main_window.py # top-level QTabWidget + wiring
108
+ proxy_tab.py # proxy controls + HTTP History / Intercept sub-tabs
109
+ history_view.py # traffic table + detail + send-to context menu/shortcuts
110
+ intercept_view.py # intercept queue, editor, forward/drop
111
+ repeater_tab.py # editable request + send + response
112
+ intruder_tab.py # skeleton (template + payloads)
113
+ detail_view.py # reusable request|response viewer + soft-wrap toggle
114
+ flow_table_model.py# custom QAbstractTableModel for history
115
+ message_view.py # raw HTTP view/editor (soft wrap + pretty print)
116
+ highlighter.py # HTTP QSyntaxHighlighter
117
+ body_format.py # content-type-aware body pretty-printer
118
+ ca_dialog.py # export/install the proxy CA certificate
119
+ packaging/
120
+ bidoytu.spec # PyInstaller (dev)
121
+ build_release.md # Nuitka (release) instructions
122
+ scripts/ # headless smoke + live verification tests
123
+ ```
124
+
125
+ ### Data flow
126
+
127
+ ```
128
+ Browser ─▶ mitmproxy (proxy thread, asyncio loop)
129
+ │ CaptureAddon maps flow -> FlowRecord
130
+ ▼
131
+ ProxyEngine.flow_captured (Qt signal, queued to UI thread)
132
+ ▼
133
+ MainWindow._on_flow_captured
134
+ ├─▶ FlowRepository.upsert (SQLite, big bodies -> BodyStore)
135
+ └─▶ FlowTableModel.upsert_record (history table updates live)
136
+ ```
137
+
138
+ ## Getting started
139
+
140
+ ```powershell
141
+ # 1. Create a virtual environment
142
+ python -m venv .venv
143
+ .venv\Scripts\Activate.ps1
144
+
145
+ # 2. Install
146
+ pip install -e .
147
+
148
+ # 3. Run
149
+ bidoytu
150
+ # or: python -m bidoytu
151
+ ```
152
+
153
+ Click **Start Proxy** on the Proxy tab. It listens on `127.0.0.1:8080` by
154
+ default (host and port are editable). Point a browser or tool at that proxy and
155
+ captured traffic appears in the history table; select a row to view the raw
156
+ request/response.
157
+
158
+ > **Intercepting HTTPS.** Browsers will reject the proxy's on-the-fly
159
+ > certificates (e.g. Firefox's `MOZILLA_PKIX_ERROR_MITM_DETECTED`) until you
160
+ > trust its CA. Start the proxy once (the CA is generated on first run under
161
+ > `<data_dir>/ca/`), then click **CA Certificate** on the Proxy tab to export
162
+ > the cert and follow the install instructions. Only trust this CA on machines
163
+ > you control, and remove it when you're done. Bidoytu only ever exports the
164
+ > public certificate, never the CA private key.
165
+
166
+ ## Building
167
+
168
+ - **Development:** `pyinstaller packaging/bidoytu.spec`
169
+ - **Release:** see `packaging/build_release.md` (Nuitka)
170
+
171
+ ## Status / next steps
172
+
173
+ Base architecture with a working Proxy (history + interception) and Repeater.
174
+ Natural next features:
175
+
176
+ - Intruder attack runner - iterate payloads through `AsyncHttpSender` and
177
+ collect results in a table (positions parsing for `§...§` markers).
178
+ - Response interception (currently only requests are paused).
179
+ - Scope filtering, search, and column sorting/filtering on the history view.
180
+ - Match/replace rules and a saved project format.
181
+
182
+ ## Contributing
183
+
184
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, the
185
+ testing workflow, and coding conventions, and [CONTRIBUTORS.md](CONTRIBUTORS.md)
186
+ for the list of people who have helped. To report a vulnerability, see
187
+ [SECURITY.md](SECURITY.md).
188
+
189
+ ## Legal / responsible use
190
+
191
+ Bidoytu is an intercepting proxy intended for testing systems **you own or are
192
+ explicitly authorized to test**. Intercepting traffic or installing a MITM CA on
193
+ machines or networks without permission may be illegal. You are responsible for
194
+ how you use it.
195
+
196
+ ## License
197
+
198
+ MIT - see [LICENSE](LICENSE).
@@ -0,0 +1,160 @@
1
+ # Bidoytu
2
+
3
+ An intercepting HTTP proxy tool for inspecting, modifying, and replaying web
4
+ traffic, built in Python. This repository currently contains the **base
5
+ architecture** only - a working skeleton you can run and build on.
6
+
7
+ ## Architecture
8
+
9
+ | Concern | Choice |
10
+ | --- | --- |
11
+ | Language | Python 3.11+ |
12
+ | Proxy / MITM engine | [mitmproxy](https://mitmproxy.org) used as a library (`DumpMaster`) |
13
+ | Desktop UI | [PySide6](https://doc.qt.io/qtforpython/) (Qt for Python) |
14
+ | Request/response editor | `QPlainTextEdit` + custom `QSyntaxHighlighter` |
15
+ | Database | SQLite via stdlib `sqlite3`, WAL mode, custom `QAbstractTableModel` |
16
+ | Large bodies | Stored as content-addressed files, referenced by path (not BLOBs) |
17
+ | Concurrency | `QThread` hosts mitmproxy on its own asyncio loop; UI updated via signals |
18
+ | Packaging | PyInstaller (dev), Nuitka (release) |
19
+
20
+ ### A note on the editor widget
21
+
22
+ QScintilla is a Riverbank project bound to PyQt and has **no official PySide6
23
+ binding** (licensing/ABI incompatibility). To keep the whole app on the
24
+ official PySide6 binding, the base uses `QPlainTextEdit` + a custom
25
+ `QSyntaxHighlighter`. This is isolated in `ui/message_view.py` and
26
+ `ui/highlighter.py`, so it can be swapped for a QScintilla or Monaco-in-
27
+ QWebEngineView approach later without touching the rest of the app.
28
+
29
+ ## Features (base)
30
+
31
+ - **Top-level tabs:** Proxy, Repeater, Intruder.
32
+ - **Proxy tab** with two sub-tabs:
33
+ - *HTTP History* - live traffic table + request/response detail.
34
+ - *Intercept* - pause in-flight requests; edit the raw request; **Forward**
35
+ or **Drop**; a toggle turns interception on/off. Requests queue while one
36
+ is held.
37
+ - **Repeater** - load a request (from history), edit it, resend via an async
38
+ `httpx` client, and view the response.
39
+ - **Intruder** - skeleton: request template with `§payload§` markers + payload
40
+ list. The attack runner is the documented next step.
41
+ - **Send to Repeater (Ctrl+R) / Send to Intruder (Ctrl+I)** via right-click on a
42
+ history row (or the keyboard shortcut when the table is focused). The Intercept
43
+ request editor has the same right-click actions.
44
+ - **Soft wrap** on all request/response views, toggleable per detail view.
45
+ - **Pretty-printed bodies** - JSON, XML/HTML, and URL-encoded forms are
46
+ formatted for display (raw request text stays verbatim for editing).
47
+ - **Configurable listen host/port** from the Proxy tab.
48
+ - **CA certificate export** for trusting HTTPS interception (Proxy tab →
49
+ *CA Certificate*).
50
+
51
+ ## Project layout
52
+
53
+ ```
54
+ src/bidoytu/
55
+ app.py # entry point (QApplication + MainWindow)
56
+ __main__.py # python -m bidoytu
57
+ config.py # paths + proxy/app configuration
58
+ http_utils.py # parse/build raw HTTP text <-> parts
59
+ proxy/
60
+ engine.py # ProxyEngine: QThread hosting mitmproxy DumpMaster
61
+ capture_addon.py # flow -> FlowRecord mapping + interception (pause/forward/drop)
62
+ net/
63
+ async_sender.py # AsyncHttpSender: httpx.AsyncClient on its own loop/thread
64
+ storage/
65
+ models.py # FlowRecord dataclass (framework-free)
66
+ repository.py # SQLite (WAL) CRUD
67
+ body_store.py # content-addressed large-body file store
68
+ ui/
69
+ main_window.py # top-level QTabWidget + wiring
70
+ proxy_tab.py # proxy controls + HTTP History / Intercept sub-tabs
71
+ history_view.py # traffic table + detail + send-to context menu/shortcuts
72
+ intercept_view.py # intercept queue, editor, forward/drop
73
+ repeater_tab.py # editable request + send + response
74
+ intruder_tab.py # skeleton (template + payloads)
75
+ detail_view.py # reusable request|response viewer + soft-wrap toggle
76
+ flow_table_model.py# custom QAbstractTableModel for history
77
+ message_view.py # raw HTTP view/editor (soft wrap + pretty print)
78
+ highlighter.py # HTTP QSyntaxHighlighter
79
+ body_format.py # content-type-aware body pretty-printer
80
+ ca_dialog.py # export/install the proxy CA certificate
81
+ packaging/
82
+ bidoytu.spec # PyInstaller (dev)
83
+ build_release.md # Nuitka (release) instructions
84
+ scripts/ # headless smoke + live verification tests
85
+ ```
86
+
87
+ ### Data flow
88
+
89
+ ```
90
+ Browser ─▶ mitmproxy (proxy thread, asyncio loop)
91
+ │ CaptureAddon maps flow -> FlowRecord
92
+ ▼
93
+ ProxyEngine.flow_captured (Qt signal, queued to UI thread)
94
+ ▼
95
+ MainWindow._on_flow_captured
96
+ ├─▶ FlowRepository.upsert (SQLite, big bodies -> BodyStore)
97
+ └─▶ FlowTableModel.upsert_record (history table updates live)
98
+ ```
99
+
100
+ ## Getting started
101
+
102
+ ```powershell
103
+ # 1. Create a virtual environment
104
+ python -m venv .venv
105
+ .venv\Scripts\Activate.ps1
106
+
107
+ # 2. Install
108
+ pip install -e .
109
+
110
+ # 3. Run
111
+ bidoytu
112
+ # or: python -m bidoytu
113
+ ```
114
+
115
+ Click **Start Proxy** on the Proxy tab. It listens on `127.0.0.1:8080` by
116
+ default (host and port are editable). Point a browser or tool at that proxy and
117
+ captured traffic appears in the history table; select a row to view the raw
118
+ request/response.
119
+
120
+ > **Intercepting HTTPS.** Browsers will reject the proxy's on-the-fly
121
+ > certificates (e.g. Firefox's `MOZILLA_PKIX_ERROR_MITM_DETECTED`) until you
122
+ > trust its CA. Start the proxy once (the CA is generated on first run under
123
+ > `<data_dir>/ca/`), then click **CA Certificate** on the Proxy tab to export
124
+ > the cert and follow the install instructions. Only trust this CA on machines
125
+ > you control, and remove it when you're done. Bidoytu only ever exports the
126
+ > public certificate, never the CA private key.
127
+
128
+ ## Building
129
+
130
+ - **Development:** `pyinstaller packaging/bidoytu.spec`
131
+ - **Release:** see `packaging/build_release.md` (Nuitka)
132
+
133
+ ## Status / next steps
134
+
135
+ Base architecture with a working Proxy (history + interception) and Repeater.
136
+ Natural next features:
137
+
138
+ - Intruder attack runner - iterate payloads through `AsyncHttpSender` and
139
+ collect results in a table (positions parsing for `§...§` markers).
140
+ - Response interception (currently only requests are paused).
141
+ - Scope filtering, search, and column sorting/filtering on the history view.
142
+ - Match/replace rules and a saved project format.
143
+
144
+ ## Contributing
145
+
146
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, the
147
+ testing workflow, and coding conventions, and [CONTRIBUTORS.md](CONTRIBUTORS.md)
148
+ for the list of people who have helped. To report a vulnerability, see
149
+ [SECURITY.md](SECURITY.md).
150
+
151
+ ## Legal / responsible use
152
+
153
+ Bidoytu is an intercepting proxy intended for testing systems **you own or are
154
+ explicitly authorized to test**. Intercepting traffic or installing a MITM CA on
155
+ machines or networks without permission may be illegal. You are responsible for
156
+ how you use it.
157
+
158
+ ## License
159
+
160
+ MIT - see [LICENSE](LICENSE).
@@ -0,0 +1,62 @@
1
+ [project]
2
+ name = "bidoytu"
3
+ version = "1.1.0"
4
+ description = "An intercepting HTTP proxy tool built with PySide6 and mitmproxy."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = { text = "MIT" }
8
+ authors = [
9
+ { name = "Bidoytu", email = "hello@swarnimbandekar.in" },
10
+ ]
11
+ keywords = ["proxy", "mitm", "http", "security", "pentest", "pyside6", "mitmproxy"]
12
+ classifiers = [
13
+ "Development Status :: 5 - Production/Stable",
14
+ "Environment :: X11 Applications :: Qt",
15
+ "Environment :: Win32 (MS Windows)",
16
+ "Intended Audience :: Developers",
17
+ "Intended Audience :: Information Technology",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Internet :: Proxy Servers",
25
+ "Topic :: Security",
26
+ "Topic :: Software Development :: Testing",
27
+ ]
28
+ dependencies = [
29
+ "PySide6>=6.6",
30
+ "mitmproxy>=11.0",
31
+ "httpx>=0.27",
32
+ "cryptography>=42.0",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/Bidoytu/Bidoytu"
37
+ Repository = "https://github.com/Bidoytu/Bidoytu"
38
+ Issues = "https://github.com/Bidoytu/Bidoytu/issues"
39
+
40
+ [project.optional-dependencies]
41
+ dev = [
42
+ "pyinstaller>=6.0",
43
+ "nuitka>=2.0",
44
+ "build>=1.0",
45
+ "twine>=5.0",
46
+ ]
47
+
48
+ [project.scripts]
49
+ bidoytu = "bidoytu.app:main"
50
+
51
+ [build-system]
52
+ requires = ["setuptools>=68", "wheel"]
53
+ build-backend = "setuptools.build_meta"
54
+
55
+ [tool.setuptools.packages.find]
56
+ where = ["src"]
57
+
58
+ [tool.setuptools.package-dir]
59
+ "" = "src"
60
+
61
+ [tool.setuptools.package-data]
62
+ bidoytu = ["assets/*.png", "assets/*.ico"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ """Bidoytu - an intercepting HTTP proxy tool.
2
+
3
+ Base architecture:
4
+ - Proxy/MITM engine: mitmproxy (DumpMaster) running in a QThread.
5
+ - Desktop UI: PySide6 (Qt for Python).
6
+ - Storage: SQLite (WAL) + on-disk body file store, exposed to the UI via
7
+ a custom QAbstractTableModel.
8
+ """
9
+
10
+ __version__ = "1.1.0"
11
+ __app_name__ = "Bidoytu"
@@ -0,0 +1,5 @@
1
+ """Enables ``python -m bidoytu``."""
2
+ from bidoytu.app import main
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())
@@ -0,0 +1,65 @@
1
+ """Application entry point.
2
+
3
+ Creates the Qt application, builds the main window, and starts the event loop.
4
+ The proxy starts automatically once the window is shown; if the listen port is
5
+ already in use, the window prompts the user to change the port or retry.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ import sys
11
+
12
+ from PySide6.QtGui import QIcon
13
+ from PySide6.QtWidgets import QApplication
14
+
15
+ from bidoytu import __app_name__
16
+ from bidoytu.config import AppConfig
17
+ from bidoytu.resources import logo_path
18
+ from bidoytu.ui.main_window import MainWindow
19
+ from bidoytu.ui.theme import apply_theme, load_theme
20
+
21
+
22
+ def _set_windows_app_id() -> None:
23
+ """Give Windows an explicit AppUserModelID so the taskbar uses our icon.
24
+
25
+ Without this, a Python-hosted app is grouped under python.exe and shows the
26
+ interpreter's icon on the taskbar instead of the window icon.
27
+ """
28
+ if os.name != "nt":
29
+ return
30
+ try:
31
+ import ctypes
32
+
33
+ ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
34
+ f"{__app_name__}.{__app_name__}"
35
+ )
36
+ except Exception:
37
+ # Non-fatal: the app still runs, just without the custom taskbar group.
38
+ pass
39
+
40
+
41
+ def main() -> int:
42
+ _set_windows_app_id()
43
+
44
+ app = QApplication(sys.argv)
45
+ app.setApplicationName(__app_name__)
46
+ app.setOrganizationName(__app_name__)
47
+
48
+ # Application/taskbar icon.
49
+ icon = QIcon(str(logo_path()))
50
+ if not icon.isNull():
51
+ app.setWindowIcon(icon)
52
+
53
+ # Apply the persisted theme (defaults to dark) before building widgets so
54
+ # highlighters pick up matching colors from the start.
55
+ apply_theme(app, load_theme())
56
+
57
+ config = AppConfig()
58
+ window = MainWindow(config)
59
+ window.show()
60
+
61
+ return app.exec()
62
+
63
+
64
+ if __name__ == "__main__":
65
+ raise SystemExit(main())
@@ -0,0 +1,132 @@
1
+ """Application configuration and filesystem paths.
2
+
3
+ Everything the app writes (SQLite DB, large request/response bodies) lives under
4
+ a single data directory so it is easy to locate, back up, or clear.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ from dataclasses import dataclass, field
10
+ from pathlib import Path
11
+
12
+
13
+ def _default_data_dir() -> Path:
14
+ """Return a per-user, per-OS data directory for Bidoytu."""
15
+ if os.name == "nt": # Windows
16
+ base = os.environ.get("LOCALAPPDATA") or os.path.expanduser("~")
17
+ return Path(base) / "Bidoytu"
18
+ # macOS / Linux
19
+ xdg = os.environ.get("XDG_DATA_HOME")
20
+ if xdg:
21
+ return Path(xdg) / "bidoytu"
22
+ return Path.home() / ".local" / "share" / "bidoytu"
23
+
24
+
25
+ @dataclass(slots=True)
26
+ class ProxyConfig:
27
+ """Listen settings for the mitmproxy engine."""
28
+
29
+ listen_host: str = "127.0.0.1"
30
+ listen_port: int = 8080
31
+ http2: bool = True
32
+
33
+
34
+ # Free, public Interactsh servers operated by ProjectDiscovery. They are tried
35
+ # in order at registration time; the first that accepts the registration wins.
36
+ # Users can add their own (self-hosted) server in the Collaborator tab.
37
+ DEFAULT_OAST_SERVERS = (
38
+ "oast.pro",
39
+ "oast.live",
40
+ "oast.site",
41
+ "oast.online",
42
+ "oast.fun",
43
+ "oast.me",
44
+ )
45
+
46
+
47
+ @dataclass(slots=True)
48
+ class CollaboratorConfig:
49
+ """Settings for the Collaborator (out-of-band interaction) feature.
50
+
51
+ Attributes:
52
+ servers: Ordered list of Interactsh server hostnames to try when
53
+ registering. The first entry is treated as the preferred server.
54
+ token: Optional ``Authorization`` token for protected / self-hosted
55
+ servers (leave empty for the public ones).
56
+ poll_interval_secs: How often to poll the server for new interactions.
57
+ """
58
+
59
+ servers: list[str] = field(default_factory=lambda: list(DEFAULT_OAST_SERVERS))
60
+ token: str = ""
61
+ poll_interval_secs: int = 10
62
+
63
+
64
+ @dataclass(slots=True)
65
+ class AppConfig:
66
+ """Top-level runtime configuration.
67
+
68
+ Attributes:
69
+ data_dir: Root directory for all persisted state.
70
+ proxy: Proxy listen configuration.
71
+ body_inline_limit: Bodies at or below this size (bytes) are stored
72
+ inline in SQLite; larger bodies are written to the file store and
73
+ referenced by path.
74
+ """
75
+
76
+ data_dir: Path = field(default_factory=_default_data_dir)
77
+ proxy: ProxyConfig = field(default_factory=ProxyConfig)
78
+ collaborator: CollaboratorConfig = field(default_factory=CollaboratorConfig)
79
+ body_inline_limit: int = 64 * 1024 # 64 KiB
80
+
81
+ @property
82
+ def db_path(self) -> Path:
83
+ return self.data_dir / "bidoytu.db"
84
+
85
+ @property
86
+ def bodies_dir(self) -> Path:
87
+ return self.data_dir / "bodies"
88
+
89
+ @property
90
+ def repeater_sessions_path(self) -> Path:
91
+ """JSON file holding persisted Repeater sessions across restarts."""
92
+ return self.data_dir / "repeater_sessions.json"
93
+
94
+ @property
95
+ def intruder_attack_path(self) -> Path:
96
+ """JSON file holding the last Intruder attack config across restarts."""
97
+ return self.data_dir / "intruder_attack.json"
98
+
99
+ @property
100
+ def collaborator_state_path(self) -> Path:
101
+ """JSON file holding Collaborator session state across restarts.
102
+
103
+ Stores the active Interactsh session (server, correlation id, keys),
104
+ generated payloads, and captured interactions so a running OAST session
105
+ can be resumed after a restart.
106
+ """
107
+ return self.data_dir / "collaborator.json"
108
+
109
+ @property
110
+ def confdir(self) -> Path:
111
+ """Directory where mitmproxy stores its generated CA and certs.
112
+
113
+ We keep it under Bidoytu's data dir (instead of the default
114
+ ``~/.mitmproxy``) so the CA is predictable and easy to export.
115
+ """
116
+ return self.data_dir / "ca"
117
+
118
+ @property
119
+ def ca_cert_pem(self) -> Path:
120
+ """PEM-encoded CA certificate (for Firefox, curl, most Linux tools)."""
121
+ return self.confdir / "mitmproxy-ca-cert.pem"
122
+
123
+ @property
124
+ def ca_cert_cer(self) -> Path:
125
+ """DER/.cer CA certificate (convenient for the Windows cert store)."""
126
+ return self.confdir / "mitmproxy-ca-cert.cer"
127
+
128
+ def ensure_dirs(self) -> None:
129
+ """Create the data, body, and CA directories if they do not exist."""
130
+ self.data_dir.mkdir(parents=True, exist_ok=True)
131
+ self.bodies_dir.mkdir(parents=True, exist_ok=True)
132
+ self.confdir.mkdir(parents=True, exist_ok=True)