跳到主要内容
KernelSU 模块

Duck ToolBox

不可变 Release 已同步

Android attestation toolbox with a Tricky Store, TEESimulator and OhMyKeymint manager, RKP workbench and Qualcomm device ID provisioning in one WebUI.

介绍

Duck ToolBox

Duck ToolBox is a root module (KernelSU, APatch or Magisk) that puts several Android attestation tools behind one WebUI. The backend is a Cargo workspace of single-purpose crates compiled into one JSON CLI (duckd); the WebUI is a set of feature folders that the app discovers at build time. Features only meet through versioned contracts, so each one can be changed, removed or added on its own.

Tools

  • Tricky Store manager: a complete port of KOWX712's Tricky Addon: Update Target List, for whichever keystore module is active:

    • Tricky Store: config.ini with per-app modes (pkg, pkg!, pkg?) and per-app policy, and the legacy target.txt + security_patch.txt layout.
    • TEESimulator: config.json profiles (mode, patch levels, identity, auto-include).
    • OhMyKeymint: injector.toml scoop and every config.toml [trust] key.

    It has the same features as upstream:

    • Target list with search, select all, deselect all and refresh.
    • Mode sheet on long press, and per-app policy.
    • Actions: select from DenyList (Magisk), deselect unnecessary apps (online list plus Xposed modules), add system apps, auto-add new apps.
    • Keyboxes from AOSP, generated "unknown", a local file, the keybox repository (the same iframe protocol) or custom providers (add, edit, remove, reset, import, export).
    • Prop handler and Verified Boot hash, schema-driven default policy with Today, help.
    • Keyboard shortcuts (Ctrl+A/D/F/S, Esc), the back gesture closing dialogs, and upstream's 23 translations, including right-to-left languages.
    • Optionally, a WebUI entry on the keystore module itself, and the TSupport-Advance auto-target stop flag.
  • RKP Workbench: Remote Key Provisioning.

    • Builds AuthenticatedRequest CSRs (DICE + COSE, per the AOSP IRemotelyProvisionedComponent HAL) and talks to the RKP server.
    • Verifies CSRs offline and exports keybox.xml, which the Tricky Store manager can install directly.
    • Device values are read from AOSP build properties.
  • Device ID Provisioner: writes attestation device IDs into the Qualcomm Keymaster trusted app through libQSEEComAPI.so, with a dry-run mode.

  • Module & updates: version and device summary, stable and canary updates with changelog, output files, command history, uninstall and reboot.

Every tool is translated into 14 languages: English, Simplified and Traditional Chinese, Japanese, Korean, Spanish, French, German, Italian, Brazilian Portuguese, Russian, Arabic, Vietnamese and Indonesian. Tricky Addon's other translations cover the strings the Tricky Store manager shares with it.

Architecture

crates/
  duck-core/          Shared runtime: paths, JSON envelope, Feature trait, command log,
                      and a Sysroot so every feature is testable off-device.
  duck-platform/      Device adapters: props/resetprop, pm, modules, root managers, HTTP.
  duck-rkp/           RKP workbench.            duck-device-ids/  Device ID provisioning.
  duck-tricky-store/  Keystore module manager.  duck-system/      Module lifecycle, updates.
  duckd/              The binary: builds its CLI from the compiled-in features.
xtask/                Repository checks (`cargo xtask line-limit`).
ui/src/
  app/                Shell: router, app bar, home and settings; discovers features.
  core/               Bridge to the root manager, validated duckd client, i18n, theme,
                      extension points and shared components.
  features/<id>/      One folder per tool: index.ts, api.ts (zod), locales/, pages, mock.ts.
  components/ui/      shadcn-vue components, restyled for Material 3 Expressive on phones.
module/               Module payload: scripts, then the built WebUI and backend binary.

