Commit Graph
21 Commits
Author SHA1 Message Date
SDD 71588e5405 dwt/screenshot: --field even for the real unit's line-interleaved framebuffer; the capture now matches the glass 2026-10-18 16:18:27 +03:00
SDD d6d6a7d44a dwt: real-unit note -- root background is white, TM stipple is a display-mode/fetch effect, not a setting 2026-10-18 16:12:44 +03:00
SDD f696a2e8f6 dwt/screenshot: --stretch for the real unit's 1024->1280 display; record geometry and the background stipple 2026-10-18 16:11:24 +03:00
SDD 4a0e1235c7 dwt: first real-unit contact -- TCP 771 and the computed challenge work; ROM peek matches v2.2; screenshot over peek 2026-10-18 15:55:48 +03:00
SDD 8588340527 dwt/loader: end-to-end host loader over rdebug
hostload.py drives one rdebug connection: jump(malloc) for the COFF buffer,
poke the COFF, poke the loader at 0x01880000, write the descriptor, call the
loader, and verify status 0 plus app evidence (marker cells or xhello stage 6
and a VRAM screenshot). --tftp uses the existing tftpc.bin fetch instead of a
host poke. Adds evidence for two/three fresh boots and appends the integrate
section to dwt/notes/LOADER.md, including the bit-offset result-block layout
and the create_process clobber of the descriptor.
2026-10-18 15:34:25 +03:00
SDD 01923ecb69 dwt/tcpip: map the socket API and fetch a file over TFTP into RAM
The firmware's tftp_open hangs in its resolver from the rdebug process, so
the payload speaks RFC 783 over the firmware socket API: socket(2,2,0),
sendto(RRQ), recvfrom(DATA)/ACK into a malloc'd buffer, close. Verified
live: 600 B fetched from 192.168.99.1 into the malloc buffer, server RRQ
logged, and rdebug peek matches probe.bin byte-for-byte.

Notes: dwt/notes/TCPIP.md (function table, ABI, limits) and the
loader/transport hand-off in dwt/notes/LOADER_CROSS.md.
2026-10-18 15:24:34 +03:00
SDD 139d89a10c dwt/loader: COFF loader places GSPLNK images and runs them via create_process 2026-10-18 15:19:44 +03:00
SDD dcca6bee4d dwt: map the firmware heap -- payload scratch sits inside the largest free block; document malloc/free and add heapmap.py 2026-10-18 14:47:14 +03:00
SDD a94e99579f dwt/gui: injected X window works via create_process
The xserver local service is reachable from a payload, but a connect made
inside the rdebug process is accepted at the service layer and then never
dequeued: the server's accept callback runs (3F34EC50), but no 12-byte X11
setup read follows and Xlib waits in select.

create_process(entry,name,stack,1,arg) from a new process fixes it. xlaunch
creates the child; the server reads the setup (READ12 ret 0x0C), writes the
reply (8 + 0x90), and xhello creates/maps/syncs a 400x200 window. The payload
also had to keep Display* in a11 (callee-saved) instead of reloading it from a
RAM cell, and re-run SETF after each Xlib call.

Final breakpoint-free frame: dwt/gui/evidence/xhello_window_frame2838.png.
ROM untouched (b46a3e442ccb86134d2356bd70d22fd2).
2026-10-18 14:28:58 +03:00
SDD a5769d3d2e dwt: GUI/X architecture note; Xlib callable but XOpenDisplay hangs
Static: the VT1200 GUI is an X11 dix server in ROM plus Xlib clients
(SERVER, SESSIONMGR/Terminal Manager, WM, VTE).  Internal clients use the
local service "xserver" via the display string "0::0"; TCP 6000 is a
separate authorised listener.  Function table and the 4-call hello-window
sequence are in dwt/notes/GUI_APPS.md.

Dynamic: a poke+jump payload proved the firmware ABI (strlen=4) and then
called XOpenDisplay; it never returns (stage 2, display 0, X-server client
watermark unchanged) and the rdebug service dies.  Verdict: hard for a
self-contained window; shared-RAM UI mutation (opcode 8) is the working
route.
2026-10-18 14:08:42 +03:00
SDD 0e4075958b dwt: rdebug opcode 8 puts attacker text in the TM Messages box 2026-10-18 11:03:01 +03:00
SDD 619aff0a93 dwt: visual injection -- confirm the persistent box on the live OS, and record that the blink is not established (toggle period is ~1536 frames, not 30) 2026-10-18 03:24:38 +03:00
SDD 05f1895bf5 dwt: visual injection experiments via the returning rdebug jump 2026-10-18 03:22:59 +03:00
SDD 1e5c095b72 dwt: reverse the dwt_prf challenge; remote poke/jump now works
The firmware transforms the reply (16-round Feistel per 8-byte record) and
compares it with the host-order copy of the challenge, so the answer is
swap4(inverse_transform(swap4(challenge))).  The font stages are memcpy in
this path because dwt_prf initialises only mode 1.

challenge.py implements the transform and its inverse using the firmware's
fixed key/SP table; solve.py answers the challenge over TCP using the
unmodified exploit client.  320 forward vectors, the firmware's own inverse
and three live sessions validate it.  A live run with no breakpoints poked
the 82-byte hello-world payload and ran it: MAGIC DEAD/BEEF/0400, VRAM
1024/1024.  Notes and evidence under dwt/notes and dwt/evidence.
2026-10-18 02:36:23 +03:00
SDD 041c82cb73 dwt: runtime oracle and ground-truth vectors for the dwt_prf challenge transform 2026-10-18 02:30:49 +03:00
SDD 5645bb00b3 dwt: exploit client and gate analysis; remote execution blocked at the challenge 2026-10-18 02:20:16 +03:00
SDD 2c7b2e8c2e dwt: gate B is real; challenge args must follow the answer 2026-10-18 02:19:54 +03:00
SDD bd58af3569 dwt: gate A is a 2-bit field and is open; correct the static reading 2026-10-18 02:07:18 +03:00
SDD a18881f45d dwt: MOP console carrier client, protocol notes, and emulator evidence 2026-10-18 02:02:17 +03:00
SDD 0a1042e81f dwt: correct the Done\n reply length (payload includes its NUL, len field = payload+1) 2026-10-18 01:55:56 +03:00
SDD 68a1aeabdc dwt: static analysis of rdebug / DWT console -- poke+jump exist, gated by a config word and a 16-byte handshake 2026-10-18 01:55:41 +03:00