惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
F
Fortinet All Blogs
博客园_首页
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏
爱范儿
爱范儿
B
Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
D
Docker
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog
罗磊的独立博客
云风的 BLOG
云风的 BLOG
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
博客园 - 三生石上(FineUI控件)
量子位
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Blog of Author Tim Ferriss
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
Cloudbric
Cloudbric
博客园 - 司徒正美
H
Help Net Security
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
L
LangChain Blog
Latest news
Latest news
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
博客园 - Franky
S
Security Affairs
W
WeLiveSecurity
F
Full Disclosure
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News
The Hacker News
The Hacker News
Cyberwarzone
Cyberwarzone
美团技术团队
PCI Perspectives
PCI Perspectives
C
Check Point Blog
Spread Privacy
Spread Privacy

Show HN

GitHub - steveking-gh/firmion: Firmion is DSL and engine for firmware image generation. GitHub - villagesql/villagesql-skills: Agent skills for VillageSQL - gemini-cli-extension; claude-code-plugin GitHub - flightdeckhq/flightdeck: Observability and control plane for AI agents. CSP Radar GitHub - Light-Heart-Labs/DreamServer: Turn your PC, Mac, or Linux box into an AI server. LLM inference, chat UI, voice, agents, workflows, RAG, and image generation. GitHub - Diplomat-ai/diplomat-agent-ts: What can your TypeScript AI agent do to the real world? Scan your code. See which tool calls have zero checks Code Block Selector - Visual Studio Marketplace Prometheus dependency graph — interactive showcase | Riftmap Show HN: I made a vi-like modal keyboard plugin for Figma GitHub - run-llama/liteparse: A fast, helpful, and open-source document parser GitHub - dalemyers/Roar: A macOS CLI tool for notifications GitHub - district-solutions/open-agent-tools-coder: Enables small-to-large self-hosted ai models to use local source code when running tool-calling agentic workloads. We actively data mine 20,900+ (2+ TB) popular github repos using large and small ai models to create reuseable: json, markdown and parquet files for local-first tool-calling models. GitHub - progapandist/stripeek: A local TUI proxy for real-time Stripe API debugging, built for navigating complex payloads fast. GitHub - sir1st/hermes-desktop: All-in-one cross-platform desktop app for Hermes Agent — bundles Python + hermes-agent + hermes-web-ui GitHub - astefanutti/shaderbang: Shebang for Shaders Show HN: Generate Claude Code Workflows using Spec Driven Development approach GitHub - nixys/nxs-universal-chart: The Helm chart you can use to install any of your applications into Kubernetes/OpenShift Show HN: AI agents for UK GDAD PCF roles and their skills The Two Pillars: Mixer Mode and Meta-Software in the Reorganization of Software Work After AI GitHub - JaiCode08/teleport-env What 1,000+ Harness Experiments Taught Me About Self-Improving Agents Show HN: Liiists, a Markdown-first, iOS and CLI list app SwiperTab – Get this Extension for 🦊 Firefox (en-US) GitHub - kouhxp/fftext: Summarize, explain, fact-check, or translate any text, URL, or file. No GPU. No cloud. One command GitHub - sweetpad-dev/sweetpad: Develop Swift/iOS projects using VSCode GitHub - dogmaticdev/IRON: IRON a.k.a. Intermediate Representation Object Notation is a Interpreter/Database that is used to create Programming Languages. GitHub - sjhalani7/vaen: Package your AI coding harness into a portable .agent file, and share it across repos, teams, & the community without ever having to copy-paste instructions, skills, MCP config, or secrets. Show HN: Gandalf the Grader Show HN: Citadeld – replay any CI failure locally from a single file GitHub - tdortman/cuSBF: High-Performance GPU Super Bloom Filter coral-ai/claude-code-token-xray at main · Coral-Bricks-AI/coral-ai GitHub - ulyssestenn/funes: Funes is a Git-based framework for LLM-managed knowledge work: an AI Librarian ingests raw sources, builds an interlinked Markdown knowledge base, and uses it to produce cited reports, analyses, and other outputs. GitHub - ThatXliner/gah: Git Add Hunk, built for agents to use GitHub - harmont-dev/harmont-cli: Command-line client for the Harmont CI platform GitHub - brooksmcmillin/mcp-authflow: OAuth 2.0 Authorization Server framework for MCP servers GitHub - javaid-codes/audit-supply-chain-agents GitHub - amorey/gochan: A small library of common channel architectures for Go, inspired by Rust GitHub - arifozgun/OpenGem: Free, Open-Source AI API Gateway with Gemini, OpenAI & Anthropic Compatibility in 1 file GitHub - Pranesh950/BioPetals: 🌸 Run BIOxAI models at home, BitTorrent-style. Fine-tuning and inference up to 10x faster than offloading GitHub - cnguyen14/bounty-doctor: Diagnose a GitHub bounty issue before you waste hours: detects honeypot scam repos, AI-bot attempt swarms, and stale contests. Show HN: CoreMCP – MCP Server for On-Prem DBs Show HN: KittyHTML – Render HTML/CSS as an inline image in your terminal GitHub - bingud/filemat: Web-based file manager Show HN: TruthLens – Free multi-signal deepfake image detector GitHub - apexlocal-jz/claude-usage-tray: Windows system-tray app showing your Claude Code rate-limit usage at a glance. Zero deps, ~300 lines of PowerShell. Cross-IDE (works regardless of VS Code, Cursor, plain terminal). Release v0.1.2.1 · kouhxp/yapsnap GitHub - noopolis/moltnet: Self-hostable chat network for AI agents. Pre-built bridges for Claude Code, Codex, and the Claws. Rooms, DMs, history. No Slack bots, no Matrix, no glue code. GitHub - tamerh/enju: Coordinating Humans, AI Agents, and Compute as Peers on a Shared Workflow Graph Show HN: Continuity-auth – Respect-weighted rate limits for the open web GitHub - luml-ai/luml: AI lifecycle platform where engineers and agents track experiments, train models, and ship to production. GitHub - mrdanielcasper/CoreTex: A UNIX-inspired, biomimetic, flat-file AI harness and knowledge engine. GitHub - clemg/pierre-github: Pierre's diffs.com and trees.software for Github GitHub - lyriks-io/unspaghettit: Behavior-driven AI development without prompt spaghetti. GitHub - sofumel/claude-handoff-revive: Resume Claude Code work after rate/usage/context limits without replaying the prior transcript. Auto-saves at 90%/95% usage. Plugin-installable, 10 languages. GitHub - dotexorg/saferpc: Typed, end-to-end encrypted RPC over any bidirectional channel. GitHub - BeeZeeAgent/beezee: Agent harness orchestration Legato Next.js Boilerplate for Internal Tools · CoreUI GitHub - clark-labs-inc/clark-hash: Clark Hash, 32x smaller searchable sketches for embeddings GitHub - ZeroPointRepo/youtube-mcp: The fastest YouTube transcript + YouTube search MCP for AI agents. Try for free. Typing Mastery — climb toward 100+ WPM, deliberately GitHub - Andebugulin/Awareen GitHub - fayzan123/claude-workflow-composer: Visual desktop app for composing multi-agent coding workflows. Drag agents, attach skills and MCPs, wire handoffs, export to .claude/ GitHub - harshaneel/humanize: Best static AI text humanizer. Two research-grounded skills that work in any LLM (Claude, ChatGPT, Gemini, Codex): humanize beats perplexity-based detectors, ai-check produces forensic scoring with evidence-quoted flags. Nine levers, 50+ peer-reviewed sources, 2024-2026 detection literature. GitHub - StackOneHQ/stack-nudge GitHub - nodes-app/swift-markdown-engine: A native AppKit Markdown editor for macOS, built on TextKit 2 and bridged to SwiftUI. We hardened an LLM agent. Each defense we added made it more exploitable. GitHub - alkait/WhatsKept: Agent-queryable WhatsApp history from an iOS backup — a single Go binary. GitHub - octelium/cordium: Open-source, general-purpose sandbox platform for devs and AI agents that provides identity-based secure access to infrastructure without credentials. WAR.GOV/UFO Microfilm5 GitHub - scosman/videowright: Build animated explainer videos with your coding agent GitHub - dipankar/dscode: The code editor you can take apart. GitHub - zoharbabin/web-researcher-mcp: MCP server (Go) for AI assistants: web search, content extraction, academic/patent/news research. Multi-provider routing, 4-tier scraping, search lenses. Works with Claude, Cursor, and any MCP client. GitHub - ruvnet/RuView: π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video. GitHub - scanaislop/aislop: Catch the slop AI coding agents leave in your code: narrative comments, swallowed exceptions, as-any casts, dead code, oversized functions. 50+ rules across 7 languages (TypeScript, JavaScript, Python, Go, Rust, Ruby, PHP). Sub-second, deterministic, no LLM at runtime. MIT-licensed. GitHub - kouhxp/cheap-im: CPU-only voice agent approximating Thinking Machines' Interaction Models demo GitHub - unprovable/OrchidMantis: Orchid Mantis — standalone framework for Zero-Knowledge Proofs of eXploit (ZKPoX). GitHub - MarcellM01/TinySearch: Shrink the web for your local LLMs! GitHub - TangibleResearch/Halgorithem: A Algo designed to detect AI Hallucitions GitHub - DO-SAY-GO/freelang: I love freelang GitHub - CarpseDeam/Aura-IDE: An AI coding harness that shaped itself - Planner/Worker agents, repo awareness, surgical edits, validation, recovery, and safe diff approvals. GitHub - chojs23/concord: A feature-rich TUI client for Discord GitHub - tommyjepsen/awesome-ux-skills: UX & AI Product designs skills you can use today in Claude Code GitHub - aerf-spec/aerf: Agent Evidence Receipt Format (AERF) — an open specification for tamper-evident, independently verifiable records of AI agent actions. GitHub - kklimuk/docx-cli: CLI for AI agents (Claude, Codex) to read, edit, and comment on .docx files with full format fidelity. GitHub - Jwrede/tokentoll: Catch LLM cost changes in code review. Infracost for LLM spend. GitHub - samchon/ttsc: A `typescript-go` toolchain for compiler-powered plugins and type-safe execution + 500x faster lint integrated into compiler GitHub - Higangssh/homebutler: 🏠 Manage your homelab from chat. Single binary, zero dependencies. GitHub - olalie/tapmap: See where your computer connects and what stands out on a live world map. GitHub - Diplomat-ai/diplomat-agent: What can your AI agent do to the real world? Scan your code. See which tool calls have zero checks GitHub - Bajusz15/beacon: Open-source agent for secure remote access, monitoring, and deploys across home-lab and self-hosted machines like Raspberry Pi, N100, or any Linux server. Open web based TTY or tunnel Home Assistant and other local services securely without opening ports. BigTech AI News - Chrome 应用商店 GitHub - vinhnx/VTCode: VT Code is an open-source coding agent with LLM-native code understanding and robust shell safety. Supports multiple LLM providers with automatic failover and efficient context management. GitHub - michaelaz774/decision-engine: A decision operating system for startup founders, powered by Claude Code. Synthesizes wisdom from 25+ legendary founders and investors into interactive AI-driven decision frameworks. GitHub - Chrilleweb/dotenv-diff: Validate environment variable usage in your codebase GitHub - Lumen-Labs/brainapi2: BrainAPI is a knowledge graph–powered AI memory layer that transforms unstructured data into structured knowledge, enabling intelligent search, recommendations, and contextual memory for AI agents and applications. GitHub - familiar-software/familiar: Let AI watch you work. Familiar lets your AI update its memory, skills, and knowledge by watching your screen. GitHub - skorotkiewicz/rudo: A small, elegant dock for Wayland GitHub - muxshed/shed: One stream in, or many. Every destination, simultaneously. No cloud middleman, no per-channel fees, no limits. make sidebar/address bar rounded corner toggleable
GitHub - datalocaltmp/Peepo: watchOS kernel R/W + live process memory dumping on Apple Watch Series 4 (watchOS 10.6.2 - latest). Named after the children's book Peepo!
datalocaltmp · 2026-06-24 · via Show HN

