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).
154 lines
4.4 KiB
NASM
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
|