mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
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).
79 lines
3.9 KiB
Markdown
79 lines
3.9 KiB
Markdown
# dwt/gui — injected X window (working)
|
|
|
|
Investigation of the VT1200 GUI architecture and whether an injected payload can
|
|
create its own window. Read `dwt/notes/GUI_APPS.md` first (especially the new
|
|
§10); this directory is the reproducible part.
|
|
|
|
**Result:** yes. The payload must run in a process created by the firmware's own
|
|
`create_process` (not in the rdebug dispatcher), and it must keep the `Display *`
|
|
in a callee-saved register rather than reloading it from a RAM cell. The final
|
|
breakpoint-free run shows the window at frame 2838:
|
|
`evidence/xhello_window_frame2838.png` (black 400x200 window at 100,100, framed
|
|
by the WM).
|
|
|
|
| file | what it is |
|
|
|---|---|
|
|
| `xhello.asm` | the window payload: ABI check (`strlen("0::0")==4`), `XOpenDisplay`, root lookup, `XCreateSimpleWindow`, `XMapWindow`, `XSync`; Display in `a11`, window in `a10`, `setf` re-established after every call |
|
|
| `xlaunch.asm` | 128-byte launcher: `create_process(xhello, name, 0x6000, 1, 0)` — the Telnet handler's call shape |
|
|
| `build.sh` | TI SDK (GSPA/GSPLNK under DOSBox) wrapper; writes `build/`, scratch in `work/` |
|
|
| `probe_win.lua` | **breakpoint-free** final probe: marker log + PNG snapshots on a trigger file |
|
|
| `probe.lua` / `probe2.lua` / `probe3.lua` | earlier probes (marker/PC telemetry; `probe3` targets the mis-identified `3F58B800`) |
|
|
| `trace_accept.lua` | instrumented run: service attach/lookup, server accept callback, 12-byte setup read, setup-reply write, Xlib read, process create |
|
|
| `build/xhello.bin` | assembled payload, linked at bit `0x01840000` |
|
|
| `build/xlaunch.bin` | assembled launcher, linked at bit `0x01860000` |
|
|
| `evidence/xhello_window_frame2838.png` | the window, after a run with no breakpoints |
|
|
| `evidence/transport_evidence.txt` | quoted accept/read/reply lines from the instrumented runs |
|
|
| `run12/debug.log` | full instrumented trace of the successful fresh-process run |
|
|
| `run13/` | final run: `mame.log`, snapshots, private cfg/nvram |
|
|
| `run/` | the earlier failing experiment (rdebug context, stage 2) |
|
|
|
|
## Build
|
|
|
|
```sh
|
|
./dwt/gui/build.sh dwt/gui/xhello.asm 01840000 # 390 bytes
|
|
./dwt/gui/build.sh dwt/gui/xlaunch.asm 01860000 # 128 bytes
|
|
```
|
|
|
|
## Run
|
|
|
|
The payload needs the OS, i.e. `VT1200_SKIP_LEVEL1=1` (documented divergence),
|
|
a BOOTP/TFTP server and the LANCE attached. MAME's network device is enabled by
|
|
the **cfg file**, not the command line — without
|
|
`<network><device tag=":lance" interface="0" .../></network>` in
|
|
`vt1200.cfg` the taptun provider is never opened (the tap stays `NO-CARRIER`).
|
|
|
|
```sh
|
|
RUN=$PWD/dwt/gui/run13
|
|
mkdir -p $RUN/cfg $RUN/nvram
|
|
cp harness/mame/cfg-net/vt1200.cfg $RUN/cfg/vt1200.cfg
|
|
|
|
sudo python3 -u harness/serve.py 192.168.99.1 --bootp &
|
|
|
|
VT1200_SKIP_LEVEL1=1 MSG_TRIGGER=$RUN/trigger MSG_DIR=$RUN \
|
|
/home/arti/code/k-space/mame0289/vt1200 vt1200 \
|
|
-rompath harness/mame/roms -sound none -skip_gameinfo \
|
|
-networkprovider taptun -video none -nothrottle \
|
|
-cfg_directory $RUN/cfg -nvram_directory $RUN/nvram \
|
|
-debug -debugger none -autoboot_script $PWD/dwt/gui/probe_win.lua \
|
|
-autoboot_delay 0
|
|
|
|
# once 192.168.99.2:771 answers (rdebug creates a fresh process per connection)
|
|
python3 dwt/visual/inject.py --host 192.168.99.2 \
|
|
--poke-file 0x01840000 --file dwt/gui/build/xhello.bin
|
|
python3 dwt/visual/inject.py --host 192.168.99.2 \
|
|
--poke-file 0x01860000 --file dwt/gui/build/xlaunch.bin \
|
|
--jump 0x01860000 --jump-wait 8
|
|
|
|
# snapshots: write "<prefix> <count> <stride>" into $RUN/trigger
|
|
echo 'xhello 6 60' > $RUN/trigger
|
|
```
|
|
|
|
Markers are diagnostic cells at bit `0x01890100` (display), `01890110` (root),
|
|
`01890120` (window), `01890130` (sync), `01890140` (stage), `01890160`
|
|
(strlen). In the successful run the stage reaches 6 and `strlen` is 4.
|
|
|
|
Do **not** call Xlib in the rdebug process: the service attach and the server's
|
|
accept callback succeed, but the server never reads the 12-byte setup, and
|
|
Xlib waits forever. See §10 of the note for the trace and the remaining
|
|
open question.
|