# Архитектура burterm English version: [ARCHITECTURE.md](ARCHITECTURE.md). История решений, найденные баги и оговорки по надёжности — в [NOTES.md](NOTES.md). ## Обзор burterm — терминальный инструмент для веб-пентеста, bug bounty и CTF: один статический Go-бинарник, 13 вкладок TUI и headless CLI-режим на том же движке. Сборка без cgo. ``` cmd/burterm/ точка входа: CLI-флаги или запуск TUI internal/ engine/ ядро Intruder: маркеры, атаки, фильтры payload/ генераторы payload'ов cli/ разбор флагов и payload-спецификаций proxy/ MITM-прокси spider/ краулер sitemap/ scope-правила, дерево сайта scanner/ активные/пассивные проверки уязвимостей fuzzer/ blackbox-фаззер бинарников project/ хранилище сессии (SQLite+FTS5) decoder/ comparer/ sequencer/ утилиты tui/ интерфейс (bubbletea) ``` ## Общие принципы - **Асинхронный I/O через `tea.Cmd`/`tea.Msg`.** TUI построен на архитектуре Elm: `Update(msg) (Model, Cmd)`. Любой побочный эффект (сеть, диск, таймер) — это `tea.Cmd`, функция без аргументов, возвращающая `tea.Msg`, выполняемая фреймворком в отдельной горутине. `Update` никогда не блокируется на I/O. - **Потоковые операции — через каналы.** Intruder-атаки, Scanner, Spider, Fuzzer стримят результаты через `<-chan T`. Общий паттерн: горутина-продюсер пишет в канал через `select` с `<-ctx.Done()`; TUI читает через `waitForXxx(ch) tea.Cmd`, переиздающий себя после каждого сообщения. - **Значения снимаются с модели до ухода `tea.Cmd` в фон** — замыкание не держит ссылку на модель, которая может измениться до того, как команда выполнится. ## internal/engine — ядро Intruder - `§маркеры§` в сыром HTTP-запросе отмечают точки вставки payload'а. `ParseMarkers` вычленяет их в `[]InsertionPoint{Start, End}` (байтовые смещения в очищенной строке) и возвращает текст без маркеров. `InsertBeforeMarker` вставляет произвольный текст перед N-м маркером — используется рекурсией (см. ниже). - `BuildRequest` подставляет payload'ы и парсит результат в `*http.Request` через `http.ReadRequest`. - Четыре режима атаки: `RunSniper`, `RunBattering`, `RunPitchfork`, `RunClusterBomb` — общий пул воркеров, читающих задания из канала. Pitchfork/ClusterBomb используют `drainGenerator`, вычитывающий генератор целиком в память перед стартом. - `EstimateTotal` считает ожидаемое число запросов по `Len()` генераторов до старта атаки — для индикации прогресса в TUI. - `ParseStatusFilter`/`ParseLengthFilter`/`ParseWordFilter`/`ParseLineFilter` — общий синтаксис (`>N`, `` / `range:::` / `preset:<имя>` / `brute:<алфавит>::`, с необязательным суффиксом `|ext:...`. Используется и headless-режимом (`cmd/burterm`), и TUI — единая грамматика. ## internal/proxy — MITM-прокси - `Server` — форвардный прокси с MITM через собственный CA (`ca.go`, генерируется в `~/.burterm` при первом запуске), `CONNECT`-туннель с `tls.Server` и динамическим выпуском листовых сертификатов по SNI. - Каждая транзакция — `Entry{Raw, StatusCode, Length, Headers, ResponseBody, ...}` в потокобезопасном `Store` (`sync.Mutex`, подписка на новые записи через канал). - `Server.SetScope(*sitemap.Scope)` под `sync.RWMutex` — если задан, `capture`/`captureErr` пропускают запись в `Store` для запросов вне scope. Сам трафик прокси обслуживает независимо от scope. - `session.go`: `ExtractSessionHeaders(entries, host)` вытаскивает `Cookie`/`Authorization` из истории для конкретного хоста (парсит их из `Entry.Raw`). ## internal/spider — краулер `Spider.Crawl` — BFS-обход в границах `scope *url.URL` и `maxDepth`. `extractLinksAndForms` парсит HTML, извлекает ссылки и описания форм. GET-формы (`Method=="GET"`) автоматически конвертируются в URL с заглушками `test` на каждое поле и добавляются в очередь обхода (`buildGetFormURL`); POST-формы пропускаются. `SetHeaders` задаёт заголовки для каждого запроса обхода — используется для передачи сессионных Cookie/Authorization из Proxy. ## internal/sitemap — scope и дерево сайта `Scope` — упорядоченный список include/exclude regex-правил (`Add`/`RemoveAt`/`Matches`/`Rules`). `Tree`/`Node`/`Endpoint` — дерево путей сайта, строится из потока URL через `Build`, экспортируется в JSON. ## internal/scanner — проверки уязвимостей - `Check` — интерфейс активной проверки (`Name`/`Probes`/`Analyze`), подставляет payload'ы в одну точку вставки через ту же `engine.BuildRequest`, что и Intruder. Реализации: SQLi, XSS (reflected, с уникальной канарейкой), SSTI, LFI, RCE (time-based), SSRF, XXE. - `Scanner.Run` возвращает канал `Event{Kind: EventProgress|EventFinding}` — прогресс и находки в одном потоке. - `CheckCORS` — одноразовая проверка через заголовок `Origin` (не вписывается в интерфейс `Check`, так как не работает через маркер). - `DecodeJWT`/`AlgNoneVariant` — разбор JWT и генерация варианта без подписи для проверки обхода. ## internal/fuzzer — фаззер бинарников Blackbox-мутационный фаззер произвольного исполняемого файла (CTF pwn). `Config{Target, Args, UseStdin, Timeout, Workers, CrashDir}`. Мутации (`mutate.go`): bit-flip, byte-flip, arithmetic, interesting values, block delete/duplicate, splice, `havoc` (комбинация нескольких мутаций за проход). Краш определяется по сигналу завершения процесса (`SIGSEGV`/`SIGABRT`/`SIGFPE`/`SIGILL`/`SIGBUS`) через `syscall.WaitStatus`. `Run` возвращает канал `Event{Kind: EventProgress|EventCrash}`, каждый воркер — независимая горутина со своим `rand.Source`. ## internal/project — хранилище сессии SQLite (`modernc.org/sqlite`, без cgo) с FTS5-индексом в режиме external content (текст хранится один раз в `requests`, `requests_fts` держит только инвертированный индекс), синхронизация через триггеры `INSERT`/`UPDATE`/`DELETE`. `Store.Open` ставит `db.SetMaxOpenConns(1)`. `ParseQuery` — мини-язык поиска (`host:… method:… status:… color:… текст`) — известные `key:value`-токены уходят в структурированный SQL, остальное — в FTS5 `MATCH`. `SaveMeta`/`LoadMeta` — произвольные key-value записи (используется для scope-правил Target). `SaveLastPath`/`LoadLastPath` — путь последнего открытого проекта хранится вне самой БД (`~/.burterm/last-project`). ## internal/decoder, comparer, sequencer `decoder` — кодеки URL/Base64/HTML/Hex/MD5 и цепочка автоопределения. `comparer` — токенный LCS-diff. `sequencer` — статистические тесты FIPS 140-2 (monobit/poker/runs/long-run) на 20000-битных блоках. ## internal/tui — интерфейс - `Model` (`model.go`) — корневая модель, поле `active view` определяет видимую вкладку. `Update` делегирует необработанные сообщения активной вкладке. - Каждая вкладка — своя `xxxModel` в отдельном файле (`requestbuilder.go`, `results.go`, `proxyview.go`, `repeater.go`, `spiderview.go`, `targetview.go`, `decoderview.go`, `comparerview.go`, `sequencerview.go`, `dashboardview.go`, `scannerview.go`, `projectview.go`, `fuzzerview.go`), с методами `Update(tea.Msg) (xxxModel, tea.Cmd)` и `View() string`. - `theme.go` — палитра, `panel()` (рамка с заголовком через `lipgloss.RoundedBorder`), `renderTabs()` (таб-бар с заливкой активной вкладки), `renderLogo()`. - `results.go` — кэширует скомпилированные предикаты фильтров (`recompileFilters`), копит отфильтрованный вывод в `strings.Builder` инкрементально (`AddResult`), рендерит во `viewport` дросселированно по таймеру `resultsTickCmd` (раз в 300мс), только для видимой атаки. - `attacks []*attackRun` — список независимых параллельных атак, каждая со своим `id`/каналом/`cancel`/`resultsModel`. - `recursionMeta` — параметры авто-рекурсии Intruder в найденные директории: шаблон запроса, точка вставки, спецификации payload'ов, глубина, предикат статусов. - Сообщения именуются по паттерну `xxxStartedMsg`/`xxxResultMsg`/ `xxxDoneMsg`/`xxxErrMsg` для каждой длительной операции. ## Хранение на диске Всё под `~/.burterm/`: `ca.pem`/`ca-key.pem` (MITM CA), `last-project` (путь последнего проекта), `fuzz-crashes//` (крашащие вводы фаззера), `sitemap-.json` (экспорт карты сайта). ## Режимы запуска TUI (без аргументов) и headless CLI (`-request`/`-payload`/`-mode` и т.д., см. `internal/cli/flags.go`) используют один и тот же `internal/engine` — сценарии CI/скриптов не дублируют логику атаки.