What keeps it modular and resistant to breaking changes:

  • Features never import each other. Backend feature crates depend only on duck-core and duck-platform. WebUI features depend only on core/; ESLint (eslint-plugin-boundaries) rejects anything else, and only core/bridge may touch the KernelSU JavaScript API.
  • Extension points instead of imports. A feature contributes to others through contributes: keyboxTargets (RKP installs its keybox through the Tricky Store manager), settingsSections and homeWidgets.
  • Versioned contracts. Every command prints { ok, api, command, data, error, ts }. duckd features lists the compiled-in features and their contract versions; the WebUI disables a tool whose backend is missing or on another contract. It validates every response with zod, so a changed shape fails loudly as contract_mismatch.
  • Keystore modules are adapters. Each backend implements ConfigAdapter and describes its editable policy as a schema; the WebUI renders whatever the schema declares.
  • Mature tools, no home-grown frameworks.
    • Backend: clap, serde, tokio, reqwest, the RustCrypto crates, rcgen and toml_edit (which keeps comments).
    • WebUI: Vue 3, vue-router, Pinia, TanStack Query, vue-i18n, zod, Tailwind CSS 4 and shadcn-vue on reka-ui, with VueUse.
  • No source file over 600 lines. cargo xtask line-limit fails CI for any source file in any language, including scripts without an extension; ESLint's max-lines flags it while editing.
  • Dependency updates are reviewable. Dependabot groups minor and patch updates; every major update gets its own pull request and a full CI run.

Adding a tool

  1. Backend: create crates/duck-<name> with a clap subcommand enum and a pub static FEATURE: ClapFeature<Command> (see duck-system). Add it to duckd as an optional dependency and cargo feature, and one entry in the FEATURES array in crates/duckd/src/main.rs.
  2. WebUI: create ui/src/features/<id>/ with an index.ts exporting defineFeature({ id, namespace, icon, order, routes, messages }), an api.ts that calls duckd() with zod schemas, a locales/<language>.json for each of the 14 languages (src/locales.test.ts fails on a missing key), and optionally a mock.ts. The home page, router, i18n, availability check and dev mock pick it up automatically.

Module lifecycle

Stage What runs
customize.sh Checks the root manager, ABI and API level; prepares /data/adb/duck-toolbox; normalizes the boot hash; drops action.sh where the manager has a WebUI button; requests hot install from metamodules that support it.
post-fs-data.sh / late-load.sh Early pass of the sensitive-prop handler (resetprop -n, never setprop). KernelSU's late-load mode runs late-load.sh instead of post-fs-data.sh.
service.sh Repairs the runtime directory. On Magisk, which has no boot-completed stage, it waits for boot and runs boot-completed.sh.
boot-completed.sh Late prop pass, keystore-module entry links, auto-add of new apps, the module description (KernelSU temporary override.description), and the TSupport-Advance flag.
action.sh (Magisk) Opens the WebUI in KSUWebUIStandalone or WebUI X, installing KSUWebUIStandalone if neither is present.
uninstall.sh Removes entry links, flags, the boot hash and /data/adb/duck-toolbox.

Saved data lives in /data/adb/duck-toolbox/var, outside the module directory, so updates keep it.

Updates. The stable channel follows updateJson in module.prop. The canary channel reads the newest CI artifact through nightly.link: CI uploads the module directory as duck-toolbox-<version>-<commit count>-canary, and the commit count is its versionCode. Each successful package on a main push or manual CI run also publishes the module ZIP as a GitHub prerelease. Tags use nightly-<8-character commit hash>-<UTC timestamp> (for example, nightly-1234abcd-20261011T120000123456Z). These releases do not replace the latest stable release; Telegram uploads continue on push builds. The manual Stable workflow reuses the CI checks and builds, preserves version and versionCode from module/module.prop, publishes v<version> as the latest non-prerelease release, and sends the same ZIP to Telegram with a stable label. Before running it on main, increase versionCode beyond all accepted releases and update update.json to match the version and duck-toolbox-<version>.zip asset.

KernelSU Modules repository. The root module.yaml supplies the module listing metadata and selects duck-toolbox-*.zip release assets. Published ZIPs contain module.prop at their root; the current builds target Android API 26+ on arm64-v8a. The repository must enable release immutability and be registered through the KernelSU Modules developer portal. Nightly prereleases are checked and recorded but are not displayed as stable versions. Every new version must have a versionCode greater than all previously accepted stable and prerelease versions; nightly CI uses the commit count. Rebuilding the same commit creates another nightly release with the same versionCode, which is treated as the same prerelease version. A stable release needs a higher versionCode, or an accepted prerelease can be promoted by clearing its prerelease flag.

