Initial commit: Null DRM Official
Capture, decrypt, and restream toolkit with compiled-in app modules (RTE, TG4, BBC), on-device MITM proxy, streamd control plane, and www. BBC module.yaml is published (clear streams); other module values stay local.
This commit is contained in:
commit
2fa8f2435f
121 changed files with 17802 additions and 0 deletions
99
apps/capture/capturecmd/capturecmd.go
Normal file
99
apps/capture/capturecmd/capturecmd.go
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// Package capturecmd is the one-shot phone MITM capture command, exposed as a
|
||||
// library so the single drm binary can host it as a subcommand.
|
||||
package capturecmd
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"drmdecryption/adb"
|
||||
"drmdecryption/app"
|
||||
"drmdecryption/modcfg"
|
||||
"drmdecryption/phonecap"
|
||||
)
|
||||
|
||||
// Run performs one capture. App modules are compiled in, so there is no modules
|
||||
// directory to scan: --app names a registered provider.
|
||||
func Run(args []string) error {
|
||||
fs := flag.NewFlagSet("capture", flag.ExitOnError)
|
||||
appName := fs.String("app", "", "app module. Empty = passive MITM, no launch/auto-play")
|
||||
channel := fs.String("channel", "", "channel id for --auto-play")
|
||||
autoPlay := fs.Bool("auto-play", false, "auto-navigate to --channel (requires --app and --channel)")
|
||||
waitSec := fs.Int("wait", 180, "seconds to wait for license/mpd capture")
|
||||
python := fs.String("python", "", "python for wvkey.py (default: .venv)")
|
||||
wvd := fs.String("wvd", "", "path to .wvd device file (required for key fetch)")
|
||||
userAgent := fs.String("user-agent", "", "optional User-Agent for license requests")
|
||||
serial := fs.String("serial", "", "adb device serial (default: sole/USB selected device)")
|
||||
closeApp := fs.Bool("close", true, "force-stop --app when capture finishes (ignored in passive mode)")
|
||||
keyMode := fs.String("key-mode", "", "override the app's key mode: modulardrm | raw | none")
|
||||
// Each module contributes --<app>.<field> overrides for its local values.
|
||||
app.BindFlags(fs)
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintf(fs.Output(), "capture — one-shot phone MITM capture\n\nUsage:\n capture --app <%s> [--channel ID] [--auto-play] [--wvd PATH]\n capture (passive: play anything on the phone)\n\nFlags:\n", strings.Join(app.Names(), "|"))
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := adb.New()
|
||||
if *serial != "" {
|
||||
c = c.WithSerial(*serial)
|
||||
}
|
||||
|
||||
// No --app: passive MITM — the operator plays whatever they want and we dump
|
||||
// whatever DRM traffic appears.
|
||||
if strings.TrimSpace(*appName) == "" {
|
||||
_, err := phonecap.RunPassive(phonecap.Options{
|
||||
Client: c,
|
||||
Python: *python,
|
||||
WVD: *wvd,
|
||||
UserAgent: *userAgent,
|
||||
Wait: time.Duration(*waitSec) * time.Second,
|
||||
KeyMode: *keyMode,
|
||||
ClearProxy: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := app.Get(*appName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *autoPlay && strings.TrimSpace(*channel) == "" {
|
||||
return fmt.Errorf("--auto-play requires --channel (%s)", knownChannels(a))
|
||||
}
|
||||
if *channel != "" && !a.HasChannel(*channel) {
|
||||
return fmt.Errorf("unknown channel %q for %s (%s)", *channel, a.Name(), knownChannels(a))
|
||||
}
|
||||
|
||||
_, err = phonecap.Run(phonecap.Options{
|
||||
App: a,
|
||||
Channel: *channel,
|
||||
Client: c,
|
||||
Python: *python,
|
||||
WVD: *wvd,
|
||||
UserAgent: *userAgent,
|
||||
Wait: time.Duration(*waitSec) * time.Second,
|
||||
NoAutoPlay: !*autoPlay,
|
||||
CloseApp: *closeApp,
|
||||
KeyMode: *keyMode,
|
||||
ClearProxy: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// knownChannels describes what the operator can pick, or where to declare it when
|
||||
// the module has no local values file yet.
|
||||
func knownChannels(a app.App) string {
|
||||
ids := []string{}
|
||||
for _, ch := range a.Channels() {
|
||||
ids = append(ids, ch.ID)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return "no channels configured — add " + modcfg.Path(a.Name())
|
||||
}
|
||||
return "known: " + strings.Join(ids, ", ")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue