diff --git a/dwt/evidence/real-unit-xhello.png b/dwt/evidence/real-unit-xhello.png new file mode 100644 index 0000000..078e4dd Binary files /dev/null and b/dwt/evidence/real-unit-xhello.png differ diff --git a/dwt/loader/hostload.py b/dwt/loader/hostload.py index b5b4fb4..608968c 100644 --- a/dwt/loader/hostload.py +++ b/dwt/loader/hostload.py @@ -249,13 +249,17 @@ def describe_pointer(ptr: int, nbytes: int) -> str: # --------------------------------------------------------------------------- def screenshot_vram(rd: exploit.RDebug, out_png: str, - out_raw: str | None = None) -> bytes: - """Grab the 1024x1024 VRAM canvas using dwt/screenshot.py primitives.""" + out_raw: str | None = None, real: bool = False) -> bytes: + """Grab the VRAM canvas using dwt/screenshot.py primitives.""" import screenshot # imported here so marker-only runs need no PNG path - data = screenshot.grab(rd, 0, screenshot.HEIGHT, True) - gray = screenshot.decode(data) - screenshot.write_png(out_png, screenshot.WIDTH, screenshot.HEIGHT, gray) + if real: + width, stride = screenshot.REAL_WIDTH, screenshot.REAL_STRIDE + else: + width, stride = screenshot.WIDTH_DEFAULT, screenshot.STRIDE_DEFAULT + data = screenshot.grab(rd, 0, screenshot.HEIGHT, stride, True) + gray = screenshot.decode(data, width, stride) + screenshot.write_png(out_png, width, screenshot.HEIGHT, gray) if out_raw: with open(out_raw, "wb") as fh: fh.write(data) @@ -350,7 +354,7 @@ def verify_markers(rd: exploit.RDebug, result: dict, settle: float) -> list[str] def verify_xhello(rd: exploit.RDebug, out_dir: str, tag: str, settle: float, - take_shot: bool) -> list[str]: + take_shot: bool, real: bool = False) -> list[str]: problems = [] time.sleep(settle) stage = peek_u32(rd, XHELLO_STAGE) @@ -363,7 +367,7 @@ def verify_xhello(rd: exploit.RDebug, out_dir: str, tag: str, settle: float, f"(calling-convention check)") if take_shot: png = os.path.join(out_dir, f"hostload_{tag}_xhello.png") - data = screenshot_vram(rd, png) + data = screenshot_vram(rd, png, real=real) print(f"[+] screenshot {png} ({os.path.getsize(png)} bytes, " f"{len(data)} bytes of VRAM)") return problems @@ -445,6 +449,9 @@ def main(argv: list[str]) -> int: help="evidence file tag (default: COFF basename)") ap.add_argument("--settle", type=float, default=1.5, help="seconds to wait for the child/window after the load") + ap.add_argument("--real", action="store_true", + help="real-unit screenshot geometry (1280x1024, 256-byte " + "stride) instead of the emulator's 1024x1024/128") ap.add_argument("--no-screenshot", action="store_true", help="do not grab VRAM for xhello") ap.add_argument("--jump-wait", type=float, default=20.0, @@ -541,7 +548,7 @@ def main(argv: list[str]) -> int: problems = verify_markers(rd, result, args.settle) elif xhello_mode: problems = verify_xhello(rd, args.out, tag, args.settle, - not args.no_screenshot) + not args.no_screenshot, real=args.real) else: problems = [] print("[.] no app-specific verifier (name is neither marker nor " diff --git a/dwt/notes/REAL_UNIT.md b/dwt/notes/REAL_UNIT.md index 6863a7a..8ec5dbe 100644 --- a/dwt/notes/REAL_UNIT.md +++ b/dwt/notes/REAL_UNIT.md @@ -163,3 +163,27 @@ Both backgrounds are captured at the correct geometry: `dwt/evidence/real-unit-1280-50pct.png` (50% `1010` root, the owner's preference). Only the root's image bytes change; the 256-byte stride and the 1280x1024 size are identical. + +### X11 app on the real unit (2026-10-18) + +The host-side loader ran end to end against the terminal: + +```sh +python3 dwt/loader/hostload.py --host 100.103.100.103 \ + --coff dwt/loader/build/xhello.coff --real +``` + +``` +jump(malloc) -> 0x007e7bf0 +COFF 774 B poked (0 differing) +loader 1220 B @ 0x01880000 (0 differing) +loader A8 = 0; entry 0x01840000; pcb 0x003f6510 +xhello stage=6 strlen=4 +``` + +Evidence: `dwt/evidence/real-unit-xhello.png` — a 400x200 WM-framed black +window over the Terminal Manager, on the real screen. + +**Caveat:** the loader and app are linked at fixed addresses (`0x01880000`, +`0x01840000`). Re-running while that app is live overwrites the running code. +Power-cycle (or choose new addresses) before loading again.