JSON CLI

duckd features | describe
duckd rkp profile show|save|clear|detect
duckd rkp info | provision | keybox | verify <file>
duckd device-ids defaults | provision
duckd tricky-store status | save | props | auto-apply
duckd tricky-store keybox install <file> | import | set-aosp | generate | fetch --url <u> [--decode <steps>]
duckd tricky-store keybox providers list | save | reset | import <file> | import-content | export [--path <file>]
duckd tricky-store apps xposed | denylist | unnecessary [--refresh]
duckd tricky-store entry status | enable | disable | apply | remove
duckd system info | update check|install [--channel stable|canary] | artifacts | files --path <dir> --extension <ext>
duckd system log [--limit <n>] | open-url <url> | uninstall | reboot

Commands that take input read JSON from stdin with --stdin-json.

Building and testing

Requirements:

  • Rust stable with the aarch64-linux-android target (rust-toolchain.toml installs it).
  • Android NDK r30.
  • Node.js 24 and pnpm 12 (corepack enable picks the version from ui/package.json). Type checking runs the TypeScript 7 engine through typescript-native-bridge, because stock TypeScript 7 no longer has the API vue-tsc needs.
cargo xtask line-limit
cargo fmt --all --check && cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace

# Device binary, e.g. with the NDK's clang as linker
cargo build --release --package duckd --target aarch64-linux-android

cd ui
pnpm install --frozen-lockfile
pnpm lint && pnpm format:check && pnpm test
pnpm build                 # type-check, then bundle into module/webroot
pnpm test:contract         # every API call through duckctl.sh and a host duckd build
pnpm test:e2e              # Playwright against a mock KernelSU host, with screenshots
pnpm dev                   # the same mock host in a desktop browser
pnpm locales:import <Tricky-Addon>/webui/public/locales/strings   # refresh translations

On Windows, pwsh ./scripts/build.ps1 -PackageModule builds everything with cargo-ndk and writes the module zip to dist/.

On a real KernelSU. scripts/device-test.sh <module zip> prepares a disposable userdebug emulator (or any device with root adbd) and runs ui/e2e-device there:

  • KernelSU is late-loaded with ksud late-load, so no boot image is patched.
  • The module and the Tricky Store, TEESimulator and OhMyKeymint releases are installed with ksud module install.
  • For each keystore module, only that one is enabled and the device reboots.
  • The tests drive the WebUI inside the KernelSU manager through Playwright's Android support. They read the files back over adb, and check each daemon's own log to confirm it accepted what the WebUI wrote.

Acknowledgements

  • The Tricky Store manager, its translations and the keybox repository protocol come from KOWX712's Tricky Addon: Update Target List (Apache-2.0).
  • The bundled software keybox is AOSP's reference attestation key (system/keymaster/contexts/soft_attestation_cert.cpp).

历史版本

0.1.2-stable

最新

版本代码 58 v0.1.2-stable

下载

Changelog

0.1.2-stable - 2026-10-11

Tricky Store manager

  • Complete port of Tricky Addon (Update Target List):
    • Target list with modes, per-app policy, search, bulk selection, DenyList, unnecessary
      apps, system apps and auto-add.
    • Keyboxes from AOSP, "unknown", a local file, the keybox repository and custom providers,
      with import and export.
    • Prop settings, default policy with Today, help, keyboard shortcuts and its 23
      translations, including right-to-left languages.
  • One manager for Tricky Store (config.ini and legacy target.txt), TEESimulator
    (config.json) and OhMyKeymint (config.toml + injector.toml).
    • The validation rules follow each module's own sources.
    • Unknown sections, comments and keys are preserved.
  • Optional WebUI entry on the keystore module (plus the action button on Magisk), and the
    TSupport-Advance auto-target stop flag.
  • Tricky Addon's in-app translation update, translation guide and Telegram link.
  • Checked against the real modules on a KernelSU device, which found and fixed:
    • OhMyKeymint v1.2.0 rejected our injector.toml (an unknown version key) while the
      WebUI reported success. [scoop.<package>] tables are now read and written like
      OhMyKeymint's own parser does.
    • The "unknown" keybox now gives each key a two-certificate chain. Tricky Addon's
      single-certificate keybox only loads on Tricky Store: TEESimulator and OhMyKeymint
      refuse it.
    • TEESimulator accepts EC-only keyboxes, such as the RKP workbench exports.
    • Saving tells when OhMyKeymint needs a restart to apply a change.

