Files
vt1200/dwt/gui/xhello.asm
T
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

154 lines
4.4 KiB
NASM

; xhello.asm -- open a *new* X connection and create/map a window on the live
; DWT X server.
;
; Run as a first-class process created by xlaunch.asm (create_process), NOT in
; the rdebug dispatcher's context: a connect made from the rdebug process is
; accepted at the service layer but the server never reads the X11 setup, so
; XOpenDisplay returns an unusable Display. A fresh process works.
;
; Calling convention (the one the firmware itself uses; see the WM at
; 07F57044 and the TM at 07E5D2B4):
;
; MOVE A14,-*SP,1 ; reserve the slot the callee restores A14 from
; MOVI argN,A0 / MOVE A0,*A14+,1 ; last argument first, upward via A14
; ...
; MOVI arg0,A0 / MOVE A0,*A14+,1 ; first argument last
; CALLA target
;
; Xlib clobbers the CPU's SETF field state, so the ABI's 32-bit field 1 is
; re-established after every call. The Display pointer and root/window ids are
; kept in a11/a10 (both callee-saved by every Xlib entry point): a RAM cell can
; be overwritten by the new process's stack, a register cannot.
;
; Xlib entry points (Ghidra address -> bit address):
; 7F384AE XOpenDisplay(name) -> 3F9C2570
; 7FA8372 XCreateSimpleWindow(...) -> 3FD41B90
; 7FAC8B6 XMapWindow(display,window) -> 3FD645B0
; 7FB3ED6 XSync(display,discard) -> 3FD9F6B0
; 7F68B1A strlen(s) -> 3FB458D0 (convention check)
;
; Markers (32-bit cells, bit addresses; diagnostic only):
; 01890100 display pointer
; 01890110 root window
; 01890120 window id
; 01890130 XSync return
; 01890140 stage counter
; 01890160 strlen("0::0") -- must be 4; if not, we stop before touching Xlib
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7
move sp, @01890420h, 1 ; entry SP
move a14, @01890400h, 1 ; entry A14
movi 1, a0, L
move a0, @01890140h, 1 ; stage = 1
; ---- convention check: strlen("0::0") == 4 --------------------
move a14, -*sp, 1
movi 01892000h, a14, L
movi 3FACE948h, a0, L ; ROM "0::0"
move a0, *a14+, 1 ; arg0
calla 3FB458D0h ; strlen
move @01890420h, sp, 1
move @01890400h, a14, 1
setf 16, 0, 0 ; Xlib leaves the field sizes changed;
setf 32, 0, 1 ; re-establish the ABI's 32-bit field 1
move a8, @01890160h, 1 ; MARK strlen
movi 4, a0, L
cmp a0, a8
jrne done
movi 2, a0, L
move a0, @01890140h, 1
; ---- display = XOpenDisplay("0::0") ---------------------------
move a14, -*sp, 1
movi 01892000h, a14, L
movi 3FACE948h, a0, L
move a0, *a14+, 1 ; arg0 = name
calla 3F9C2570h ; XOpenDisplay
move @01890420h, sp, 1
move @01890400h, a14, 1
setf 16, 0, 0
setf 32, 0, 1
move a8, a11 ; keep the Display in a callee-saved reg
move a11, @01890100h, 1 ; MARK display
move a11, a11
jreq done
movi 3, a0, L
move a0, @01890140h, 1
; ---- root = *(*(display+0x480)+0x40) --------------------------
move *a11(0480h), a10, 1
move *a10(040h), a10, 1
move a10, @01890110h, 1 ; MARK root
; ---- XCreateSimpleWindow(display,root,100,100,400,200,2,0,0) --
move a14, -*sp, 1
movi 01892000h, a14, L
movi 0, a0, L
move a0, *a14+, 1 ; background = 0 (black)
move a0, *a14+, 1 ; border = 0
movi 2, a0, L
move a0, *a14+, 1 ; border width
movi 200, a0, L
move a0, *a14+, 1 ; height
movi 400, a0, L
move a0, *a14+, 1 ; width
movi 100, a0, L
move a0, *a14+, 1 ; y
move a0, *a14+, 1 ; x
move a10, *a14+, 1 ; parent = root
move a11, *a14+, 1 ; display
calla 3FD41B90h ; XCreateSimpleWindow
move @01890420h, sp, 1
move @01890400h, a14, 1
setf 16, 0, 0
setf 32, 0, 1
move a8, a10 ; window id (root no longer needed)
move a10, @01890120h, 1 ; MARK window
movi 4, a0, L
move a0, @01890140h, 1
; ---- XMapWindow(display, window) ------------------------------
move a14, -*sp, 1
movi 01892000h, a14, L
move a10, *a14+, 1 ; window
move a11, *a14+, 1 ; display
calla 3FD645B0h ; XMapWindow
move @01890420h, sp, 1
move @01890400h, a14, 1
setf 16, 0, 0
setf 32, 0, 1
movi 5, a0, L
move a0, @01890140h, 1
; ---- XSync(display, 0) ----------------------------------------
move a14, -*sp, 1
movi 01892000h, a14, L
movi 0, a0, L
move a0, *a14+, 1 ; discard = 0
move a11, *a14+, 1 ; display
calla 3FD9F6B0h ; XSync
move @01890420h, sp, 1
move @01890400h, a14, 1
setf 16, 0, 0
setf 32, 0, 1
move a8, @01890130h, 1 ; MARK sync
movi 6, a0, L
move a0, @01890140h, 1
done:
mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7
movi 0, a8, L
rets
.end