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.
Files changed (169) hide show
  1. pentool/__init__.py +4 -0
  2. pentool/__main__.py +17 -0
  3. pentool/api/__init__.py +45 -0
  4. pentool/api/base_api.py +52 -0
  5. pentool/api/comparer_api.py +23 -0
  6. pentool/api/decoder_api.py +28 -0
  7. pentool/api/intruder_api.py +209 -0
  8. pentool/api/proxy_api.py +319 -0
  9. pentool/api/repeater_api.py +118 -0
  10. pentool/api/scanner_api.py +336 -0
  11. pentool/api/sequencer_api.py +21 -0
  12. pentool/api/spider_api.py +126 -0
  13. pentool/api/target_api.py +121 -0
  14. pentool/cli/__init__.py +1 -0
  15. pentool/cli/main.py +100 -0
  16. pentool/cli/project.py +90 -0
  17. pentool/cli/proxy.py +185 -0
  18. pentool/cli/scan.py +118 -0
  19. pentool/core/__init__.py +1 -0
  20. pentool/core/config.py +184 -0
  21. pentool/core/crash_reporter.py +75 -0
  22. pentool/core/database.py +139 -0
  23. pentool/core/event_bus.py +232 -0
  24. pentool/core/events.py +164 -0
  25. pentool/core/features.py +410 -0
  26. pentool/core/license.py +294 -0
  27. pentool/core/logging.py +59 -0
  28. pentool/core/plugin_manager.py +332 -0
  29. pentool/core/project.py +37 -0
  30. pentool/core/storage_interface.py +311 -0
  31. pentool/core/updater.py +96 -0
  32. pentool/core/utils.py +61 -0
  33. pentool/modules/__init__.py +1 -0
  34. pentool/modules/comparer.py +177 -0
  35. pentool/modules/decoder.py +281 -0
  36. pentool/modules/intruder.py +432 -0
  37. pentool/modules/intruder_turbo.py +190 -0
  38. pentool/modules/match_replace.py +146 -0
  39. pentool/modules/proxy.py +803 -0
  40. pentool/modules/repeater.py +237 -0
  41. pentool/modules/scanner/__init__.py +7 -0
  42. pentool/modules/scanner/ai_analyzer.py +230 -0
  43. pentool/modules/scanner/base.py +173 -0
  44. pentool/modules/scanner/baseline.py +101 -0
  45. pentool/modules/scanner/checks/__init__.py +47 -0
  46. pentool/modules/scanner/checks/broken_auth.py +231 -0
  47. pentool/modules/scanner/checks/cors.py +209 -0
  48. pentool/modules/scanner/checks/dom_xss.py +114 -0
  49. pentool/modules/scanner/checks/graphql.py +110 -0
  50. pentool/modules/scanner/checks/header_injection.py +262 -0
  51. pentool/modules/scanner/checks/headers.py +75 -0
  52. pentool/modules/scanner/checks/helpers.py +358 -0
  53. pentool/modules/scanner/checks/info_leak.py +68 -0
  54. pentool/modules/scanner/checks/jwt_none.py +238 -0
  55. pentool/modules/scanner/checks/lfi.py +186 -0
  56. pentool/modules/scanner/checks/nosql_injection.py +92 -0
  57. pentool/modules/scanner/checks/oauth.py +123 -0
  58. pentool/modules/scanner/checks/open_redirect.py +168 -0
  59. pentool/modules/scanner/checks/path_traversal.py +229 -0
  60. pentool/modules/scanner/checks/prototype_pollution.py +88 -0
  61. pentool/modules/scanner/checks/rce.py +338 -0
  62. pentool/modules/scanner/checks/sensitive_data.py +74 -0
  63. pentool/modules/scanner/checks/sqli.py +546 -0
  64. pentool/modules/scanner/checks/ssrf.py +273 -0
  65. pentool/modules/scanner/checks/ssti.py +353 -0
  66. pentool/modules/scanner/checks/xss.py +622 -0
  67. pentool/modules/scanner/checks/xxe.py +240 -0
  68. pentool/modules/scanner/engine.py +407 -0
  69. pentool/modules/scanner/fingerprint.py +169 -0
  70. pentool/modules/scanner/helpers.py +94 -0
  71. pentool/modules/scanner/mutator.py +378 -0
  72. pentool/modules/scanner/oob.py +104 -0
  73. pentool/modules/scanner/passive.py +114 -0
  74. pentool/modules/scanner/payloads.py +224 -0
  75. pentool/modules/scanner/report.py +117 -0
  76. pentool/modules/sequencer.py +500 -0
  77. pentool/modules/spider.py +702 -0
  78. pentool/modules/target.py +190 -0
  79. pentool/modules/websocket_handler.py +259 -0
  80. pentool/plugins/__init__.py +7 -0
  81. pentool/plugins/builtin/__init__.py +1 -0
  82. pentool/plugins/builtin/payloads_pro.py +404 -0
  83. pentool/plugins/builtin/reports_pro.py +450 -0
  84. pentool/plugins/builtin/scanner_pro.py +308 -0
  85. pentool/plugins/example_plugin.py +75 -0
  86. pentool/project_to_txt.py +67 -0
  87. pentool/services/__init__.py +1 -0
  88. pentool/services/base_service.py +64 -0
  89. pentool/services/intruder_service.py +108 -0
  90. pentool/services/proxy_service.py +232 -0
  91. pentool/services/repeater_service.py +111 -0
  92. pentool/services/scan_service.py +340 -0
  93. pentool/storage/__init__.py +0 -0
  94. pentool/storage/http_storage.py +522 -0
  95. pentool/storage/large_body_handler.py +54 -0
  96. pentool/storage/lru_cache.py +49 -0
  97. pentool/t.py +213 -0
  98. pentool/tui/__init__.py +1 -0
  99. pentool/tui/app.py +1438 -0
  100. pentool/tui/constants.py +79 -0
  101. pentool/tui/dialogs/__init__.py +0 -0
  102. pentool/tui/dialogs/cert_dialog.py +81 -0
  103. pentool/tui/dialogs/file_selector.py +227 -0
  104. pentool/tui/dialogs/load_from_proxy.py +125 -0
  105. pentool/tui/dialogs/match_replace_dialog.py +229 -0
  106. pentool/tui/dialogs/project_dialog.py +82 -0
  107. pentool/tui/dialogs/scope_dialog.py +225 -0
  108. pentool/tui/messages.py +121 -0
  109. pentool/tui/mixins/__init__.py +0 -0
  110. pentool/tui/mixins/app_mixin.py +61 -0
  111. pentool/tui/mixins/dialog_cancel.py +25 -0
  112. pentool/tui/mixins/request_context_menu.py +285 -0
  113. pentool/tui/mixins/tab_rename.py +101 -0
  114. pentool/tui/screens/__init__.py +31 -0
  115. pentool/tui/screens/comparer/__init__.py +3 -0
  116. pentool/tui/screens/comparer/screen.py +233 -0
  117. pentool/tui/screens/dashboard/__init__.py +2 -0
  118. pentool/tui/screens/dashboard/live_dashboard.py +741 -0
  119. pentool/tui/screens/dashboard/screen.py +820 -0
  120. pentool/tui/screens/decoder/__init__.py +3 -0
  121. pentool/tui/screens/decoder/screen.py +311 -0
  122. pentool/tui/screens/extensions/__init__.py +3 -0
  123. pentool/tui/screens/extensions/screen.py +24 -0
  124. pentool/tui/screens/intruder/__init__.py +3 -0
  125. pentool/tui/screens/intruder/screen.py +1362 -0
  126. pentool/tui/screens/proxy/__init__.py +3 -0
  127. pentool/tui/screens/proxy/screen.py +1664 -0
  128. pentool/tui/screens/repeater/__init__.py +3 -0
  129. pentool/tui/screens/repeater/screen.py +646 -0
  130. pentool/tui/screens/scanner/__init__.py +3 -0
  131. pentool/tui/screens/scanner/screen.py +1984 -0
  132. pentool/tui/screens/sequencer/__init__.py +3 -0
  133. pentool/tui/screens/sequencer/screen.py +520 -0
  134. pentool/tui/screens/settings/__init__.py +5 -0
  135. pentool/tui/screens/settings/hotkeys.py +134 -0
  136. pentool/tui/screens/settings/screen.py +543 -0
  137. pentool/tui/screens/spider/__init__.py +3 -0
  138. pentool/tui/screens/spider/screen.py +385 -0
  139. pentool/tui/screens/target/__init__.py +4 -0
  140. pentool/tui/screens/target/screen.py +361 -0
  141. pentool/tui/screens/terminal/__init__.py +5 -0
  142. pentool/tui/screens/terminal/screen.py +181 -0
  143. pentool/tui/widgets/__init__.py +1 -0
  144. pentool/tui/widgets/context_menu.py +148 -0
  145. pentool/tui/widgets/filter_bar.py +206 -0
  146. pentool/tui/widgets/inspector_panel.py +112 -0
  147. pentool/tui/widgets/menu.py +86 -0
  148. pentool/tui/widgets/menu_bar.py +238 -0
  149. pentool/tui/widgets/module_tabs.py +73 -0
  150. pentool/tui/widgets/payload_drop_zone.py +66 -0
  151. pentool/tui/widgets/request_editor.py +504 -0
  152. pentool/tui/widgets/resize_handle.py +116 -0
  153. pentool/tui/widgets/search_bar.py +113 -0
  154. pentool/tui/widgets/statusbar.py +99 -0
  155. pentool/tui/widgets/toolbar_button.py +76 -0
  156. pentool/utils/__init__.py +1 -0
  157. pentool/utils/cert.py +361 -0
  158. pentool/utils/coder.py +170 -0
  159. pentool/utils/copy_as.py +251 -0
  160. pentool/utils/diff.py +91 -0
  161. pentool/utils/http_client.py +175 -0
  162. pentool/utils/parser.py +227 -0
  163. pentool/utils/terminal_check.py +32 -0
  164. pentool-1.0.0.dist-info/METADATA +155 -0
  165. pentool-1.0.0.dist-info/RECORD +169 -0
  166. pentool-1.0.0.dist-info/WHEEL +5 -0
  167. pentool-1.0.0.dist-info/entry_points.txt +2 -0
  168. pentool-1.0.0.dist-info/licenses/LICENSE +34 -0
  169. 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()
@@ -0,0 +1 @@
1
+ """Пакет tui: TUI-приложение на Textual."""