Here's a little baby - One, two, three - Sits in her high chair - What does she see? PEEPO!

Named after the children's book Peepo!. App artwork done by my niece H. McLaren.

⚠️ Read Compatibility before running. Confirmed on the Apple Watch Series 4 (Watch4,1) on watchOS 10.6.1 and 10.6.2 (the latest); the Series 5 and SE 1st gen share the same T8006 kernel and should work too. On any unsupported model or watchOS version it will panic/reboot the device - the exploit and offsets are hardcoded to the xnu-10063.144.1 kernel build, so confirm yours is in the matrix first.

Peepo exploits the darksword kernel bug to gain arbitrary kernel read/write on an Apple Watch Series 4 (Watch4,1 / T8006 / watchOS 10.6.1 or 10.6.2 / xnu-10063.144.1, arm64_32 userland), then uses that primitive to enumerate live processes and dump another process's memory to the app container - viewable on-watch or pullable to a host.

Peepo / DATASWORD demo


Table of contents

  • Compatibility
  • What it does
  • Setup (run it on your own watch)
  • On-watch UI
  • Pulling dumps off the watch ← file extraction
  • Dump file format & MachO extraction
  • How it works
  • Key offsets & constants
  • Build & deploy
  • Source map

Compatibility

Support is tied to the T8006 kernel build (xnu-10063.144.1, kernel UUID 00DD9EAB-9ABB-345E-B9AA-3E1F40538764), not the device alone. watchOS 10.6.1 and 10.6.2 ship that byte-identical kernel, and 10.6.2 is the final watchOS for every device below - so a fully-updated supported watch is covered.

