79 lines
1.9 KiB
Go
79 lines
1.9 KiB
Go
package cameradar
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// Reporter reports progress and results of the application.
|
|
type Reporter interface {
|
|
Start(step Step, message string)
|
|
Done(step Step, message string)
|
|
Error(step Step, err error)
|
|
Summary(streams []Stream, err error)
|
|
}
|
|
|
|
// App scans one or more targets and attacks all RTSP streams found to get their credentials.
|
|
type App struct {
|
|
streamScanner StreamScanner
|
|
attacker StreamAttacker
|
|
reporter Reporter
|
|
|
|
targets []string
|
|
ports []string
|
|
}
|
|
|
|
// StreamScanner discovers RTSP streams for the given inputs.
|
|
type StreamScanner interface {
|
|
Scan(ctx context.Context) ([]Stream, error)
|
|
}
|
|
|
|
// StreamAttacker attacks streams to discover routes and credentials.
|
|
type StreamAttacker interface {
|
|
Attack(ctx context.Context, streams []Stream) ([]Stream, error)
|
|
}
|
|
|
|
// New creates a new App with explicit dependencies.
|
|
func New(streamScanner StreamScanner, attacker StreamAttacker, targets, ports []string, reporter Reporter) (*App, error) {
|
|
if streamScanner == nil {
|
|
return nil, errors.New("stream scanner is required")
|
|
}
|
|
if attacker == nil {
|
|
return nil, errors.New("stream attacker is required")
|
|
}
|
|
|
|
app := &App{
|
|
streamScanner: streamScanner,
|
|
attacker: attacker,
|
|
targets: targets,
|
|
ports: ports,
|
|
reporter: reporter,
|
|
}
|
|
|
|
return app, nil
|
|
}
|
|
|
|
// Run runs the scan and prints the results.
|
|
func (a *App) Run(ctx context.Context) error {
|
|
a.reporter.Start(StepScan, "Scanning targets for RTSP streams")
|
|
streams, err := a.streamScanner.Scan(ctx)
|
|
if err != nil {
|
|
wrapped := fmt.Errorf("discovering devices: %w", err)
|
|
a.reporter.Error(StepScan, wrapped)
|
|
a.reporter.Summary(streams, wrapped)
|
|
return wrapped
|
|
}
|
|
a.reporter.Done(StepScan, "Scan complete")
|
|
|
|
streams, err = a.attacker.Attack(ctx, streams)
|
|
if err != nil {
|
|
wrapped := fmt.Errorf("attacking devices: %w", err)
|
|
a.reporter.Summary(streams, wrapped)
|
|
return wrapped
|
|
}
|
|
|
|
a.reporter.Summary(streams, nil)
|
|
return nil
|
|
}
|