WebUI

  • Rebuilt on Vue 3.5, Vite 8, Tailwind CSS 4 and shadcn-vue.
    • A black and white theme, light or dark, where color only marks errors, success and
      warnings.
    • Designed for phones along Material 3 Expressive:
      • 48dp touch targets and a visible response to every press.
      • Round buttons that square up while pressed, segmented lists, and spring motion.
      • A large title that collapses into the 64dp app bar, for one-handed reach.
      • Tonal gray surfaces instead of borders and shadows, with contrast checked
        against WCAG.
    • Menus, tabs and button groups mirror in right-to-left languages too.
    • Follows the KernelSU manager's window insets.
    • The Android back gesture closes dialogs and sheets.
  • Every tool in 14 languages: English, Simplified and Traditional Chinese, Japanese, Korean,
    Spanish, French, German, Italian, Brazilian Portuguese, Russian, Arabic, Vietnamese and
    Indonesian.
  • Help: long links and code wrap inside the page, and two slips in upstream translations
    (a link missing its parenthesis, a code span closed with a quote) no longer show raw
    Markdown.
  • Every tool is a self-contained feature folder, discovered automatically.
    • Features plug into each other only through extension points.
    • Every backend response is validated against a schema.
  • A tool whose backend feature is missing or on another contract version is disabled
    instead of misreading data.
  • Unit tests (Vitest) and end-to-end tests (Playwright against a mock KernelSU host) with
    light, dark, right-to-left and Chinese screenshots.
  • Contract tests run every API call through duckctl.sh and a real duckd build and
    parse the results with the WebUI's schemas.
  • Device tests (scripts/device-test.sh) drive the WebUI inside the real KernelSU manager
    with each keystore module installed.
  • Loads as seven files instead of about eighty. The KernelSU manager reads each request
    through a root shell, so this halved the load time on a slow device.
  • Type-checked on the TypeScript 7 engine through typescript-native-bridge.

Backend

  • duckd builds its CLI from a feature registry. duckd features reports the compiled-in
    features, and each feature can be built alone.
  • New system feature: module and device summary, stable and canary updates with changelog,
    output files, command history, uninstall and reboot.
  • RKP profiles read their device defaults from AOSP build properties.
  • Updated RustCrypto to its current generation (p256/p384 0.14, ed25519/x25519 3, aes-gcm
    0.11, x509-cert 0.3). Keys derived from saved seeds are pinned by regression tests.

Module

  • Scripts follow the KernelSU module guide:
    • Late-load support (late-load.sh).
    • A late prop pass after boot for values the system sets late.
    • The module description goes into KernelSU's temporary config.
  • Magisk runs the boot-completed work from service.sh.
  • The prop handler adds ro.boot.vbmeta.size, and applies the boot hash even when the
    handler is disabled, as upstream does.
  • Uninstalling removes entry links, flags and saved data.

Tooling

  • CI fails when any source file in any language exceeds 600 lines.
  • CI: NDK r30, Node 24, pnpm 12, WebUI lint/format/unit/E2E, per-feature builds.
  • Canary artifacts are the installable module directory.
  • Dependabot opens one pull request per major update.

文件 1

duck-toolbox-0.1.2-stable.zip 3.8 MiB

SHA-256 173fb3686745cf2975017abccda37225317fa10f4fdd375a2af46d162766c2ff · Attestation

透明度

Tag
v0.1.2-stable 不可变 Release
Tag commit
c573b6fa74a1
内容 commit
c573b6fa74a1
SHA-256
173fb3686745cf2975017abccda37225317fa10f4fdd375a2af46d162766c2ff
最近同步到变更

自行复核

KernelSU 模块不对模块签名,也不审计模块代码。SHA-256 只证明下载内容与本索引一致。可使用 GitHub CLI 自行复核:

gh release verify v0.1.2-stable -R eltavine/Duck-ToolBox
gh release verify-asset v0.1.2-stable duck-toolbox-0.1.2-stable.zip -R eltavine/Duck-ToolBox