nx_printer_web_probe.nx source
↩ module page · 86 lines · 4050 B
1// nx_printer_web_probe.nx -- READ-ONLY recon of the printer's OWN embedded web UI (port 80). Drives a
2// sovereign HTTP GET to discover what settings the printer exposes (e.g. a toner "Continue mode" the
3// vendor app hides). Saves pages to knowledge/fetched/ for analysis. NO writes to the printer, NO firmware
4// -> never-brick (#26) by construction. Sovereign (reuses nx_ipp_transport socket helpers). license_tier: ORIGINAL
5
6import "nx_syscalls.nx"
7import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
8import "nx_ipp_transport.nx"
9const K_MAGIC_262144: i64 = 262144
10
11func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
12func pn(v: i64) -> i64 {
13 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
14 var m: i64 = v
15 let t: *u8 = sys_mmap(24); var k: i64 = 0
16 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
17 let b: *u8 = sys_mmap(24); var i: i64 = 0
18 while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
19 sys_write(1, b, k); return 0
20}
21func write_all(fd: i64, buf: *u8, len: i64) -> i64 {
22 var sent: i64 = 0
23 while sent < len {
24 let w: i64 = sys_write(fd, ((buf as i64) + sent) as *u8, len - sent)
25 if w <= 0 { return 0 - 1 }
26 sent = sent + w
27 }
28 return 0
29}
30
31// sovereign HTTP GET to a.b.c.d:port<path>; extract body into body_buf. out2[0]=status out2[1]=body len.
32func http_get(a: i64, b: i64, c: i64, d: i64, port: i64, path: *u8,
33 resp: *u8, resp_cap: i64, body: *u8, body_cap: i64, out2: *i64) -> i64 {
34 let req: *u8 = sys_mmap(512)
35 var o: i64 = 0
36 o = nx_ipt_puts(req, o, "GET ")
37 o = nx_ipt_puts(req, o, path)
38 o = nx_ipt_puts(req, o, " HTTP/1.1\r\nHost: ")
39 o = nx_ipt_puti(req, o, a); req[o] = 46 as u8; o = o + 1
40 o = nx_ipt_puti(req, o, b); req[o] = 46 as u8; o = o + 1
41 o = nx_ipt_puti(req, o, c); req[o] = 46 as u8; o = o + 1
42 o = nx_ipt_puti(req, o, d)
43 o = nx_ipt_puts(req, o, "\r\nUser-Agent: nishi\r\nConnection: close\r\n\r\n")
44
45 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
46 if fd < 0 { return NX_IPT_CONN_FAIL }
47 sys_set_socket_timeout(fd, 6)
48 let dest: *u8 = sys_mmap(16)
49 nx_ipt_sockaddr(dest, a, b, c, d, port)
50 if nx_connect_bounded(fd, dest, 16, NX_CONN_DEFAULT_MS) != 0 { sys_close(fd); return NX_IPT_CONN_FAIL }
51 if nx_ipt_send_all(fd, req, o) != 0 { sys_close(fd); return NX_IPT_CONN_FAIL }
52 var total: i64 = 0
53 var keep: i64 = 1
54 while keep == 1 {
55 if total >= resp_cap { keep = 0 }
56 else {
57 let r: i64 = sys_read(fd, ((resp as i64) + total) as *u8, resp_cap - total)
58 if r <= 0 { keep = 0 }
59 else { total = total + r }
60 }
61 }
62 sys_close(fd)
63 return nx_ipt_extract_body(resp, total, body, body_cap, out2)
64}
65
66func fetch_save(a: i64, b: i64, c: i64, d: i64, path: *u8, outpath: *u8) -> i64 {
67 let resp: *u8 = sys_mmap(K_MAGIC_262144)
68 let body: *u8 = sys_mmap(K_MAGIC_262144)
69 let out2: *i64 = sys_mmap(16) as *i64
70 let v: i64 = http_get(a, b, c, d, 80, path, resp, K_MAGIC_262144, body, K_MAGIC_262144, out2)
71 p("GET "); p(path); p(" -> ")
72 if v != NX_IPT_OK { p("transport="); p(nx_ipt_verdict_name(v)); p("\n"); return 0 }
73 p("http="); pn(out2[0]); p(" body="); pn(out2[1]); p("B saved="); p(outpath); p("\n")
74 let fd: i64 = sys_openat_wr(outpath, 0x1a4)
75 if fd >= 0 { write_all(fd, body, out2[1]); sys_close(fd) }
76 return 0
77}
78
79func main() -> i64 {
80 p("=== Brother web-UI recon (READ-ONLY) ===\n")
81 fetch_save(192, 168, 8, 127, "/", "knowledge/fetched/brother_web_root.html\x00" as *u8)
82 fetch_save(192, 168, 8, 127, "/general/status.html", "knowledge/fetched/brother_web_status.html\x00" as *u8)
83 fetch_save(192, 168, 8, 127, "/general/information.html", "knowledge/fetched/brother_web_info.html\x00" as *u8)
84 fetch_save(192, 168, 8, 127, "/general/replacetoner.html", "knowledge/fetched/brother_web_replacetoner.html\x00" as *u8)
85 sys_exit(0); return 0
86}