pentool 1.0.0__py3-none-any.whl
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.
- pentool/__init__.py +4 -0
- pentool/__main__.py +17 -0
- pentool/api/__init__.py +45 -0
- pentool/api/base_api.py +52 -0
- pentool/api/comparer_api.py +23 -0
- pentool/api/decoder_api.py +28 -0
- pentool/api/intruder_api.py +209 -0
- pentool/api/proxy_api.py +319 -0
- pentool/api/repeater_api.py +118 -0
- pentool/api/scanner_api.py +336 -0
- pentool/api/sequencer_api.py +21 -0
- pentool/api/spider_api.py +126 -0
- pentool/api/target_api.py +121 -0
- pentool/cli/__init__.py +1 -0
- pentool/cli/main.py +100 -0
- pentool/cli/project.py +90 -0
- pentool/cli/proxy.py +185 -0
- pentool/cli/scan.py +118 -0
- pentool/core/__init__.py +1 -0
- pentool/core/config.py +184 -0
- pentool/core/crash_reporter.py +75 -0
- pentool/core/database.py +139 -0
- pentool/core/event_bus.py +232 -0
- pentool/core/events.py +164 -0
- pentool/core/features.py +410 -0
- pentool/core/license.py +294 -0
- pentool/core/logging.py +59 -0
- pentool/core/plugin_manager.py +332 -0
- pentool/core/project.py +37 -0
- pentool/core/storage_interface.py +311 -0
- pentool/core/updater.py +96 -0
- pentool/core/utils.py +61 -0
- pentool/modules/__init__.py +1 -0
- pentool/modules/comparer.py +177 -0
- pentool/modules/decoder.py +281 -0
- pentool/modules/intruder.py +432 -0
- pentool/modules/intruder_turbo.py +190 -0
- pentool/modules/match_replace.py +146 -0
- pentool/modules/proxy.py +803 -0
- pentool/modules/repeater.py +237 -0
- pentool/modules/scanner/__init__.py +7 -0
- pentool/modules/scanner/ai_analyzer.py +230 -0
- pentool/modules/scanner/base.py +173 -0
- pentool/modules/scanner/baseline.py +101 -0
- pentool/modules/scanner/checks/__init__.py +47 -0
- pentool/modules/scanner/checks/broken_auth.py +231 -0
- pentool/modules/scanner/checks/cors.py +209 -0
- pentool/modules/scanner/checks/dom_xss.py +114 -0
- pentool/modules/scanner/checks/graphql.py +110 -0
- pentool/modules/scanner/checks/header_injection.py +262 -0
- pentool/modules/scanner/checks/headers.py +75 -0
- pentool/modules/scanner/checks/helpers.py +358 -0
- pentool/modules/scanner/checks/info_leak.py +68 -0
- pentool/modules/scanner/checks/jwt_none.py +238 -0
- pentool/modules/scanner/checks/lfi.py +186 -0
- pentool/modules/scanner/checks/nosql_injection.py +92 -0
- pentool/modules/scanner/checks/oauth.py +123 -0
- pentool/modules/scanner/checks/open_redirect.py +168 -0
- pentool/modules/scanner/checks/path_traversal.py +229 -0
- pentool/modules/scanner/checks/prototype_pollution.py +88 -0
- pentool/modules/scanner/checks/rce.py +338 -0
- pentool/modules/scanner/checks/sensitive_data.py +74 -0
- pentool/modules/scanner/checks/sqli.py +546 -0
- pentool/modules/scanner/checks/ssrf.py +273 -0
- pentool/modules/scanner/checks/ssti.py +353 -0
- pentool/modules/scanner/checks/xss.py +622 -0
- pentool/modules/scanner/checks/xxe.py +240 -0
- pentool/modules/scanner/engine.py +407 -0
- pentool/modules/scanner/fingerprint.py +169 -0
- pentool/modules/scanner/helpers.py +94 -0
- pentool/modules/scanner/mutator.py +378 -0
- pentool/modules/scanner/oob.py +104 -0
- pentool/modules/scanner/passive.py +114 -0
- pentool/modules/scanner/payloads.py +224 -0
- pentool/modules/scanner/report.py +117 -0
- pentool/modules/sequencer.py +500 -0
- pentool/modules/spider.py +702 -0
- pentool/modules/target.py +190 -0
- pentool/modules/websocket_handler.py +259 -0
- pentool/plugins/__init__.py +7 -0
- pentool/plugins/builtin/__init__.py +1 -0
- pentool/plugins/builtin/payloads_pro.py +404 -0
- pentool/plugins/builtin/reports_pro.py +450 -0
- pentool/plugins/builtin/scanner_pro.py +308 -0
- pentool/plugins/example_plugin.py +75 -0
- pentool/project_to_txt.py +67 -0
- pentool/services/__init__.py +1 -0
- pentool/services/base_service.py +64 -0
- pentool/services/intruder_service.py +108 -0
- pentool/services/proxy_service.py +232 -0
- pentool/services/repeater_service.py +111 -0
- pentool/services/scan_service.py +340 -0
- pentool/storage/__init__.py +0 -0
- pentool/storage/http_storage.py +522 -0
- pentool/storage/large_body_handler.py +54 -0
- pentool/storage/lru_cache.py +49 -0
- pentool/t.py +213 -0
- pentool/tui/__init__.py +1 -0
- pentool/tui/app.py +1438 -0
- pentool/tui/constants.py +79 -0
- pentool/tui/dialogs/__init__.py +0 -0
- pentool/tui/dialogs/cert_dialog.py +81 -0
- pentool/tui/dialogs/file_selector.py +227 -0
- pentool/tui/dialogs/load_from_proxy.py +125 -0
- pentool/tui/dialogs/match_replace_dialog.py +229 -0
- pentool/tui/dialogs/project_dialog.py +82 -0
- pentool/tui/dialogs/scope_dialog.py +225 -0
- pentool/tui/messages.py +121 -0
- pentool/tui/mixins/__init__.py +0 -0
- pentool/tui/mixins/app_mixin.py +61 -0
- pentool/tui/mixins/dialog_cancel.py +25 -0
- pentool/tui/mixins/request_context_menu.py +285 -0
- pentool/tui/mixins/tab_rename.py +101 -0
- pentool/tui/screens/__init__.py +31 -0
- pentool/tui/screens/comparer/__init__.py +3 -0
- pentool/tui/screens/comparer/screen.py +233 -0
- pentool/tui/screens/dashboard/__init__.py +2 -0
- pentool/tui/screens/dashboard/live_dashboard.py +741 -0
- pentool/tui/screens/dashboard/screen.py +820 -0
- pentool/tui/screens/decoder/__init__.py +3 -0
- pentool/tui/screens/decoder/screen.py +311 -0
- pentool/tui/screens/extensions/__init__.py +3 -0
- pentool/tui/screens/extensions/screen.py +24 -0
- pentool/tui/screens/intruder/__init__.py +3 -0
- pentool/tui/screens/intruder/screen.py +1362 -0
- pentool/tui/screens/proxy/__init__.py +3 -0
- pentool/tui/screens/proxy/screen.py +1664 -0
- pentool/tui/screens/repeater/__init__.py +3 -0
- pentool/tui/screens/repeater/screen.py +646 -0
- pentool/tui/screens/scanner/__init__.py +3 -0
- pentool/tui/screens/scanner/screen.py +1984 -0
- pentool/tui/screens/sequencer/__init__.py +3 -0
- pentool/tui/screens/sequencer/screen.py +520 -0
- pentool/tui/screens/settings/__init__.py +5 -0
- pentool/tui/screens/settings/hotkeys.py +134 -0
- pentool/tui/screens/settings/screen.py +543 -0
- pentool/tui/screens/spider/__init__.py +3 -0
- pentool/tui/screens/spider/screen.py +385 -0
- pentool/tui/screens/target/__init__.py +4 -0
- pentool/tui/screens/target/screen.py +361 -0
- pentool/tui/screens/terminal/__init__.py +5 -0
- pentool/tui/screens/terminal/screen.py +181 -0
- pentool/tui/widgets/__init__.py +1 -0
- pentool/tui/widgets/context_menu.py +148 -0
- pentool/tui/widgets/filter_bar.py +206 -0
- pentool/tui/widgets/inspector_panel.py +112 -0
- pentool/tui/widgets/menu.py +86 -0
- pentool/tui/widgets/menu_bar.py +238 -0
- pentool/tui/widgets/module_tabs.py +73 -0
- pentool/tui/widgets/payload_drop_zone.py +66 -0
- pentool/tui/widgets/request_editor.py +504 -0
- pentool/tui/widgets/resize_handle.py +116 -0
- pentool/tui/widgets/search_bar.py +113 -0
- pentool/tui/widgets/statusbar.py +99 -0
- pentool/tui/widgets/toolbar_button.py +76 -0
- pentool/utils/__init__.py +1 -0
- pentool/utils/cert.py +361 -0
- pentool/utils/coder.py +170 -0
- pentool/utils/copy_as.py +251 -0
- pentool/utils/diff.py +91 -0
- pentool/utils/http_client.py +175 -0
- pentool/utils/parser.py +227 -0
- pentool/utils/terminal_check.py +32 -0
- pentool-1.0.0.dist-info/METADATA +155 -0
- pentool-1.0.0.dist-info/RECORD +169 -0
- pentool-1.0.0.dist-info/WHEEL +5 -0
- pentool-1.0.0.dist-info/entry_points.txt +2 -0
- pentool-1.0.0.dist-info/licenses/LICENSE +34 -0
- pentool-1.0.0.dist-info/top_level.txt +1 -0
pentool/t.py
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Скрипт сборки проекта в один текстовый файл.
|
|
6
|
+
Собирает все текстовые файлы (по расширениям и известным именам),
|
|
7
|
+
игнорируя служебные папки (__pycache__, .git, node_modules и т.п.).
|
|
8
|
+
Результат сохраняется в указанный файл с заголовками для каждого исходного файла.
|
|
9
|
+
|
|
10
|
+
После создания выводится статистика:
|
|
11
|
+
- размер файла на диске
|
|
12
|
+
- количество символов
|
|
13
|
+
- приблизительное число токенов (символы / 4)
|
|
14
|
+
- предупреждение, если токенов > 128k
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import argparse
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
# Папки, которые будут полностью исключены из обхода
|
|
23
|
+
EXCLUDE_DIRS = {
|
|
24
|
+
'.git', '__pycache__', 'node_modules', '.venv', 'venv', 'env',
|
|
25
|
+
'dist', 'build', '.idea', '.vscode', '.pytest_cache', '.mypy_cache',
|
|
26
|
+
'.tox', '.eggs', 'coverage', 'htmlcov', '.ruff_cache', '.ipynb_checkpoints'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Расширения файлов, считающихся текстовыми (код, конфиги, документация)
|
|
30
|
+
INCLUDE_EXTS = {
|
|
31
|
+
'.py', '.js', '.jsx', '.ts', '.tsx', '.html', '.htm', '.css', '.scss', '.sass',
|
|
32
|
+
'.json', '.xml', '.yaml', '.yml', '.toml', '.ini', '.cfg', '.conf',
|
|
33
|
+
'.txt', '.md', '.rst', '.log', '.sh', '.bash', '.bat', '.cmd', '.ps1',
|
|
34
|
+
'.sql', '.php', '.rb', '.go', '.rs', '.c', '.cpp', '.h', '.hpp', '.java',
|
|
35
|
+
'.kt', '.swift', '.pl', '.pm', '.lua', '.r', '.dart', '.lisp', '.clj',
|
|
36
|
+
'.scala', '.groovy', '.gradle', '.makefile', '.cmake', '.dockerfile',
|
|
37
|
+
'.gitignore', '.gitattributes', '.editorconfig', '.env',
|
|
38
|
+
'.csv', '.tsv', '.svg', '.xml', '.xslt', '.wsdl'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Имена файлов без расширения, которые тоже нужно включать
|
|
42
|
+
SPECIAL_NAMES = {
|
|
43
|
+
'Dockerfile', 'Makefile', 'makefile', 'CMakeLists.txt', 'LICENSE',
|
|
44
|
+
'README', 'README.md', 'CHANGELOG', 'CONTRIBUTING', 'AUTHORS'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def should_include_file(file_path: Path, include_exts, exclude_dirs, special_names):
|
|
49
|
+
"""
|
|
50
|
+
Определяет, нужно ли включать файл в сборку.
|
|
51
|
+
Проверяет:
|
|
52
|
+
- не находится ли в исключённой папке;
|
|
53
|
+
- соответствует ли расширение списку разрешённых;
|
|
54
|
+
- или имя файла входит в специальные имена;
|
|
55
|
+
- а также пытается прочитать начало файла как UTF‑8 (проверка на текст).
|
|
56
|
+
"""
|
|
57
|
+
# Исключаем папки
|
|
58
|
+
for part in file_path.parts:
|
|
59
|
+
if part in exclude_dirs:
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
# Проверка расширения или специального имени
|
|
63
|
+
if file_path.suffix.lower() in include_exts:
|
|
64
|
+
pass # разрешено по расширению
|
|
65
|
+
elif file_path.name in special_names:
|
|
66
|
+
pass # разрешено по имени
|
|
67
|
+
else:
|
|
68
|
+
return False # не подходит
|
|
69
|
+
|
|
70
|
+
# Попытка прочитать небольшой кусок как текст UTF‑8
|
|
71
|
+
try:
|
|
72
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
73
|
+
f.read(1024)
|
|
74
|
+
return True
|
|
75
|
+
except (UnicodeDecodeError, PermissionError, OSError):
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def collect_files(root_dir: str, include_exts=None, exclude_dirs=None, special_names=None):
|
|
80
|
+
"""Рекурсивно собирает все подходящие файлы из корневой директории."""
|
|
81
|
+
if include_exts is None:
|
|
82
|
+
include_exts = INCLUDE_EXTS
|
|
83
|
+
if exclude_dirs is None:
|
|
84
|
+
exclude_dirs = EXCLUDE_DIRS
|
|
85
|
+
if special_names is None:
|
|
86
|
+
special_names = SPECIAL_NAMES
|
|
87
|
+
|
|
88
|
+
root = Path(root_dir).resolve()
|
|
89
|
+
if not root.is_dir():
|
|
90
|
+
raise NotADirectoryError(f"'{root_dir}' не является директорией.")
|
|
91
|
+
|
|
92
|
+
files = []
|
|
93
|
+
for item in root.rglob('*'):
|
|
94
|
+
if item.is_file():
|
|
95
|
+
if should_include_file(item, include_exts, exclude_dirs, special_names):
|
|
96
|
+
files.append(item)
|
|
97
|
+
return files
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def generate_output(files, output_file: str, root_dir: str):
|
|
101
|
+
"""Записывает все файлы в выходной файл с разделителями."""
|
|
102
|
+
with open(output_file, 'w', encoding='utf-8') as out:
|
|
103
|
+
out.write("=" * 80 + "\n")
|
|
104
|
+
out.write("СБОРКА ВСЕХ ФАЙЛОВ ПРОЕКТА\n")
|
|
105
|
+
out.write(f"Корневая папка: {root_dir}\n")
|
|
106
|
+
out.write(f"Всего файлов: {len(files)}\n")
|
|
107
|
+
out.write("=" * 80 + "\n\n")
|
|
108
|
+
|
|
109
|
+
for file_path in sorted(files):
|
|
110
|
+
# Относительный путь от корня проекта для наглядности
|
|
111
|
+
try:
|
|
112
|
+
rel_path = file_path.relative_to(Path(root_dir).resolve())
|
|
113
|
+
except ValueError:
|
|
114
|
+
rel_path = file_path # на случай, если путь не вложен
|
|
115
|
+
|
|
116
|
+
out.write(f"ФАЙЛ: {rel_path}\n")
|
|
117
|
+
out.write("-" * 80 + "\n")
|
|
118
|
+
try:
|
|
119
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
120
|
+
content = f.read()
|
|
121
|
+
out.write(content)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
out.write(f"ОШИБКА ЧТЕНИЯ: {e}\n")
|
|
124
|
+
out.write("\n" + "=" * 80 + "\n\n")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def main():
|
|
128
|
+
parser = argparse.ArgumentParser(
|
|
129
|
+
description="Собрать все текстовые файлы проекта в один файл для передачи ИИ."
|
|
130
|
+
)
|
|
131
|
+
parser.add_argument(
|
|
132
|
+
'--root', default='.',
|
|
133
|
+
help='Корневая папка проекта (по умолчанию текущая)'
|
|
134
|
+
)
|
|
135
|
+
parser.add_argument(
|
|
136
|
+
'--output', default='project_export.txt',
|
|
137
|
+
help='Выходной файл (по умолчанию project_export.txt)'
|
|
138
|
+
)
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
'--extensions', nargs='+',
|
|
141
|
+
help='Список расширений для включения (например .py .js) — переопределяет стандартный список'
|
|
142
|
+
)
|
|
143
|
+
parser.add_argument(
|
|
144
|
+
'--exclude-dirs', nargs='+',
|
|
145
|
+
help='Список дополнительных папок для исключения (добавляются к стандартным)'
|
|
146
|
+
)
|
|
147
|
+
parser.add_argument(
|
|
148
|
+
'--no-default-excludes', action='store_true',
|
|
149
|
+
help='Не использовать стандартный список исключённых папок'
|
|
150
|
+
)
|
|
151
|
+
parser.add_argument(
|
|
152
|
+
'--max-size-mb', type=float, default=None,
|
|
153
|
+
help='Пропускать файлы размером больше указанного МБ (по умолчанию без ограничения)'
|
|
154
|
+
)
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
'--no-stats', action='store_true',
|
|
157
|
+
help='Не выводить статистику по итоговому файлу'
|
|
158
|
+
)
|
|
159
|
+
args = parser.parse_args()
|
|
160
|
+
|
|
161
|
+
root_dir = args.root
|
|
162
|
+
output_file = args.output
|
|
163
|
+
|
|
164
|
+
# Формируем списки
|
|
165
|
+
include_exts = set(args.extensions) if args.extensions else None # None означает использовать стандартный
|
|
166
|
+
exclude_dirs = set(args.exclude_dirs) if args.exclude_dirs else set()
|
|
167
|
+
if not args.no_default_excludes:
|
|
168
|
+
exclude_dirs.update(EXCLUDE_DIRS)
|
|
169
|
+
|
|
170
|
+
files = collect_files(root_dir, include_exts, exclude_dirs, SPECIAL_NAMES)
|
|
171
|
+
|
|
172
|
+
# Фильтр по размеру, если задан
|
|
173
|
+
if args.max_size_mb is not None:
|
|
174
|
+
max_bytes = args.max_size_mb * 1024 * 1024
|
|
175
|
+
files = [f for f in files if f.stat().st_size <= max_bytes]
|
|
176
|
+
print(f"После фильтра по размеру осталось {len(files)} файлов.")
|
|
177
|
+
|
|
178
|
+
print(f"Найдено файлов для включения: {len(files)}")
|
|
179
|
+
generate_output(files, output_file, root_dir)
|
|
180
|
+
print(f"Результат записан в {output_file}")
|
|
181
|
+
|
|
182
|
+
# --- ВЫВОД СТАТИСТИКИ ---
|
|
183
|
+
if not args.no_stats:
|
|
184
|
+
try:
|
|
185
|
+
file_size = os.path.getsize(output_file)
|
|
186
|
+
with open(output_file, 'r', encoding='utf-8') as f:
|
|
187
|
+
content = f.read()
|
|
188
|
+
char_count = len(content)
|
|
189
|
+
approx_tokens = char_count // 4 # грубая оценка
|
|
190
|
+
|
|
191
|
+
print("\n" + "=" * 50)
|
|
192
|
+
print("СТАТИСТИКА ИТОГОВОГО ФАЙЛА")
|
|
193
|
+
print(f"Размер на диске: {file_size} байт "
|
|
194
|
+
f"({file_size / 1024:.2f} КБ, {file_size / 1024 / 1024:.2f} МБ)")
|
|
195
|
+
print(f"Количество символов: {char_count:,}")
|
|
196
|
+
print(f"Оценка токенов (символы ÷ 4): {approx_tokens:,}")
|
|
197
|
+
|
|
198
|
+
# Предупреждение о превышении типичного контекста
|
|
199
|
+
if approx_tokens > 128_000:
|
|
200
|
+
print("\n⚠️ ВНИМАНИЕ: оценка токенов превышает 128 000.")
|
|
201
|
+
print(" Это может не поместиться в контекст многих современных моделей (GPT-4, Claude 3 и др.).")
|
|
202
|
+
print(" Рекомендуется сократить проект или разбить на части.")
|
|
203
|
+
elif approx_tokens > 16_000:
|
|
204
|
+
print("\nℹ️ Оценка токенов > 16 000 — контекст может быть заполнен значительной частью.")
|
|
205
|
+
else:
|
|
206
|
+
print("\n✅ Оценка токенов в пределах типичного контекста (≤ 16 000).")
|
|
207
|
+
print("=" * 50)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
print(f"Не удалось подсчитать статистику: {e}")
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
if __name__ == '__main__':
|
|
213
|
+
main()
|
pentool/tui/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Пакет tui: TUI-приложение на Textual."""
|