Device SoC watchOS Status
Series 4 (Watch4,1) T8006 10.6.1 Confirmed on-device - primary target
Series 4 (Watch4,1) T8006 10.6.2 Confirmed on-device
Series 5 (Watch5,1-5,4) T8006 10.6.1 / 10.6.2 🟡 Should work - same kernel build & struct offsets (untested on hardware)
SE 1st gen (Watch5,9-5,12) T8006 10.6.1 / 10.6.2 🟡 Should work - ships the identical kernelcache to Series 5 (untested on hardware)

Why Series 5 / SE 1st gen should work: all three are the same T8006 chip. The Series 5 and SE-1st-gen kernelcaches are byte-identical to each other, and their kernel is the same build as Series 4 (identical UUID ⇒ identical struct offsets)

  • just relocated into a different kernelcache, which doesn't change the offsets Peepo hardcodes. The one unverified risk on those models is the dumper's hardcoded readable-physmap window (depends on the device's physical DRAM layout); the kernel R/W exploit and process enumeration should be unaffected. SE 2nd gen is a different SoC (S8/T8301) and will not work - don't confuse the two.

What it does

DATASWORD ──► darksword_run()  ──►  "=== WIN ==="  (kernel R/W + base/slide)
                                         │
                                         ▼
                                  PROCESS DUMP screen
                                         │
                  ┌──────────────────────┼───────────────────────┐
                  ▼                       ▼                        ▼
          peepo_list_processes    tap a process →          VIEW HEX (on-watch
          (kernel proc walk)      peepo_dump_process()     xxd of the dump)
                                  → <name>_<pid>.bin

Confirmed working: full kernel R/W, ~276-process enumeration, and complete memory dumps of live processes.


Setup (run it on your own watch)

This targets the T8006 watches (Series 4 confirmed; Series 5 / SE 1st gen expected) on watchOS 10.6.1 or 10.6.2 - see Compatibility for the matrix and confidence levels. Both builds ship the identical kernel, so the offsets work on either. On an unsupported model or OS version the hardcoded offsets are wrong and it will panic and reboot rather than fail cleanly. watchOS is OTA-only, but since 10.6.2 is the latest and works, a supported watch on an older build can simply update to 10.6.2.

0. Check compatibility first

On the watch: Settings → General → About - confirm your Model is in the Compatibility matrix (Watch4,1 is confirmed; Watch5,x is expected) and watchOS Version = 10.6.1 or 10.6.2. If the model isn't listed, stop here; if you're on an older watchOS, update to 10.6.2 first.

1. Prerequisites

  • A Mac with Xcode (the watchOS SDK + devicectl).
  • An Apple Developer account signed into Xcode. A free "Personal Team" works for running on your own watch (see Signing & account notes).
  • An iPhone paired to the watch, both with Developer Mode enabled (Settings → Privacy & Security → Developer Mode), and the watch trusted by Xcode for development.

2. Make it yours

The committed project is intentionally teamless - set signing to your own account. Open Peepo.xcodeproj in Xcode and, for both the app and the Watch App target (Signing & Capabilities):

  1. Signing Team - select your team; let Xcode manage signing automatically.
  2. Bundle identifier - change com.datalocaltmp.Peepo* to your own if Xcode can't register the existing one under your team (e.g. com.<you>.Peepo).
  3. HealthKit (Workout Processing) - leave this capability enabled. The app starts a HealthKit workout session purely to stay alive (avoid suspension) during the run, and WKBackgroundModes = workout-processing depends on it.

Then grab your watch's UDID for the command line:

xcrun devicectl list devices         # copy your watch's identifier

Use it wherever the docs say DEV=… (the repo's value is a placeholder).

3. Signing & account notes

  • A free account is enough. A free "Personal Team" (just an Apple ID added in Xcode → Settings → Accounts) can sign and run this on your own watch, HealthKit included - this project was built/run on one.
  • If signing fails on the HealthKit entitlement (rare, account-dependent): as a fallback you can strip WorkoutManager, the com.apple.developer.healthkit entitlement, and the workout-processing background mode - the app then runs without HealthKit but may get suspended mid-run.
  • Find your Team ID (for the CLI DEVELOPMENT_TEAM=…): Xcode → Settings → Accounts → your team → 10-char ID, or run security find-identity -v.

4. Build, install, run

See Build & deploy for exact commands. In short: build, devicectl … install, launch, tap DATASWORD, wait for === WIN ===.

5. Expect reboots

The R/W primitive is one-shot per launch, and force-quitting or reinstalling the app usually panics + reboots the watch - that's normal here; it recovers. Dumping an incompatible page also panics. None of this is persistent.


On-watch UI

Home screen

  • DATASWORD - runs the exploit; streams a live console; ends at === WIN ===.
  • 📄 list dumps - lists every *.bin dump in the app container with sizes.
  • 🗑 delete dumps - deletes all *.bin files to free space (incl. kc.bin).

After WIN (PROCESS DUMP screen)

  • Console of the exploit log, with a floating PROCESS DUMP button.
  • Tapping it opens the process list (name-only rows). Tap a process to dump it → <name>_<pid>.bin in the app's Documents/.
  • After a dump, VIEW HEX ▸ appears - an on-watch xxd view (offset · hex · ASCII, first 64 KB) with an to close. No host needed.

Pulling dumps off the watch

Dumps are written to the app's Documents container. Use Apple's devicectl (ships with Xcode). Two constants:

DEV=<YOUR-WATCH-UDID>          # the Apple Watch (devicectl list devices)
BUNDLE=com.datalocaltmp.Peepo.watchkitapp         # the app's bundle id

1. List what's in the container

xcrun devicectl device info files \
  --device "$DEV" \
  --domain-type appDataContainer \
  --domain-identifier "$BUNDLE" \
  --subdirectory Documents

Example output:

Name                       Size       Modification date
LegacyProfilesSu_325.bin   236.9 MB   ...
MTLCompilerServi_248.bin   250.5 MB   ...
kc.bin                     41.3 MB    ...   # kernelcache dump (if taken)
dumpdbg.log                10 KB      ...   # only present when DUMP_DEBUG=1

⚠️ This listing times out while the app is actively running (darksword holds kernel R/W and starves the file service over the tunnel). Run it when the app is not running - e.g. right after a reboot, or before relaunching. Single-file copies (below) work even while the app runs.

2. Pull a file

xcrun devicectl device copy from \
  --device "$DEV" \
  --domain-type appDataContainer \
  --domain-identifier "$BUNDLE" \
  --source Documents/LegacyProfilesSu_325.bin \
  --destination ./LegacyProfilesSu_325.bin

3. Pull the whole Documents directory

mkdir -p ./peepo_docs
xcrun devicectl device copy from --device "$DEV" \
  --domain-type appDataContainer --domain-identifier "$BUNDLE" \
  --source Documents --destination ./peepo_docs

(Same caveat: do it while the app isn't running, or it may time out.)

File naming

Dump files are named <last-16-chars-of-process-name>_<pid>.bin (non-alnum chars → _). The process name (not the truncated display) drives the filename, and pids change every boot, so always list first rather than guessing. Other files you may see:

File What When
<name>_<pid>.bin a process memory dump after PROCESS DUMP
kc.bin live kernelcache dump if the (currently hidden) DUMP KERNEL path is used
dumpdbg.log durable, panic-surviving step/PT-walk trace only when DUMP_DEBUG=1

Dump file format & MachO extraction

A .bin dump is a flat sequence of fixed records, one per mapped 16 KB page (unmapped/un-resident pages are skipped):

record = [ u64 little-endian virtual address ][ 16384 bytes of page data ]
record size = 8 + 0x4000 = 16392 bytes

Only resident pages are captured (demand-paged code that was never executed translates to PA 0 and is skipped), and only pages inside the readable physmap window are read. The dump is capped at 1 GB per process.

Because VAs are preserved, you can recover MachO images (the main executable and resident dyld-shared-cache slices) by scanning for the mach header magic. Quick host-side parser/extractor:

import struct, sys

REC = 8 + 0x4000
data = open(sys.argv[1], "rb").read()
n = len(data) // REC
print(f"{len(data)} bytes, {n} pages")

for i in range(n):
    off = i * REC
    va  = struct.unpack_from("<Q", data, off)[0]
    page = data[off+8 : off+8+0x4000]
    if page[:4] in (b"\xcf\xfa\xed\xfe", b"\xca\xfe\xba\xbe"):  # MH_MAGIC_64 / FAT
        print(f"  MachO @ va {va:#x}")
        # carve: open(f"img_{va:x}.bin","wb").write(<contiguous pages from va>)

(cf fa ed fe = little-endian MH_MAGIC_64.) On-watch, the same data is viewable directly via VIEW HEX without pulling anything.


How it works

1. darksword - kernel R/W

A physical-use-after-free (PUAF) attack that races pwritev()'s copy against a mach_vm_map(… OVERWRITE …) page remap.

  • pcObject is allocated from PurpleGfxMem (GPU device memory) via IOSurfaceCreate({IOSurfaceMemoryRegion: "PurpleGfxMem"}). These pages are device memory, not managed DRAM, so the kernel's physical-copy path does not trip the pmap_map_cpu_windows_copy_internal: attempted to map a managed page panic (guarded by pa_valid()). This was the key watch-port fix.
  • free_thread remaps pcAddress with one atomic mach_vm_map(VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, …).
  • "Race landed" = pwritev returns -1 (EFAULT) plus a randomMarker sentinel mismatch: search pages are pre-filled with randomMarker; a page reclaimed by the kernel as a socket inpcb reads back kernel data instead.
  • pe_v1 sprays ~22k ICMPv6 sockets to reclaim freed pages, finds an inpcb of ours, and corrupts its in6p_icmp6filt pointer → a 0x20-byte arbitrary kernel R/W via get/setsockopt(ICMP6_FILTER) (early_kread64/early_kwrite).

Base + slide: controlSocketPcb → socket → so_proto → pr_input leaks a PAC-signed kernel text pointer. The watch's __xpaci is a no-op, so strip explicitly - the PAC sits in the top 32 bits, real text is the low 32: textPtr = (raw & 0xffffffff) | (protoPtr & 0xffffffff00000000). Scan down 16 KB pages for the MH_FILESET mach header → kernel_base; kernel_slide = kernel_base - 0xfffffff007004000.

STEP 6 bumps both sockets' so_count ("leak forever") so the R/W stays valid for the inspection code after the run.

2. Process enumeration

Userland enumeration is sandbox-blocked, so we walk the kernel proc list.

The anchor is obtained offset-free via leak_current_proc(): spray ~10-20k kqueue() fds (each kqfile stores kq_p = current_proc), read the reclaimed pages back through the physical-read race while free_thread is alive, and take the kernel pointer that repeats across the page. From current_proc, walk proc.p_list both directions; the proc-name field offset is self-calibrated at runtime by searching the struct for our own executable name.

3. Process memory dump

peepo_dump_process(proc, name) walks proc → task → vm_map → pmap, then for each vm_map entry translates every 16 KB page and writes it out.

  • task = proc + 0x740; map = strip(*(task+0x28)); pmap = strip(*(map+0x40)) (vm_map->pmap is PAC-signed, data key A, discriminator 0x250c).
  • 3-level 16 KB page-table walk (39-bit user VA): L1 (8-entry root) → L2 (2048) → L3 (2048): l1i=(va>>36)&7, l2i=(va>>25)&0x7ff, l3i=(va>>14)&0x7ff.
  • Physmap slide is global: derived from our own validated process's pmap (physmap_off = tte - ttep), not the target's (a target's ttep can be inconsistent). physmap_kva = pa + physmap_off.
  • PAC strip forces bit 39: (v & 0x7fffffffff) | 0xffffff8000000000 - the central bug that, when missing, mangled every signed pointer.

The carveout gate. early_kread is fault-unsafe - reading a physical page not covered by the physmap panics (reboots the watch). Live traces showed the low DRAM carveout (iBoot/SEP/TZ, 0x8_00000000 .. gPhysBase) is not in the physmap: pages at 0x801…/0x802… panic, while gPhysBase ≤ 0x8_06e68cc0 reads fine. So the dumper gates reads to a safe window [0x8_07000000, 0x8_40000000) and skips anything outside it. (TODO: read the kernel's exact gPhysBase/gPhysSize to close the small gap below the gate.)

Panicking runs are diagnosable only with DUMP_DEBUG=1, which mirrors every step to dumpdbg.log using F_FULLFSYNC (plain fsync does not survive a kernel panic on this device - the FS cache is effectively volatile across a panic).


Key offsets & constants (watchOS 10.6.1 / 10.6.2 / T8006)

Thing Value Notes
unslid kernel base 0xfffffff007004000 for kernel_slide
proc.p_list.le_next / le_prev +0x0 / +0x8 proc list walk
proc.p_pid +0x60
proc → task gap (proc_struct_size) 0x740 validated on this build (kfd's 0x778 was wrong here)
task->map +0x28
vm_map->pmap +0x40 PAC-signed (data key A, disc 0x250c)
pmap->tte / pmap->ttep +0x0 / +0x8 virtual / physical root TT
proc name field self-calibrated (gNameOff) searches struct for exe name
PAGE_SIZE 0x4000 (16 KB) DS_PAGE_SHIFT = 14
readable physmap window [0x807000000, 0x840000000) DRAM minus low carveout
dump cap 1 GB / process

All offsets were validated against the live kernel (the on-device kernelcache is the source of truth for this build, not a generic reference). A kernelcache dump (kc.bin) can be taken for cross-checking with blacktop/ipsw.


Build & deploy

watchOS app, target/scheme Peepo Watch App, builds for arm64_32.

The committed project has no signing team (scrubbed). Either open it in Xcode once and pick your team under Signing & Capabilities, or pass your Team ID on the command line (xcrun devicectl list devices gives your watch UDID; your Team ID is in Xcode → Settings → Accounts, or security find-identity -v).

DEV=<YOUR-WATCH-UDID>
TEAM=<YOUR-TEAM-ID>
BUNDLE=com.datalocaltmp.Peepo.watchkitapp
APP="$HOME/Library/Developer/Xcode/DerivedData/Peepo-*/Build/Products/Debug-watchos/Peepo Watch App.app"

xcodebuild -scheme "Peepo Watch App" -destination "generic/platform=watchOS" \
  DEVELOPMENT_TEAM="$TEAM" build
xcrun devicectl device install app --device "$DEV" $APP
xcrun devicectl device process launch --device "$DEV" "$BUNDLE"

Conventions / gotchas:

  • Rotate buildTag (4-char hex in ContentView.swift) before every redeploy so the running build is visually confirmable on-watch.
  • Force-quit Peepo before reinstalling. While the app runs it holds kernel R/W; install then times out (NSPOSIXErrorDomain 60 / IXRemoteErrorDomain 6). Force-quitting (or any reinstall) usually panics + reboots the watch - that's expected; it recovers.
  • The R/W primitive is one-shot per app launch (no persistence).
  • DUMP_DEBUG (in darksword.m) defaults to 0 (lean dumps). Set to 1 to get the durable dumpdbg.log panic trace back while debugging.

Troubleshooting

Symptom Cause / fix
Signing for "…" requires a development team No team set. Pick yours in Xcode → Signing & Capabilities, or pass DEVELOPMENT_TEAM=<id> to xcodebuild.
Build fails on the HealthKit entitlement Rare/account-dependent - see the fallback (strip HealthKit) in Signing & account notes.
install times out (NSPOSIXErrorDomain 60 / IXRemoteErrorDomain 6) The app is running and holding kernel R/W. Force-quit Peepo on the watch, then reinstall.
Watch panics/reboots on launch or on a dump Almost always the wrong device/OS (must be a T8006 watch @ 10.6.1 or 10.6.2 - see Compatibility), or a dump hit memory outside the readable physmap. Expected; it recovers.
devicectl device info files (listing dumps) times out The app is running. List after a reboot / before relaunching; single-file copy from still works while running.
App quietly dies mid-run Workout session didn't keep it alive - confirm the HealthKit/Workout capability is enabled and granted.

Source map

File Role
Peepo Watch App/darksword.m exploit + kernel R/W + proc walk + process dump + PT walk
Peepo Watch App/darksword.h public API (darksword_run, peepo_list_processes, peepo_dump_process, peepo_last_dump_path, …)
Peepo Watch App/ContentView.swift UI: home, console, PROCESS DUMP, process list, hex viewer, list/delete dumps, build tag
Peepo Watch App/ConsoleView.swift / ConsoleBridge.swift / ConsoleBuffer.swift on-watch console + console_log bridge
Peepo Watch App/kern_panic.c / .h console-logging plumbing (printf → console)
Peepo Watch App/WorkoutManager.swift keeps the app alive (HealthKit workout session) during the run

Credits & shout-outs

  • opa334 and htimesnine - for the darksword kernel n-day this project is built on. None of this exists without their work.
  • tihmstar - for jelbrekTime, the Apple Watch Series 3 jailbreak, and a great reference for watchOS exploitation.