mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
dwt: NVRAM dump over rdebug (settings block) and LANCE address ROM read; both match the model
This commit is contained in:
1 parent
0db6dd2e65
commit
e2c18ee70b
4 files changed
+121
No files matched your search
Binary file not shown.
Binary file not shown.
@@ -251,3 +251,34 @@ The first attempt hung the Terminal Manager; this one completed. The hang is
|
||||
not deterministic. The mailbox watcher's reconnect storm during boot is one
|
||||
possible co-factor (it spawns a debug process per accepted connection), but the
|
||||
diagnostic reset is the other; a single success does not settle which.
|
||||
|
||||
### NVRAM and LANCE address ROM, read over rdebug
|
||||
|
||||
`dwt/nvram_dump.py` reads 4 KiB at bit `0x6000000` and extracts the 0x800
|
||||
settings bytes (low byte of each 16-bit word). Evidence:
|
||||
`real-unit-nvram-settings.bin`, `real-unit-nvram-raw.bin`.
|
||||
|
||||
Printable settings runs:
|
||||
|
||||
```
|
||||
0x26f 100.103.0.10 0x28f 172.20.51.0
|
||||
0x3cf 1.1.1.1 0x3ef 8.8.8.8
|
||||
0x40f retro.k-space.ee
|
||||
0x50f 100.103.0.1
|
||||
0x597 ROM 0x5e7 ROM
|
||||
0x5eb 103.255.254:69
|
||||
0x637 100.103.100.103 0x657 255.255.0.0
|
||||
0x677 Messages 0x6ca / 0x6ea VTE 1
|
||||
```
|
||||
|
||||
Both font-path fields persist: the selected `ROM` and the old TFTP
|
||||
`103.255.254:69`.
|
||||
|
||||
The LANCE address ROM at bit `0x6800000` reads (low bytes of the words):
|
||||
|
||||
```
|
||||
08 00 2b 16 4b 5a c1 86
|
||||
```
|
||||
|
||||
byte-identical to the MAME model. The `Ethernet Address ROM Test` passing is
|
||||
consistent with this.
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Dump the VT1200 NVR (user settings) over rdebug `peek`.
|
||||
|
||||
The NVR is at bit `0x6000000`, a 16-bit-wide region. The firmware's
|
||||
`io_settings_copy_expand` copies **0x800 settings bytes, one per 16-bit word**
|
||||
(and `io_settings_copy_linear` writes them back the same way). So:
|
||||
|
||||
raw region 4 KiB (0x800 words x 2 bytes)
|
||||
settings 2 KiB (the low byte of each word)
|
||||
|
||||
The low byte of a little-endian word is the even byte of the linear byte
|
||||
stream, so `raw[0::2]` is the settings block.
|
||||
|
||||
python3 dwt/nvram_dump.py --host 100.103.100.103
|
||||
python3 dwt/nvram_dump.py --host HOST --out nvram.bin --raw nvram-raw.bin
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import exploit
|
||||
|
||||
NVR_BASE = 0x6000000
|
||||
NVR_BYTES = 0x1000 # 0x800 words x 2 bytes
|
||||
SETTINGS_LEN = 0x800 # one byte per word
|
||||
|
||||
|
||||
def main(argv):
|
||||
ap = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
ap.add_argument("--host", default="100.103.100.103")
|
||||
ap.add_argument("--port", type=int, default=771)
|
||||
ap.add_argument("--timeout", type=float, default=8.0)
|
||||
ap.add_argument("--out", default="dwt/evidence/nvram-settings.bin")
|
||||
ap.add_argument("--raw", default=None, help="also write the 4 KiB raw region")
|
||||
ap.add_argument("--ascii", action="store_true", default=True,
|
||||
help="print strings/ASCII (default)")
|
||||
a = ap.parse_args(argv[1:])
|
||||
|
||||
rd = exploit.RDebug(a.host, a.port, a.timeout, False)
|
||||
rd.connect()
|
||||
raw = bytearray()
|
||||
try:
|
||||
for off in range(0, NVR_BYTES, exploit.MAX_XFER):
|
||||
n = min(exploit.MAX_XFER, NVR_BYTES - off)
|
||||
raw += rd.peek(NVR_BASE + off * 8, n)
|
||||
finally:
|
||||
rd.close()
|
||||
|
||||
settings = bytes(raw[0::2])
|
||||
with open(a.out, "wb") as fh:
|
||||
fh.write(settings)
|
||||
print(f"[+] raw {len(raw)} bytes at bit {NVR_BASE:#010x}")
|
||||
print(f"[+] settings {len(settings)} bytes -> {a.out}")
|
||||
if a.raw:
|
||||
with open(a.raw, "wb") as fh:
|
||||
fh.write(raw)
|
||||
print(f"[+] raw copy -> {a.raw}")
|
||||
|
||||
# Known landmarks from the NVRAM report and the unit's settings.
|
||||
for needle in (b"ROM", b"100.103", b"LAT_", b"DECW$FONT", b"192.168", b":69"):
|
||||
idx = settings.find(needle)
|
||||
if idx >= 0:
|
||||
print(f" {needle!r} at settings offset 0x{idx:03x}")
|
||||
|
||||
# Printable ASCII runs, useful for reading the settings block.
|
||||
runs, cur = [], bytearray()
|
||||
for i, b in enumerate(settings):
|
||||
if 32 <= b < 127:
|
||||
cur.append(b)
|
||||
else:
|
||||
if len(cur) >= 3:
|
||||
runs.append((i - len(cur), bytes(cur)))
|
||||
cur.clear()
|
||||
if len(cur) >= 3:
|
||||
runs.append((len(settings) - len(cur), bytes(cur)))
|
||||
print(f"[+] {len(runs)} printable runs:")
|
||||
for off, s in runs[:80]:
|
||||
print(f" 0x{off:03x} {s.decode('latin-1')}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main(sys.argv))
|
||||
except (exploit.ProtocolError, OSError) as exc:
|
||||
print(f"error: {exc}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Reference in new issue
Block a user