From 8588340527261e73e85a0363b6b5a02571d4d4a0 Mon Sep 17 00:00:00 2001 From: SDD Date: Sun, 18 Oct 2026 15:34:25 +0300 Subject: [PATCH] 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. --- dwt/loader/evidence/hostload/README.md | 91 +++ .../evidence/hostload/heapmap_boot4.txt | 26 + .../hostload/hostload_xhello_boot2_xhello.png | Bin 0 -> 6608 bytes .../hostload/hostload_xhello_boot3_xhello.png | Bin 0 -> 6696 bytes .../hostload/hostload_xhello_boot4_xhello.png | Bin 0 -> 6696 bytes dwt/loader/evidence/hostload/mame_boot1.log | 11 + dwt/loader/evidence/hostload/mame_boot2.log | 11 + dwt/loader/evidence/hostload/mame_boot3.log | 11 + dwt/loader/evidence/hostload/mame_boot4.log | 11 + .../evidence/hostload/marker_boot2_run4.log | 33 + dwt/loader/evidence/hostload/marker_boot3.log | 33 + dwt/loader/evidence/hostload/marker_boot4.log | 33 + .../hostload/marker_nopokeloader_boot4.log | 33 + dwt/loader/evidence/hostload/serve_boot1.log | 4 + .../evidence/hostload/serve_tftp_marker.log | 8 + .../hostload/serve_tftp_marker_boot2.log | 3 + .../evidence/hostload/tftp_marker_boot3.log | 34 ++ .../evidence/hostload/tftp_marker_boot4.log | 34 ++ dwt/loader/evidence/hostload/xhello_boot3.log | 30 + dwt/loader/evidence/hostload/xhello_boot4.log | 30 + dwt/loader/hostload.py | 574 ++++++++++++++++++ dwt/notes/LOADER.md | 94 +++ 22 files changed, 1104 insertions(+) create mode 100644 dwt/loader/evidence/hostload/README.md create mode 100644 dwt/loader/evidence/hostload/heapmap_boot4.txt create mode 100644 dwt/loader/evidence/hostload/hostload_xhello_boot2_xhello.png create mode 100644 dwt/loader/evidence/hostload/hostload_xhello_boot3_xhello.png create mode 100644 dwt/loader/evidence/hostload/hostload_xhello_boot4_xhello.png create mode 100644 dwt/loader/evidence/hostload/mame_boot1.log create mode 100644 dwt/loader/evidence/hostload/mame_boot2.log create mode 100644 dwt/loader/evidence/hostload/mame_boot3.log create mode 100644 dwt/loader/evidence/hostload/mame_boot4.log create mode 100644 dwt/loader/evidence/hostload/marker_boot2_run4.log create mode 100644 dwt/loader/evidence/hostload/marker_boot3.log create mode 100644 dwt/loader/evidence/hostload/marker_boot4.log create mode 100644 dwt/loader/evidence/hostload/marker_nopokeloader_boot4.log create mode 100644 dwt/loader/evidence/hostload/serve_boot1.log create mode 100644 dwt/loader/evidence/hostload/serve_tftp_marker.log create mode 100644 dwt/loader/evidence/hostload/serve_tftp_marker_boot2.log create mode 100644 dwt/loader/evidence/hostload/tftp_marker_boot3.log create mode 100644 dwt/loader/evidence/hostload/tftp_marker_boot4.log create mode 100644 dwt/loader/evidence/hostload/xhello_boot3.log create mode 100644 dwt/loader/evidence/hostload/xhello_boot4.log create mode 100644 dwt/loader/hostload.py diff --git a/dwt/loader/evidence/hostload/README.md b/dwt/loader/evidence/hostload/README.md new file mode 100644 index 0000000..e8b3be0 --- /dev/null +++ b/dwt/loader/evidence/hostload/README.md @@ -0,0 +1,91 @@ +# hostload evidence (rdebug -> malloc -> COFF -> loader -> app) + +All runs: `VT1200_SKIP_LEVEL1=1`, private `-cfg_directory`/`-nvram_directory`, +`-networkprovider taptun`, BOOTP/TFTP from `dwt/tcpip/serve_probe.py` on +`192.168.99.2`. The ROM is untouched +(`md5 b46a3e442ccb86134d2356bd70d22fd2`, re-checked after the runs); no driver +edits, no breakpoints. + +Driver: `dwt/loader/hostload.py`. Each log is one complete connection. + +## Malloc -> poke -> descriptor -> loader -> markers (three boots) + +| log | boot | `jump(malloc)` bit ptr | byte | status / PCB | markers | +|---|---|---|---|---|---| +| `marker_boot2_run4.log` | 2 | `0x007df450` | `0x0FBE8A` | 0 / `0x003fc5d0` | start/data/data2/bss OK, count moving | +| `marker_boot3.log` | 3 | `0x007c7290` | `0x0F8E52` | 0 / `0x003ffbd0` | start/data/data2/bss OK, count moving | +| `marker_boot4.log` | 4 | `0x007c8030` | `0x0F9006` | 0 / `0x003ffbd0` | start/data/data2/bss OK, count moving | +| `marker_nopokeloader_boot4.log` | 4 | `0x007d8970` | `0x0FB12E` | 0 / `0x003fd590` | loader readback 610 words, 0 differing | + +The marker values in every run are `start=0x018C0000`, `data=0xDEADBEEF`, +`data2=0x12345678`, `bss=0` after a fresh boot. The counter changes between two +samples (multiple children from successive runs can make it go backwards; a +fresh boot is monotonic). + +Each log shows the full result block: status 0, entry/text/data/bss addresses +and sizes, `pcb != 0`, `nscns=3`, `coff_len=510`, `loader_base=0x01880000`. + +## xhello -> X window (two boots) + +| log | boot | malloc bit ptr | stage | screenshot | +|---|---|---|---|---| +| `xhello_boot3.log` | 3 | `0x007c82d0` | 6 | `hostload_xhello_boot3_xhello.png` | +| `xhello_boot4.log` | 4 | `0x007c9070` | 6 | `hostload_xhello_boot4_xhello.png` | + +`stage=6` is set after `XSync`; `strlen=4` is the ABI check. The PNGs (1-bit +1024x1024 VRAM, lossless) show the black 400x200 window with its WM title bar at +`(100,100)` over the Terminal Manager — same visual as +`dwt/loader/evidence/loader_frame2650.png`. + +## Heap placement (read-only `dwt/heapmap.py`) + +`heapmap_boot4.txt` shows the global free list after the boot-4 runs and checks +the two app `.text` targets: `0x018C0000` and `0x01840000` are both **inside** +the last free block (`byte 0x1719BA..0x400000`) with about 950 KiB / 0.97 MiB +of headroom to its end. The malloc'd COFF buffers (`0x007C…`, `0x009F…`, +`0x00AD…`) are in the low blocks, far from the loader page (byte `0x310000`) +and from both targets. That is why the loader's free-list check (a check, not +a reservation) passes on these boots. + +## `--tftp`: fetched COFF, no host poke of the COFF (two boots) + +| log | boot | tftpc buffer | RRQ line | +|---|---|---|---| +| `tftp_marker_boot3.log` | 3 | `0x009fccd0` | `15:31:47 ... requested 'dwt/tcpip/probe.bin' (510 bytes)` | +| `tftp_marker_boot4.log` | 4 | `0x009fccd0` | `15:32:16 ... requested 'dwt/tcpip/probe.bin' (510 bytes)` | + +(`serve_tftp_marker_boot2.log` is the boot-2 RRQ from the first, pre-logging +run: `15:31:07`, buffer `0x00b4ce90`; its host-side output was not saved.) + +The TFTP server was serving `dwt/loader/build/marker.coff` for **any** name +(`--file dwt/loader/build/marker.coff`); `tftpc.asm`'s RRQ name is fixed. Each +log shows `stage=4 fd=1 total=510 done=0x05A5A5A5`, then a `peek` comparison of +the fetched buffer against the local COFF: 510/510 bytes, sha256 +`519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749` (same as +the file). The loader then used that buffer's bit address in the descriptor. + +## Failure that is not a failure + +The first integration attempts parsed the result block at byte offsets +`0x20, 0x40, ...` and saw `0x55555555`. The loader's constants are **bit** +offsets (`RESULT_BASE+020h` = +4 bytes), so the real block is 13 adjacent +32-bit cells (52 bytes) at byte offsets `0x00, 0x04, ... 0x30`. The stale/free +heap fill beyond byte 0x34 reads `0x55`. `hostload.py` now converts bit +offsets to bytes; no loader change was needed. + +## Descriptor quirk worth knowing + +After a successful load, a 16-byte window at `0x01882C00` (the descriptor) is +overwritten with `0d 00 00 00 00 60 00 00` — the `create_process` +call frame from the loader's `ARG_AREA` (`0x01882B00`, 0x100 bits below the +descriptor). It is harmless: the loader has already read the descriptor, and +the result block at `0x01882D00` is untouched. It does mean a second call must +rewrite the descriptor, which `hostload.py` always does immediately before the +jump. + +## Frame dumps + +`hostload.py --frame N` only waits for `vt1200-frame-N.ppm` (a MAME +`VT1200_DUMP_FRAME` dump). Frame numbers are boot-relative and the dump must be +configured on the MAME side; the load-relative evidence here is the rdebug VRAM +screenshot, not a MAME frame dump. diff --git a/dwt/loader/evidence/hostload/heapmap_boot4.txt b/dwt/loader/evidence/hostload/heapmap_boot4.txt new file mode 100644 index 0000000..f3b305a --- /dev/null +++ b/dwt/loader/evidence/hostload/heapmap_boot4.txt @@ -0,0 +1,26 @@ +# fresh boot 4, after hostload marker/xhello/tftp runs +# free counter / global free list (read-only peek) +free counter: 22345840 bits = 2793230 bytes (2793 KB decimal) +global: 10 blocks, byte 0x0F5A7E..0x400000, 2705790 bytes usable + bit 0x007AD3F0 byte 0x0F5A7E size 84 B end 0x0F5AD2 next 0x007ADF90 + bit 0x007ADF90 byte 0x0F5BF2 size 44 B end 0x0F5C1E next 0x007AEAD0 + bit 0x007AEAD0 byte 0x0F5D5A size 88 B end 0x0F5DB2 next 0x007AF0F0 + bit 0x007AF0F0 byte 0x0F5E1E size 12768 B end 0x0F8FFE next 0x007DBCD0 + bit 0x007DBCD0 byte 0x0FB79A size 836 B end 0x0FBADE next 0x007DF410 + bit 0x007DF410 byte 0x0FBE82 size 11364 B end 0x0FEAE6 next 0x008DB630 + bit 0x008DB630 byte 0x11B6C6 size 56 B end 0x11B6FE next 0x009029D0 + bit 0x009029D0 byte 0x12053A size 164 B end 0x1205DE next 0x009209F0 + bit 0x009209F0 byte 0x12413E size 76 B end 0x12418A next 0x00B8CDD0 + bit 0x00B8CDD0 byte 0x1719BA size 2680390 B end 0x400000 next 0x00000000 + +# --at 0x018C0000 (marker .text target) +free counter: 22345520 bits = 2793190 bytes (2793 KB decimal) +global: 10 blocks, byte 0x0F5A7E..0x400000, 2705790 bytes usable +check bit 0x018C0000 (byte 0x318000): INSIDE a free block + global: block bit 0x00B8CDD0, 950272 bytes of headroom to its end + +# --at 0x01840000 (xhello .text target) +free counter: 22345840 bits = 2793230 bytes (2793 KB decimal) +global: 10 blocks, byte 0x0F5A7E..0x400000, 2705790 bytes usable +check bit 0x01840000 (byte 0x308000): INSIDE a free block + global: block bit 0x00B8CDD0, 1015808 bytes of headroom to its end diff --git a/dwt/loader/evidence/hostload/hostload_xhello_boot2_xhello.png b/dwt/loader/evidence/hostload/hostload_xhello_boot2_xhello.png new file mode 100644 index 0000000000000000000000000000000000000000..ba0547e637995649307b83faad6202bdc8d4a7fd GIT binary patch literal 6608 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 M;=#*a?6>{@0g(YMVgLXD literal 0 HcmV?d00001 diff --git a/dwt/loader/evidence/hostload/hostload_xhello_boot4_xhello.png b/dwt/loader/evidence/hostload/hostload_xhello_boot4_xhello.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a146622840c72176f0a1ffba58b692f3450b14 GIT binary patch literal 6696 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 M;=#*a?6>{@0g(YMVgLXD literal 0 HcmV?d00001 diff --git a/dwt/loader/evidence/hostload/mame_boot1.log b/dwt/loader/evidence/hostload/mame_boot1.log new file mode 100644 index 0000000..904b84e --- /dev/null +++ b/dwt/loader/evidence/hostload/mame_boot1.log @@ -0,0 +1,11 @@ +Warning: -video none doesn't make much sense without -seconds_to_run +vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901 +vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901 +vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901 +vt1200: scanline#1 line=0 enabled=1 +vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901 +vt1200: scanline#2 line=0 enabled=1 +vt1200: scanline#3 line=1 enabled=1 +vt1200: scanline#4 line=2 enabled=1 diff --git a/dwt/loader/evidence/hostload/mame_boot2.log b/dwt/loader/evidence/hostload/mame_boot2.log new file mode 100644 index 0000000..904b84e --- /dev/null +++ b/dwt/loader/evidence/hostload/mame_boot2.log @@ -0,0 +1,11 @@ +Warning: -video none doesn't make much sense without -seconds_to_run +vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901 +vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901 +vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901 +vt1200: scanline#1 line=0 enabled=1 +vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901 +vt1200: scanline#2 line=0 enabled=1 +vt1200: scanline#3 line=1 enabled=1 +vt1200: scanline#4 line=2 enabled=1 diff --git a/dwt/loader/evidence/hostload/mame_boot3.log b/dwt/loader/evidence/hostload/mame_boot3.log new file mode 100644 index 0000000..904b84e --- /dev/null +++ b/dwt/loader/evidence/hostload/mame_boot3.log @@ -0,0 +1,11 @@ +Warning: -video none doesn't make much sense without -seconds_to_run +vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901 +vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901 +vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901 +vt1200: scanline#1 line=0 enabled=1 +vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901 +vt1200: scanline#2 line=0 enabled=1 +vt1200: scanline#3 line=1 enabled=1 +vt1200: scanline#4 line=2 enabled=1 diff --git a/dwt/loader/evidence/hostload/mame_boot4.log b/dwt/loader/evidence/hostload/mame_boot4.log new file mode 100644 index 0000000..904b84e --- /dev/null +++ b/dwt/loader/evidence/hostload/mame_boot4.log @@ -0,0 +1,11 @@ +Warning: -video none doesn't make much sense without -seconds_to_run +vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901 +vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901 +vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901 +vt1200: scanline#1 line=0 enabled=1 +vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901 +vt1200: scanline#2 line=0 enabled=1 +vt1200: scanline#3 line=1 enabled=1 +vt1200: scanline#4 line=2 enabled=1 diff --git a/dwt/loader/evidence/hostload/marker_boot2_run4.log b/dwt/loader/evidence/hostload/marker_boot2_run4.log new file mode 100644 index 0000000..a8716b1 --- /dev/null +++ b/dwt/loader/evidence/hostload/marker_boot2_run4.log @@ -0,0 +1,33 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007df450 (8254544) +[+] jump(malloc) -> 0x007df450; bit 0x007df450 = byte 0x0fbe8a, 510 bytes, bit range 0x007df450..0x007e0440 +[+] COFF poked 510 B at 0x007df450 (255 words, 0 differing bytes) + readback[0:510] 90 00 03 00 de e0 d4 6a 02 01 00 00 0e 00 00 00 1c 00 03 01 08 01 c7 00 90 02 00 00 40 00 00 00 40 00 00 00 00 00 8c 01 00 00 8c 01 00 00 8d 01 2e 74 65 78 74 00 00 00 00 00 8c 01 00 00 8c 01 90 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 00 00 8d 01 40 00 00 00 fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 00 80 8d 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 50 05 40 07 e2 09 00 00 8c 01 82 07 00 00 8e 01 a0 07 00 00 8d 01 80 07 20 00 8e 01 a1 07 20 00 8d 01 81 07 40 00 8e 01 a3 07 00 80 8d 01 83 07 60 00 8e 01 84 44 04 0b 01 00 84 07 20 80 8d 01 84 07 80 00 8e 01 e5 09 00 20 00 00 25 3c f3 c0 60 09 ef be ad de 78 56 34 12 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 03 01 90 02 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 73 75 62 00 00 00 00 00 80 02 8c 01 01 00 00 00 02 00 5f 73 74 61 72 74 00 00 00 00 8c 01 01 00 00 00 02 00 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 02 00 65 74 65 78 74 00 00 00 90 02 8c 01 01 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 02 00 65 64 61 74 61 00 00 00 40 00 8d 01 02 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 02 00 65 6e 64 00 00 00 00 00 40 80 8d 01 03 00 00 00 02 00 +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 50 f4 7d 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007df450, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fc5d0 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 20495 -> 23238 (child scheduled) +[+] PASS: status=0 pcb=0x003fc5d0 entry=0x018c0000 (marker_boot2_run4) diff --git a/dwt/loader/evidence/hostload/marker_boot3.log b/dwt/loader/evidence/hostload/marker_boot3.log new file mode 100644 index 0000000..e368b5c --- /dev/null +++ b/dwt/loader/evidence/hostload/marker_boot3.log @@ -0,0 +1,33 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007c7290 (8155792) +[+] jump(malloc) -> 0x007c7290; bit 0x007c7290 = byte 0x0f8e52, 510 bytes, bit range 0x007c7290..0x007c8280 +[+] COFF poked 510 B at 0x007c7290 (255 words, 0 differing bytes) + readback[0:510] 90 00 03 00 de e0 d4 6a 02 01 00 00 0e 00 00 00 1c 00 03 01 08 01 c7 00 90 02 00 00 40 00 00 00 40 00 00 00 00 00 8c 01 00 00 8c 01 00 00 8d 01 2e 74 65 78 74 00 00 00 00 00 8c 01 00 00 8c 01 90 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 00 00 8d 01 40 00 00 00 fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 00 80 8d 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 50 05 40 07 e2 09 00 00 8c 01 82 07 00 00 8e 01 a0 07 00 00 8d 01 80 07 20 00 8e 01 a1 07 20 00 8d 01 81 07 40 00 8e 01 a3 07 00 80 8d 01 83 07 60 00 8e 01 84 44 04 0b 01 00 84 07 20 80 8d 01 84 07 80 00 8e 01 e5 09 00 20 00 00 25 3c f3 c0 60 09 ef be ad de 78 56 34 12 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 03 01 90 02 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 73 75 62 00 00 00 00 00 80 02 8c 01 01 00 00 00 02 00 5f 73 74 61 72 74 00 00 00 00 8c 01 01 00 00 00 02 00 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 02 00 65 74 65 78 74 00 00 00 90 02 8c 01 01 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 02 00 65 64 61 74 61 00 00 00 40 00 8d 01 02 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 02 00 65 6e 64 00 00 00 00 00 40 80 8d 01 03 00 00 00 02 00 +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 90 72 7c 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007c7290, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003ffbd0 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 387 -> 1301 (child scheduled) +[+] PASS: status=0 pcb=0x003ffbd0 entry=0x018c0000 (marker_boot3) diff --git a/dwt/loader/evidence/hostload/marker_boot4.log b/dwt/loader/evidence/hostload/marker_boot4.log new file mode 100644 index 0000000..479b876 --- /dev/null +++ b/dwt/loader/evidence/hostload/marker_boot4.log @@ -0,0 +1,33 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007c8030 (8159280) +[+] jump(malloc) -> 0x007c8030; bit 0x007c8030 = byte 0x0f9006, 510 bytes, bit range 0x007c8030..0x007c9020 +[+] COFF poked 510 B at 0x007c8030 (255 words, 0 differing bytes) + readback[0:510] 90 00 03 00 de e0 d4 6a 02 01 00 00 0e 00 00 00 1c 00 03 01 08 01 c7 00 90 02 00 00 40 00 00 00 40 00 00 00 00 00 8c 01 00 00 8c 01 00 00 8d 01 2e 74 65 78 74 00 00 00 00 00 8c 01 00 00 8c 01 90 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 00 00 8d 01 40 00 00 00 fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 00 80 8d 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 50 05 40 07 e2 09 00 00 8c 01 82 07 00 00 8e 01 a0 07 00 00 8d 01 80 07 20 00 8e 01 a1 07 20 00 8d 01 81 07 40 00 8e 01 a3 07 00 80 8d 01 83 07 60 00 8e 01 84 44 04 0b 01 00 84 07 20 80 8d 01 84 07 80 00 8e 01 e5 09 00 20 00 00 25 3c f3 c0 60 09 ef be ad de 78 56 34 12 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 03 01 90 02 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 73 75 62 00 00 00 00 00 80 02 8c 01 01 00 00 00 02 00 5f 73 74 61 72 74 00 00 00 00 8c 01 01 00 00 00 02 00 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 02 00 65 74 65 78 74 00 00 00 90 02 8c 01 01 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 02 00 65 64 61 74 61 00 00 00 40 00 8d 01 02 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 02 00 65 6e 64 00 00 00 00 00 40 80 8d 01 03 00 00 00 02 00 +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 30 80 7c 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007c8030, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003ffbd0 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 380 -> 1252 (child scheduled) +[+] PASS: status=0 pcb=0x003ffbd0 entry=0x018c0000 (marker_boot4) diff --git a/dwt/loader/evidence/hostload/marker_nopokeloader_boot4.log b/dwt/loader/evidence/hostload/marker_nopokeloader_boot4.log new file mode 100644 index 0000000..20d1ea2 --- /dev/null +++ b/dwt/loader/evidence/hostload/marker_nopokeloader_boot4.log @@ -0,0 +1,33 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007d8970 (8227184) +[+] jump(malloc) -> 0x007d8970; bit 0x007d8970 = byte 0x0fb12e, 510 bytes, bit range 0x007d8970..0x007d9960 +[+] COFF poked 510 B at 0x007d8970 (255 words, 0 differing bytes) + readback[0:510] 90 00 03 00 de e0 d4 6a 02 01 00 00 0e 00 00 00 1c 00 03 01 08 01 c7 00 90 02 00 00 40 00 00 00 40 00 00 00 00 00 8c 01 00 00 8c 01 00 00 8d 01 2e 74 65 78 74 00 00 00 00 00 8c 01 00 00 8c 01 90 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 00 00 8d 01 40 00 00 00 fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 00 80 8d 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 50 05 40 07 e2 09 00 00 8c 01 82 07 00 00 8e 01 a0 07 00 00 8d 01 80 07 20 00 8e 01 a1 07 20 00 8d 01 81 07 40 00 8e 01 a3 07 00 80 8d 01 83 07 60 00 8e 01 84 44 04 0b 01 00 84 07 20 80 8d 01 84 07 80 00 8e 01 e5 09 00 20 00 00 25 3c f3 c0 60 09 ef be ad de 78 56 34 12 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 03 01 90 02 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 03 01 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 73 75 62 00 00 00 00 00 80 02 8c 01 01 00 00 00 02 00 5f 73 74 61 72 74 00 00 00 00 8c 01 01 00 00 00 02 00 2e 74 65 78 74 00 00 00 00 00 8c 01 01 00 00 00 02 00 65 74 65 78 74 00 00 00 90 02 8c 01 01 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 8d 01 02 00 00 00 02 00 65 64 61 74 61 00 00 00 40 00 8d 01 02 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 80 8d 01 03 00 00 00 02 00 65 6e 64 00 00 00 00 00 40 80 8d 01 03 00 00 00 02 00 +[.] --no-poke-loader: /home/arti/code/k-space/vt1200/dwt/loader/build/loader.bin readback (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 70 89 7d 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007d8970, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fd590 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 4578 -> 606 (child scheduled) +[+] PASS: status=0 pcb=0x003fd590 entry=0x018c0000 (marker_nopokeloader_boot4) diff --git a/dwt/loader/evidence/hostload/serve_boot1.log b/dwt/loader/evidence/hostload/serve_boot1.log new file mode 100644 index 0000000..bf33c19 --- /dev/null +++ b/dwt/loader/evidence/hostload/serve_boot1.log @@ -0,0 +1,4 @@ +tftp: serving 600 bytes (probe.bin) for any name on ('192.168.99.1', 69) +bootp: L2 responder on tap-mess-1000-0: handing out 192.168.99.2, siaddr 192.168.99.1 +bootp: request from 08:00:2b:16:4b:5a xid=f81fccff -> 192.168.99.2 (siaddr 192.168.99.1, tap tap-mess-1000-0) +bootp: request from 08:00:2b:16:4b:5a xid=f81fccff -> 192.168.99.2 (siaddr 192.168.99.1, tap tap-mess-1000-0) diff --git a/dwt/loader/evidence/hostload/serve_tftp_marker.log b/dwt/loader/evidence/hostload/serve_tftp_marker.log new file mode 100644 index 0000000..fb2f6d0 --- /dev/null +++ b/dwt/loader/evidence/hostload/serve_tftp_marker.log @@ -0,0 +1,8 @@ +tftp: serving 510 bytes (marker.coff) for any name on ('192.168.99.1', 69) +bootp: L2 responder on tap-mess-1000-0: handing out 192.168.99.2, siaddr 192.168.99.1 +15:31:07 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) +bootp: request from 08:00:2b:16:4b:5a xid=f81fccff -> 192.168.99.2 (siaddr 192.168.99.1, tap tap-mess-1000-0) +15:31:47 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) +bootp: request from 08:00:2b:16:4b:5a xid=f81fccff -> 192.168.99.2 (siaddr 192.168.99.1, tap tap-mess-1000-0) +15:32:16 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) +15:32:53 RRQ 192.168.99.2:1026 requested 'dwt/tcpip/probe.bin' (510 bytes) diff --git a/dwt/loader/evidence/hostload/serve_tftp_marker_boot2.log b/dwt/loader/evidence/hostload/serve_tftp_marker_boot2.log new file mode 100644 index 0000000..f7ebef3 --- /dev/null +++ b/dwt/loader/evidence/hostload/serve_tftp_marker_boot2.log @@ -0,0 +1,3 @@ +tftp: serving 510 bytes (marker.coff) for any name on ('192.168.99.1', 69) +bootp: L2 responder on tap-mess-1000-0: handing out 192.168.99.2, siaddr 192.168.99.1 +15:31:07 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) diff --git a/dwt/loader/evidence/hostload/tftp_marker_boot3.log b/dwt/loader/evidence/hostload/tftp_marker_boot3.log new file mode 100644 index 0000000..1c70786 --- /dev/null +++ b/dwt/loader/evidence/hostload/tftp_marker_boot3.log @@ -0,0 +1,34 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] tftpc poked 694 B at 0x01870000 (347 words, 0 differing) +[.] jump returned 0x00000000 (0) +[.] tftpc markers: stage=4 fd=1 buf=0x9fccd0 total=510 last=514 block=0x100 done=0x5a5a5a5 +[.] server RRQ (dwt/loader/evidence/hostload/serve_tftp_marker.log): 15:31:47 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) +[+] TFTP fetch verified byte-for-byte: 510 B at 0x009fccd0 (sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749) +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 d0 cc 9f 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x009fccd0, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fe310 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 268 -> 794 (child scheduled) +[+] PASS: status=0 pcb=0x003fe310 entry=0x018c0000 (tftp_marker_boot3) diff --git a/dwt/loader/evidence/hostload/tftp_marker_boot4.log b/dwt/loader/evidence/hostload/tftp_marker_boot4.log new file mode 100644 index 0000000..d352498 --- /dev/null +++ b/dwt/loader/evidence/hostload/tftp_marker_boot4.log @@ -0,0 +1,34 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/marker.coff: 510 B, 3 sections, entry=0x018c0000 sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749 + .text paddr=0x018c0000 size=656 bits (82 B) nreloc=0 + .data paddr=0x018d0000 size=64 bits (8 B) nreloc=0 + .bss paddr=0x018d8000 size=64 bits (8 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] tftpc poked 694 B at 0x01870000 (347 words, 0 differing) +[.] jump returned 0x00000000 (0) +[.] tftpc markers: stage=4 fd=1 buf=0x9fccd0 total=510 last=514 block=0x100 done=0x5a5a5a5 +[.] server RRQ (dwt/loader/evidence/hostload/serve_tftp_marker.log): 15:32:16 RRQ 192.168.99.2:1025 requested 'dwt/tcpip/probe.bin' (510 bytes) +[+] TFTP fetch verified byte-for-byte: 510 B at 0x009fccd0 (sha256=519e4724aa537436a35f5e49a3306b3f6bcebdc216a0ce4c103822b0df28d749) +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 d0 cc 9f 00 fe 01 00 00 01 00 00 00 (magic 4C44/5231, buf=0x009fccd0, len=510, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x018c0000 + +0x040 text_addr 0x018c0000 + +0x060 text_size 0x00000290 + +0x080 data_addr 0x018d0000 + +0x0a0 data_size 0x00000040 + +0x0c0 bss_addr 0x018d8000 + +0x0e0 bss_size 0x00000040 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fe310 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x000001fe + +0x180 loader_base 0x01880000 +[.] marker start 0x018c0000 (want 0x018c0000) +[.] marker data 0xdeadbeef (want 0xdeadbeef) +[.] marker data2 0x12345678 (want 0x12345678) +[.] marker bss 0x00000000 (want 0x00000000) +[.] marker count 269 -> 14890 (child scheduled) +[+] PASS: status=0 pcb=0x003fe310 entry=0x018c0000 (tftp_marker_boot4) diff --git a/dwt/loader/evidence/hostload/xhello_boot3.log b/dwt/loader/evidence/hostload/xhello_boot3.log new file mode 100644 index 0000000..dec1b94 --- /dev/null +++ b/dwt/loader/evidence/hostload/xhello_boot3.log @@ -0,0 +1,30 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/xhello.coff: 774 B, 3 sections, entry=0x01840000 sha256=a8b3014d27deb97adcebb418a5d14da51fc3c11559e84923ede72e260d3e7271 + .data paddr=0x00000000 size=0 bits (0 B) nreloc=0 + .bss paddr=0x00000000 size=0 bits (0 B) nreloc=0 + .text paddr=0x01840000 size=3120 bits (390 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007c82d0 (8159952) +[+] jump(malloc) -> 0x007c82d0; bit 0x007c82d0 = byte 0x0f905a, 774 bytes, bit range 0x007c82d0..0x007c9b00 +[+] COFF poked 774 B at 0x007c82d0 (387 words, 0 differing bytes) + readback[0:774] 90 00 03 00 0c e0 d4 6a 2e 02 00 00 0c 00 00 00 1c 00 03 01 08 01 c7 00 30 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84 01 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 2e 74 65 78 74 00 00 00 00 00 84 01 00 00 84 01 30 0c 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 50 05 40 07 8f 09 00 ff 8f 07 20 04 89 01 8e 07 00 04 89 01 e0 09 01 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 48 e9 ac 3f 0e 92 5f 0d d0 58 b4 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 88 07 60 01 89 01 e0 09 04 00 00 00 08 48 00 cb 91 00 e0 09 02 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 48 e9 ac 3f 0e 92 5f 0d 70 25 9c 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 0b 4d 8b 07 00 01 89 01 6b 4d 72 ca e0 09 03 00 00 00 80 07 40 01 89 01 6a b7 80 04 4a b7 40 00 8a 07 10 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 00 00 00 00 0e 92 0e 92 e0 09 02 00 00 00 0e 92 e0 09 c8 00 00 00 0e 92 e0 09 90 01 00 00 0e 92 e0 09 64 00 00 00 0e 92 0e 92 4e 93 6e 93 5f 0d 90 1b d4 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 0a 4d 8a 07 20 01 89 01 e0 09 04 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 4e 93 6e 93 5f 0d b0 45 d6 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 e0 09 05 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 00 00 00 00 0e 92 6e 93 5f 0d b0 f6 d9 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 88 07 30 01 89 01 e0 09 06 00 00 00 80 07 40 01 89 01 af 09 ff 00 e8 09 00 00 00 00 60 09 2e 74 65 78 74 00 00 00 00 00 84 01 03 00 00 00 03 01 30 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 00 00 00 02 00 00 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 74 65 78 74 00 00 00 00 00 84 01 03 00 00 00 02 00 65 74 65 78 74 00 00 00 30 0c 84 01 03 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 02 00 65 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 00 00 00 02 00 00 00 02 00 65 6e 64 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 d0 82 7c 00 06 03 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007c82d0, len=774, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x01840000 + +0x040 text_addr 0x01840000 + +0x060 text_size 0x00000c30 + +0x080 data_addr 0x00000000 + +0x0a0 data_size 0x00000000 + +0x0c0 bss_addr 0x00000000 + +0x0e0 bss_size 0x00000000 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fe0d0 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x00000306 + +0x180 loader_base 0x01880000 +[.] xhello stage=6 strlen=4 +[+] screenshot dwt/loader/evidence/hostload/hostload_xhello_boot3_xhello.png (6696 bytes), raw dwt/loader/evidence/hostload/hostload_xhello_boot3_xhello.vram +[+] PASS: status=0 pcb=0x003fe0d0 entry=0x01840000 (xhello_boot3) diff --git a/dwt/loader/evidence/hostload/xhello_boot4.log b/dwt/loader/evidence/hostload/xhello_boot4.log new file mode 100644 index 0000000..e65c3c1 --- /dev/null +++ b/dwt/loader/evidence/hostload/xhello_boot4.log @@ -0,0 +1,30 @@ +[.] COFF /home/arti/code/k-space/vt1200/dwt/loader/build/xhello.coff: 774 B, 3 sections, entry=0x01840000 sha256=a8b3014d27deb97adcebb418a5d14da51fc3c11559e84923ede72e260d3e7271 + .data paddr=0x00000000 size=0 bits (0 B) nreloc=0 + .bss paddr=0x00000000 size=0 bits (0 B) nreloc=0 + .text paddr=0x01840000 size=3120 bits (390 B) nreloc=0 +[.] connected 192.168.99.2:771; opcode 7 -> flag=0x0 b'Done\n\x00' +[.] jump returned 0x007c9070 (8163440) +[+] jump(malloc) -> 0x007c9070; bit 0x007c9070 = byte 0x0f920e, 774 bytes, bit range 0x007c9070..0x007ca8a0 +[+] COFF poked 774 B at 0x007c9070 (387 words, 0 differing bytes) + readback[0:774] 90 00 03 00 0c e0 d4 6a 2e 02 00 00 0c 00 00 00 1c 00 03 01 08 01 c7 00 30 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84 01 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 2e 62 73 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 2e 74 65 78 74 00 00 00 00 00 84 01 00 00 84 01 30 0c 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 50 05 40 07 8f 09 00 ff 8f 07 20 04 89 01 8e 07 00 04 89 01 e0 09 01 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 48 e9 ac 3f 0e 92 5f 0d d0 58 b4 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 88 07 60 01 89 01 e0 09 04 00 00 00 08 48 00 cb 91 00 e0 09 02 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 48 e9 ac 3f 0e 92 5f 0d 70 25 9c 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 0b 4d 8b 07 00 01 89 01 6b 4d 72 ca e0 09 03 00 00 00 80 07 40 01 89 01 6a b7 80 04 4a b7 40 00 8a 07 10 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 00 00 00 00 0e 92 0e 92 e0 09 02 00 00 00 0e 92 e0 09 c8 00 00 00 0e 92 e0 09 90 01 00 00 0e 92 e0 09 64 00 00 00 0e 92 0e 92 4e 93 6e 93 5f 0d 90 1b d4 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 0a 4d 8a 07 20 01 89 01 e0 09 04 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 4e 93 6e 93 5f 0d b0 45 d6 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 e0 09 05 00 00 00 80 07 40 01 89 01 cf a3 ee 09 00 20 89 01 e0 09 00 00 00 00 0e 92 6e 93 5f 0d b0 f6 d9 3f af 07 20 04 89 01 ae 07 00 04 89 01 50 05 40 07 88 07 30 01 89 01 e0 09 06 00 00 00 80 07 40 01 89 01 af 09 ff 00 e8 09 00 00 00 00 60 09 2e 74 65 78 74 00 00 00 00 00 84 01 03 00 00 00 03 01 30 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 62 73 73 00 00 00 00 00 00 00 00 02 00 00 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 74 65 78 74 00 00 00 00 00 84 01 03 00 00 00 02 00 65 74 65 78 74 00 00 00 30 0c 84 01 03 00 00 00 02 00 2e 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 02 00 65 64 61 74 61 00 00 00 00 00 00 00 01 00 00 00 02 00 2e 62 73 73 00 00 00 00 00 00 00 00 02 00 00 00 02 00 65 6e 64 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 +[+] loader poked 1220 B at 0x01880000 (610 words, 0 differing) +[.] descriptor @ 0x01882c00: 44 4c 31 52 70 90 7c 00 06 03 00 00 01 00 00 00 (magic 4C44/5231, buf=0x007c9070, len=774, mode=1) +[.] jump returned 0x00000000 (0) +[.] loader A8=0x0 (OK) +[.] result block @ 0x1882d00: + +0x000 status 0x00000000 + +0x020 entry 0x01840000 + +0x040 text_addr 0x01840000 + +0x060 text_size 0x00000c30 + +0x080 data_addr 0x00000000 + +0x0a0 data_size 0x00000000 + +0x0c0 bss_addr 0x00000000 + +0x0e0 bss_size 0x00000000 + +0x100 relocs 0x00000000 + +0x120 pcb 0x003fe0d0 + +0x140 nscns 0x00000003 + +0x160 coff_len 0x00000306 + +0x180 loader_base 0x01880000 +[.] xhello stage=6 strlen=4 +[+] screenshot dwt/loader/evidence/hostload/hostload_xhello_boot4_xhello.png (6696 bytes), raw dwt/loader/evidence/hostload/hostload_xhello_boot4_xhello.vram +[+] PASS: status=0 pcb=0x003fe0d0 entry=0x01840000 (xhello_boot4) diff --git a/dwt/loader/hostload.py b/dwt/loader/hostload.py new file mode 100644 index 0000000..b5b4fb4 --- /dev/null +++ b/dwt/loader/hostload.py @@ -0,0 +1,574 @@ +#!/usr/bin/env python3 +"""hostload.py -- end-to-end host-side app loader over the stock rdebug service. + +One driver, one TCP connection to the terminal's `DEBUG TCP Port` (771): + + rdebug ---- malloc(size) --> bit pointer + ---- poke COFF ---> that buffer + ---- poke loader -> bit 0x01880000 + ---- poke descriptor @ 0x01882C00 + ---- jump 0x01880000 -> status in A8 + result block + ---- peek markers / screenshot + +The COFF loader itself (`dwt/loader/loader.asm`, 1220 B) is position-dependent +and lives at bit `0x01880000`. This script only supplies its input and reads +its result; it does not choose load addresses (the COFF section headers do) and +does not patch the ROM. + +Two transports for the COFF: + + * default -- poke the file into a `malloc`'d buffer from the host. + * --tftp -- poke the existing `dwt/tcpip/tftpc.bin` (bit 0x01870000), jump + it, and read the buffer/length it fetched. The TFTP server must be serving + the COFF *content* for any requested name, because tftpc.asm's RRQ name is + fixed (`dwt/tcpip/probe.bin`): + + sudo python3 -u dwt/tcpip/serve_probe.py 192.168.99.1 --bootp \ + --file dwt/loader/build/marker.coff + + That server must already be answering BOOTP so the terminal has 192.168.99.2. + +Addresses are TMS34010 **bit** addresses throughout; `poke`/`peek` convert by +8 bits per byte, and the malloc return is used verbatim as a bit pointer. + +Exit status: 0 only when the loader returned status 0, the result block is +consistent, and the app's own evidence verifies (markers, or X stage + frame). + +Examples: + + # marker app: markers at 0x018E0000.. (start/data/data2/bss/counter) + python3 dwt/loader/hostload.py --host 192.168.99.2 \ + --coff dwt/loader/build/marker.coff --marker \ + --out dwt/loader/evidence/hostload --tag marker + + # xhello: X window, verified by stage==6 and a VRAM screenshot + python3 dwt/loader/hostload.py --host 192.168.99.2 \ + --coff dwt/loader/build/xhello.coff \ + --out dwt/loader/evidence/hostload --tag xhello + + # self-contained fetch: no COFF poke, tftpc fetches it into malloc memory + python3 dwt/loader/hostload.py --host 192.168.99.2 --tftp \ + --coff dwt/loader/build/marker.coff --marker \ + --tftp-log dwt/loader/evidence/hostload/serve_tftp_marker.log \ + --tag tftp_marker +""" +from __future__ import annotations + +import argparse +import hashlib +import os +import struct +import sys +import time + +HERE = os.path.dirname(os.path.abspath(__file__)) # dwt/loader +DWT = os.path.dirname(HERE) # dwt +ROOT = os.path.dirname(DWT) # repo root +sys.path.insert(0, DWT) + +import exploit # noqa: E402 + +# --- fixed loader contract (dwt/notes/LOADER_CROSS.md) --------------------- +LOADER_BASE = 0x01880000 +LOADER_PAGE_END = 0x01883200 +DESC = 0x01882C00 +RESULT = 0x01882D00 +MALLOC = 0x3F701230 +RAM_BITS = 0x2000000 # 4 MiB, in bits + +# Result-block cell offsets. These are BIT offsets (loader.asm uses +# `RESULT_BASE+020h`, and the TMS34010 assembler's addresses are bit +# addresses), so 0x020 bits is byte +4, not +0x20 bytes. The block is 13 +# adjacent 32-bit cells, 52 bytes total. +RESULT_CELLS = { + 0x000: "status", + 0x020: "entry", + 0x040: "text_addr", + 0x060: "text_size", + 0x080: "data_addr", + 0x0A0: "data_size", + 0x0C0: "bss_addr", + 0x0E0: "bss_size", + 0x100: "relocs", + 0x120: "pcb", + 0x140: "nscns", + 0x160: "coff_len", + 0x180: "loader_base", +} +RESULT_BYTES = 0x34 # 0x180 bits + 4 bytes + +STATUS_NAMES = { + 0: "OK", + 1: "bad descriptor", + 2: "truncated COFF / section headers", + 3: "bad COFF magic", + 4: "section size not whole words", + 5: "target outside RAM", + 6: "target overlaps loader page or COFF buffer", + 7: "relocation records present (unsupported)", + 8: "target not in a free-list block", + 9: "no entry point", + 10: "create_process returned 0", +} + +# tftpc.asm markers (dwt/tcpip/tftpc.asm) +TFTPC_BASE = 0x01870000 +TFTP_MARK = 0x0187C000 +TFTP_DONE = 0x05A5A5A5 + +# app marker cells +MARKER_CELLS = [ + (0x018E0000, "start"), + (0x018E0020, "data"), + (0x018E0040, "data2"), + (0x018E0060, "bss"), + (0x018E0080, "count"), +] +XHELLO_STAGE = 0x01890140 +XHELLO_STRLEN = 0x01890160 + + +# --------------------------------------------------------------------------- +# small helpers +# --------------------------------------------------------------------------- + +def parse_int(text: str) -> int: + text = text.strip().replace("_", "") + if text.lower().startswith("0x"): + return int(text, 16) + if any(c in "abcdefABCDEF" for c in text): + return int(text, 16) + return int(text, 10) + + +def u16(d: bytes, off: int) -> int: + return struct.unpack_from(" int: + return struct.unpack_from(" bool: + """Half-open ranges [a0,a1) and [b0,b1) in the same unit.""" + return a0 < b1 and b0 < a1 + + +def parse_coff(data: bytes) -> dict: + """Minimal TI COFF header/section reader (same fields as coff.py).""" + if len(data) < 20: + raise ValueError("shorter than a COFF file header") + magic, nscns = u16(data, 0), u16(data, 2) + opthdr = u16(data, 16) + if magic != 0x0090: + raise ValueError(f"COFF magic {magic:#06x}, expected 0x0090") + if 20 + opthdr > len(data): + raise ValueError("optional header past EOF") + entry = textstart = None + if opthdr: + entry = u32(data, 20 + 16) + textstart = u32(data, 20 + 20) + sections = [] + base = 20 + opthdr + for i in range(nscns): + off = base + i * 40 + if off + 40 > len(data): + raise ValueError(f"section header {i} past EOF") + name = data[off:off + 8].rstrip(b"\0").decode("latin-1") + paddr = u32(data, off + 8) + size = u32(data, off + 16) + scnptr = u32(data, off + 20) + nreloc = u16(data, off + 32) + flags = u32(data, off + 36) + sections.append(dict(name=name, paddr=paddr, size=size, + scnptr=scnptr, nreloc=nreloc, flags=flags)) + return dict(magic=magic, nscns=nscns, opthdr=opthdr, + entry=entry or 0, textstart=textstart or 0, + sections=sections) + + +def poke_bytes(rd: exploit.RDebug, bit_addr: int, data: bytes, + chunk: int = exploit.MAX_XFER) -> None: + for off in range(0, len(data), chunk): + rd.poke(bit_addr + off * 8, data[off:off + chunk]) + + +def peek_bytes(rd: exploit.RDebug, bit_addr: int, length: int) -> bytes: + out = bytearray() + while len(out) < length: + n = min(exploit.MAX_XFER, length - len(out)) + out += rd.peek(bit_addr + len(out) * 8, n) + return bytes(out) + + +def peek_u32(rd: exploit.RDebug, bit_addr: int) -> int: + return struct.unpack(" tuple[int, int]: + """Peek *data* back and return (words, differing bytes).""" + got = peek_bytes(rd, bit_addr, len(data)) + bad = sum(1 for a, b in zip(got, data) if a != b) + return (len(data) + 1) // 2, bad + + +def check_buffer(ptr: int, nbytes: int, coff: dict) -> list[str]: + """Sanity-check a malloc'd bit pointer. Returns a list of problems.""" + problems = [] + end = ptr + nbytes * 8 + if ptr == 0: + problems.append("malloc returned 0") + return problems + if ptr % 8: + problems.append(f"pointer {ptr:#010x} is not byte-aligned " + f"(byte offset {ptr % 8})") + if ptr < 0x100 or end > RAM_BITS: + problems.append(f"range {ptr:#010x}..{end:#010x} is outside RAM") + if overlaps(ptr, end, LOADER_BASE, LOADER_PAGE_END): + problems.append("buffer overlaps the loader page") + for sec in coff["sections"]: + if sec["size"] and overlaps(ptr, end, sec["paddr"], + sec["paddr"] + sec["size"]): + problems.append(f"buffer overlaps section {sec['name']} " + f"at {sec['paddr']:#010x}") + for cell, name in MARKER_CELLS: + if overlaps(ptr, end, cell, cell + 0x20): + problems.append(f"buffer overlaps marker cell {name}") + if overlaps(ptr, end, 0x01890100, 0x01890170): + problems.append("buffer overlaps the xhello marker cells") + return problems + + +def describe_pointer(ptr: int, nbytes: int) -> str: + return (f"bit {ptr:#010x} = byte {ptr >> 3:#08x}, {nbytes} bytes, " + f"bit range {ptr:#010x}..{ptr + nbytes * 8:#010x}") + + +# --------------------------------------------------------------------------- +# screenshot / frame helpers +# --------------------------------------------------------------------------- + +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.""" + 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 out_raw: + with open(out_raw, "wb") as fh: + fh.write(data) + return data + + +def wait_for_frame(path: str, timeout: float) -> bool: + end = time.monotonic() + timeout + while time.monotonic() < end: + if os.path.exists(path) and os.path.getsize(path) > 0: + return True + time.sleep(0.5) + return os.path.exists(path) and os.path.getsize(path) > 0 + + +# --------------------------------------------------------------------------- +# the loader sequence +# --------------------------------------------------------------------------- + +def read_desc(rd: exploit.RDebug) -> bytes: + return peek_bytes(rd, DESC, 16) + + +def write_desc(rd: exploit.RDebug, buf: int, length: int) -> bytes: + desc = struct.pack(" dict: + raw = peek_bytes(rd, RESULT, RESULT_BYTES) + # RESULT_CELLS keys are bit offsets; the peeked buffer is bytes. + return {name: u32(raw, off // 8) for off, name in RESULT_CELLS.items()} + + +def run_loader(rd: exploit.RDebug, buf: int, coff_len: int, + jump_wait: float) -> tuple[int, dict]: + # Rewritten immediately before the call: create_process uses ARG_AREA + # (0x01882B00) and its 0x100-bit call frame lands on the descriptor, so a + # descriptor left from a previous run is not trustworthy. + desc = write_desc(rd, buf, coff_len) + print(f"[.] descriptor @ {DESC:#010x}: {desc.hex(' ')} " + f"(magic 4C44/5231, buf={buf:#010x}, len={coff_len}, mode=1)") + res = rd.jump(LOADER_BASE, [], wait=True, wait_timeout=jump_wait) + if res is None: + raise RuntimeError(f"loader at {LOADER_BASE:#010x} did not return within " + f"{jump_wait}s") + status = res[0] + result = read_result(rd) + print(f"[.] loader A8={status:#x} ({STATUS_NAMES.get(status, 'unknown')})") + print("[.] result block @ {:#x} (cell offsets are bit offsets):".format( + RESULT)) + for off, name in RESULT_CELLS.items(): + print(f" +{off:#05x} {name:<12} {result[name]:#010x}") + problems = [] + if status != 0: + problems.append(f"loader status {status} ({STATUS_NAMES.get(status, '?')})") + if result["status"] != status: + problems.append(f"result status {result['status']} != A8 {status}") + if result["loader_base"] != LOADER_BASE: + problems.append(f"result loader_base {result['loader_base']:#x} != " + f"{LOADER_BASE:#x}") + if result["pcb"] == 0: + problems.append("create_process returned a null PCB") + if result["coff_len"] != coff_len: + problems.append(f"result coff_len {result['coff_len']} != {coff_len}") + if problems: + raise RuntimeError("; ".join(problems)) + return status, result + + +def verify_markers(rd: exploit.RDebug, result: dict, settle: float) -> list[str]: + problems = [] + vals = {name: peek_u32(rd, cell) for cell, name in MARKER_CELLS} + time.sleep(settle) + vals2 = {name: peek_u32(rd, cell) for cell, name in MARKER_CELLS} + for name, want in (("start", result["entry"]), ("data", 0xDEADBEEF), + ("data2", 0x12345678), ("bss", 0)): + got = vals[name] + print(f"[.] marker {name:<6} {got:#010x} (want {want:#010x})") + if got != want: + problems.append(f"marker {name}={got:#x}, want {want:#x}") + c0, c1 = vals["count"], vals2["count"] + print(f"[.] marker count {c0} -> {c1} (child scheduled)") + if c1 == c0: + problems.append("marker counter did not advance") + return problems + + +def verify_xhello(rd: exploit.RDebug, out_dir: str, tag: str, settle: float, + take_shot: bool) -> list[str]: + problems = [] + time.sleep(settle) + stage = peek_u32(rd, XHELLO_STAGE) + strlen = peek_u32(rd, XHELLO_STRLEN) + print(f"[.] xhello stage={stage} strlen={strlen}") + if stage != 6: + problems.append(f"xhello stage={stage}, want 6 (XSync done)") + if strlen != 4: + problems.append(f"xhello strlen={strlen}, want 4 " + f"(calling-convention check)") + if take_shot: + png = os.path.join(out_dir, f"hostload_{tag}_xhello.png") + data = screenshot_vram(rd, png) + print(f"[+] screenshot {png} ({os.path.getsize(png)} bytes, " + f"{len(data)} bytes of VRAM)") + return problems + + +def tftp_fetch(rd: exploit.RDebug, tftpc_path: str, coff_len: int, + jump_wait: float) -> tuple[int, int]: + tftpc = open(tftpc_path, "rb").read() + poke_bytes(rd, TFTPC_BASE, tftpc) + words, bad = compare(rd, TFTPC_BASE, tftpc) + print(f"[.] tftpc poked {len(tftpc)} B at {TFTPC_BASE:#010x} " + f"({words} words, {bad} differing)") + if bad: + raise RuntimeError("tftpc readback mismatch") + res = rd.jump(TFTPC_BASE, [], wait=True, wait_timeout=jump_wait) + if res is None: + raise RuntimeError(f"tftpc at {TFTPC_BASE:#010x} did not return within " + f"{jump_wait}s (server running? file served?)") + marks = {name: peek_u32(rd, TFTP_MARK + off) + for off, name in ((0x00, "stage"), (0x20, "fd"), (0x40, "buf"), + (0x60, "total"), (0x80, "last"), + (0xA0, "block"), (0xC0, "done"))} + print("[.] tftpc markers: " + " ".join( + f"{k}={v:#x}" if k in ("buf", "done", "block") else f"{k}={v}" + for k, v in marks.items())) + if marks["stage"] != 4 or marks["done"] != TFTP_DONE: + raise RuntimeError("tftpc did not complete (stage/done marker wrong)") + if marks["total"] != coff_len: + raise RuntimeError(f"tftpc fetched {marks['total']} bytes, " + f"COFF is {coff_len}") + return marks["buf"], marks["total"] + + +def print_tftp_rrq(path: str | None) -> None: + if not path or not os.path.exists(path): + return + lines = [ln.rstrip() for ln in open(path, errors="replace") if "RRQ" in ln] + if lines: + print(f"[.] server RRQ ({path}): {lines[-1]}") + + +# --------------------------------------------------------------------------- +# main +# --------------------------------------------------------------------------- + +def main(argv: list[str]) -> int: + ap = argparse.ArgumentParser( + description="End-to-end rdebug app loader: malloc -> poke COFF -> " + "COFF loader @0x01880000 -> create_process -> verify.", + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--host", default="192.168.99.2") + ap.add_argument("--port", type=int, default=771) + ap.add_argument("--timeout", type=float, default=10.0) + ap.add_argument("--coff", required=True, help="linked GSPLNK COFF image") + ap.add_argument("--loader", default=os.path.join(HERE, "build", "loader.bin"), + help="raw loader image (default dwt/loader/build/loader.bin)") + ap.add_argument("--no-poke-loader", action="store_true", + help="do not write the loader; verify it is already resident") + ap.add_argument("--marker", action="store_true", + help="verify marker.coff evidence cells (otherwise inferred " + "from the file name)") + ap.add_argument("--tftp", action="store_true", + help="fetch the COFF with dwt/tcpip/tftpc.bin instead of " + "poking it") + ap.add_argument("--tftpc", default=os.path.join(ROOT, "dwt", "tcpip", + "build", "tftpc.bin"), + help="raw TFTP client image (default dwt/tcpip/build/tftpc.bin)") + ap.add_argument("--tftp-log", default=None, + help="server log to quote the RRQ line from (optional)") + ap.add_argument("--frame", type=parse_int, default=None, metavar="N", + help="wait for MAME's VT1200_DUMP_FRAME=N PPM (boot-relative; " + "the dump must be configured on the MAME side)") + ap.add_argument("--dump-dir", default=os.getcwd(), + help="directory searched for vt1200-frame-N.ppm") + ap.add_argument("--frame-timeout", type=float, default=120.0) + ap.add_argument("--out", default=os.path.join(HERE, "evidence", "hostload"), + help="evidence directory (default dwt/loader/evidence/hostload)") + ap.add_argument("--tag", default=None, + 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("--no-screenshot", action="store_true", + help="do not grab VRAM for xhello") + ap.add_argument("--jump-wait", type=float, default=20.0, + help="seconds to wait for the loader call to return") + ap.add_argument("--verbose", action="store_true") + args = ap.parse_args(argv[1:]) + + coff_path = os.path.abspath(args.coff) + coff = open(coff_path, "rb").read() + try: + info = parse_coff(coff) + except ValueError as exc: + print(f"error: {coff_path}: {exc}", file=sys.stderr) + return 2 + tag = args.tag or os.path.splitext(os.path.basename(coff_path))[0] + os.makedirs(args.out, exist_ok=True) + marker_mode = args.marker or "marker" in os.path.basename(coff_path).lower() + xhello_mode = "xhello" in os.path.basename(coff_path).lower() + + print(f"[.] COFF {coff_path}: {len(coff)} B, {info['nscns']} sections, " + f"entry={info['entry'] or info['textstart']:#010x} " + f"sha256={hashlib.sha256(coff).hexdigest()}") + for sec in info["sections"]: + print(f" {sec['name']:<8} paddr={sec['paddr']:#010x} " + f"size={sec['size']} bits ({sec['size'] // 8} B) " + f"nreloc={sec['nreloc']}") + + rd = exploit.RDebug(args.host, args.port, args.timeout, args.verbose) + rc = 1 + try: + rd.connect() + flag, payload = rd.liveness(7) + print(f"[.] connected {args.host}:{args.port}; opcode 7 -> " + f"flag={flag:#x} {payload!r}") + + # 1. allocate the COFF buffer (or fetch it with the TFTP client) + if args.tftp: + buf, fetched = tftp_fetch(rd, args.tftpc, len(coff), args.jump_wait) + print_tftp_rrq(args.tftp_log) + problems = check_buffer(buf, fetched, info) + if problems: + raise RuntimeError("unsafe TFTP buffer: " + "; ".join(problems)) + got = peek_bytes(rd, buf, fetched) + if got != coff: + diff = next((i for i, (a, b) in enumerate(zip(got, coff)) + if a != b), None) + raise RuntimeError(f"TFTP buffer differs from {coff_path} " + f"(first mismatch at {diff})") + print(f"[+] TFTP fetch verified byte-for-byte: {fetched} B at " + f"{buf:#010x} (sha256={hashlib.sha256(got).hexdigest()})") + else: + res = rd.jump(MALLOC, [len(coff)], wait=True, + wait_timeout=args.jump_wait) + if res is None: + raise RuntimeError("jump(malloc) did not return") + buf = res[0] + print(f"[+] jump(malloc) -> {buf:#010x}; " + f"{describe_pointer(buf, len(coff))}") + problems = check_buffer(buf, len(coff), info) + if problems: + raise RuntimeError("unsafe malloc buffer: " + "; ".join(problems)) + # 2. poke the COFF and prove the readback + poke_bytes(rd, buf, coff) + words, bad = compare(rd, buf, coff) + print(f"[+] COFF poked {len(coff)} B at {buf:#010x} " + f"({words} words, {bad} differing bytes)") + if bad: + raise RuntimeError("COFF readback mismatch") + first = min(exploit.MAX_XFER, len(coff)) + print(f" readback[0:{first}] {peek_bytes(rd, buf, first).hex(' ')}") + + # 3. loader resident? + loader = open(args.loader, "rb").read() + if args.no_poke_loader: + words, bad = compare(rd, LOADER_BASE, loader) + print(f"[.] --no-poke-loader: {args.loader} readback " + f"({words} words, {bad} differing)") + if bad: + raise RuntimeError("loader is not resident at " + f"{LOADER_BASE:#010x}") + else: + poke_bytes(rd, LOADER_BASE, loader) + words, bad = compare(rd, LOADER_BASE, loader) + print(f"[+] loader poked {len(loader)} B at {LOADER_BASE:#010x} " + f"({words} words, {bad} differing)") + if bad: + raise RuntimeError("loader readback mismatch") + + # 4. descriptor + call + result block + status, result = run_loader(rd, buf, len(coff), args.jump_wait) + + # 5. app evidence + if marker_mode: + problems = verify_markers(rd, result, args.settle) + elif xhello_mode: + problems = verify_xhello(rd, args.out, tag, args.settle, + not args.no_screenshot) + else: + problems = [] + print("[.] no app-specific verifier (name is neither marker nor " + "xhello); status/result only") + if problems: + raise RuntimeError("app verification failed: " + "; ".join(problems)) + + # 6. optional MAME frame dump (boot-relative, externally configured) + if args.frame is not None: + ppm = os.path.join(args.dump_dir, f"vt1200-frame-{args.frame}.ppm") + if wait_for_frame(ppm, args.frame_timeout): + print(f"[+] frame dump {ppm} " + f"({os.path.getsize(ppm)} bytes)") + else: + raise RuntimeError(f"no frame dump {ppm} within " + f"{args.frame_timeout}s") + + print(f"[+] PASS: status=0 pcb={result['pcb']:#010x} " + f"entry={result['entry']:#010x} ({tag})") + rc = 0 + except (OSError, exploit.ProtocolError, RuntimeError, ValueError) as exc: + print(f"[-] FAIL: {exc}", file=sys.stderr) + rc = 2 + finally: + rd.close() + return rc + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv)) diff --git a/dwt/notes/LOADER.md b/dwt/notes/LOADER.md index ddecf52..a341d17 100644 --- a/dwt/notes/LOADER.md +++ b/dwt/notes/LOADER.md @@ -477,3 +477,97 @@ the descriptor in `A8`; `LOADER_SNAP=1` writes a PNG at `LOADER_END`. | `dwt/loader/evidence/xhello_run.log` | xhello run | | `dwt/loader/evidence/loader_frame2650.png` | the xhello window | | `dwt/loader/evidence/reloc_refused.log` | `.obj` refused with status 7 | + +--- + +## 10. End-to-end host-side loader (rdebug): malloc -> poke -> load -> run + +Date: 2026-10-18. Driver: `dwt/loader/hostload.py`. Evidence: +`dwt/loader/evidence/hostload/` (its `README.md` indexes the logs and PNGs). +This is the integration of the two existing halves; the loader and the apps are +unchanged. + +### Exact sequence (one TCP connection to `192.168.99.2:771`) + +1. `opcode 7` liveness; the computed challenge is answered by + `dwt/challenge.py` (the `RDebug` default). +2. `jump 0x3F701230` (`malloc`) with **one** argument, the COFF byte length. + `jump` returns the callee's `A8`, i.e. a **bit** pointer. +3. Poke the COFF to that bit pointer in 1024-byte chunks + (`bit + off*8`, never `bit + off`) and `peek` it back: 510/510 or 774/774 + bytes equal, sha256 matches the local file. +4. Poke the raw loader (`build/loader.bin`, 1220 B) at bit `0x01880000`, then + `peek` it back (610 words, 0 differing). `--no-poke-loader` skips the write + and requires that readback to match. +5. Build the 16-byte descriptor at bit `0x01882C00` from **bit** offsets + +0/+0x10/+0x20/+0x40/+0x60 (bytes 0/2/4/8/12): + `44 4c 31 52 01 00 00 00`. +6. `jump 0x01880000` with **zero** arguments. The rdebug jump handler's + zero-arg path is a bare `CALL` after `MOVE A9,A8` with `A9 = 0`, so the + loader enters with `A8 = 0` and uses the fixed descriptor. (With N args the + stubs do not set `A8` to the descriptor either; `A8 = 0` is the reliable + calling convention from rdebug.) +7. Read the result block at bit `0x01882D00`, then app evidence: marker cells + by `peek`, or xhello `stage`/`strlen` plus a VRAM screenshot. + +### What worked (two or three fresh boots each) + +* `jump(malloc)` returns a usable, byte-aligned bit pointer in the firmware + heap: `0x007c7290` (byte `0x0F8E52`), `0x007c8030` (byte `0x0F9006`), + `0x007df450` (byte `0x0FBE8A`), `0x00adcd90`, `0x009fccd0`. These are far + below the loader page (`0x01880000`, byte `0x310000`) and below the current + apps (`.text` byte `0x318000`), and `hostload.py` rejects a pointer that + overlaps either, the loader page or the marker cells. +* The loader accepts a malloc'd buffer: status `0` and `A8 = 0` on every run. + Its free-list check (status 8) passed for `.text 0x018C0000` and for + `xhello` `.text 0x01840000`; the result block reports entry/text/data/bss, + `pcb != 0`, `nscns=3`, and `loader_base=0x01880000`. +* `create_process` really runs the app: `marker.coff` leaves + `start=0x018C0000`, `data=0xDEADBEEF`, `data2=0x12345678`, `bss=0`, and a + live counter; `xhello.coff` reaches `stage=6` (`XSync`) and its black + 400x200 window is visible at `(100,100)` in + `hostload_xhello_boot{3,4}_xhello.png`. +* `--tftp` also works: the existing `dwt/tcpip/tftpc.bin` (bit `0x01870000`) + fetches into its own `malloc` buffer (`stage=4`, `total=510`, + `done=0x05A5A5A5`); `peek` matches the COFF byte-for-byte, and that buffer is + fed to the same descriptor/loader. Server RRQ, boot 3 and 4: + `... requested 'dwt/tcpip/probe.bin' (510 bytes)`. + +### Two traps found + +1. **Result-block offsets are bits.** `loader.asm`'s `RESULT_BASE+020h` is + +4 **bytes**, so the block is 13 adjacent 32-bit cells (52 B), not cells at + byte intervals of 0x20. Reading at byte offsets `0x20, 0x40, ...` returns + `0x55555555` from the free heap beyond the real block; that was a host + parsing bug, not a loader failure. +2. **The descriptor is clobbered after a load.** A successful + `create_process` leaves a call frame at `0x01882C00` + (`0d 00 00 00 00 60 00 00`); `ARG_AREA` is `0x01882B00` and the + frame is 0x100 bits wide. The loader has already consumed the descriptor, + and the result block (`0x01882D00`) is untouched, but a second call must + rewrite the descriptor. `hostload.py` does so immediately before every + jump. + +### Limits + +* **No reservation.** `malloc` only finds a buffer; the loader's free-list + check is still a check. The apps stay linked at byte `0x318000`/`0x308000` + while allocations grow from the low free blocks; enough allocations on one + boot would eventually split the big block up to them. Fresh-boot runs are + safe; on a long-lived unit the caller must still choose a free link address. +* **`--tftp` needs a server that serves the COFF under tftpc's fixed name** + (`dwt/tcpip/probe.bin`); `tftpc.asm` has no filename argument. The server + used here was + `serve_probe.py 192.168.99.1 --bootp --file dwt/loader/build/marker.coff`. +* **`--frame N` cannot trigger a MAME dump.** It only waits for + `vt1200-frame-N.ppm` from an externally configured + `VT1200_DUMP_FRAME(S)`; frame numbers are boot-relative, so the load-relative + visual evidence is the rdebug VRAM screenshot. +* The loader is still position-dependent and fixed at `0x01880000`, and the + loaded images are position-dependent; none of this adds relocation. +* rdebug process only: `create_process` is used for the *app*, not for the + loader or the TFTP client. A `create_process` child previously returned `-1` + from `socket()` (TCPIP.md), so the fetch stays in the rdebug process. +* The real unit would need TCP 771 reachable and the same debug-gate state; + the emulator run uses the documented `VT1200_SKIP_LEVEL1=1` divergence to + reach the OS.