nx_ff_cookies.nx source
↩ module page · 128 lines · 7178 B
1// nx_ff_cookies.nx -- SOVEREIGN Firefox/Waterfox cookies.sqlite reader (X-TORRENT-SPOOF R1).
2// WHY: javdb/livecamrips are Cloudflare-walled (403). To fetch them we reuse the operator's existing
3// browser session -- the cf_clearance (+ site session) cookie that their browser already earned.
4// Waterfox/Firefox store cookies UNENCRYPTED in cookies.sqlite, so a sovereign organ can read them
5// directly (Chrome's are DPAPI-encrypted -> not us). This parses the SQLite file format itself (no
6// external sqlite lib): scan every table-leaf page, decode each record, emit name=value where the
7// host column matches the target domain. moz_cookies column order: 0=id 1=originAttributes 2=name
8// 3=value 4=host 5=path ... -> name=col2, value=col3, host=col4.
9// argv[1]=cookies.sqlite path argv[2]=domain substring (e.g. "javdb") -> prints "name=value | host"
10// v1: main DB only (not -wal). license_tier: ORIGINAL module: nishi-core.browser.ff_cookies
11import "nx_syscalls.nx"
12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
13const K_MAGIC_16777216: i64 = 16777216
14const K_MAGIC_65536: i64 = 65536
15const K_MAGIC_4096: i64 = 4096
16
17func ff_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
18// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
19// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
20// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
21// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
22func ff_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
23func ff_wbuf(fd: i64, buf: *u8, off: i64, len: i64) -> i64 { sys_write(fd, (buf as i64 + off) as *u8, len); return 0 }
24
25// SQLite varint (1..9 bytes, 7 bits/byte, high bit = continue; 9th byte uses all 8 bits). advances pos[0].
26func sq_varint(buf: *u8, pos: *i64) -> i64 {
27 var p: i64 = pos[0]; var v: i64 = 0; var i: i64 = 0; var done: i64 = 0
28 while done == 0 {
29 let b: i64 = buf[p] as i64; p = p + 1
30 if i == 8 { v = (v << 8) | b; done = 1 } else {
31 v = (v << 7) | (b & 0x7f)
32 if (b & 0x80) == 0 { done = 1 } else { i = i + 1 }
33 }
34 }
35 pos[0] = p; return v
36}
37func sq_be(buf: *u8, off: i64, len: i64) -> i64 { var v: i64=0; var i: i64=0; while i<len { v=(v<<8)|(buf[off+i] as i64); i=i+1 } return v }
38// does buf[off..off+len) contain the NUL-terminated needle?
39func sq_contains(buf: *u8, off: i64, len: i64, needle: *u8) -> i64 {
40 var nl: i64=0; while needle[nl]!=(0 as u8){nl=nl+1}
41 if nl==0 { return 1 }
42 var i: i64=0
43 while i+nl<=len { var j: i64=0; var ok: i64=1; while j<nl { if buf[off+i+j]!=needle[j] { ok=0; j=nl } else { j=j+1 } } if ok==1 { return 1 } i=i+1 }
44 return 0
45}
46// byte length of a column given its serial type
47func sq_collen(st: i64) -> i64 {
48 if st==0 { return 0 } if st==1 { return 1 } if st==2 { return 2 } if st==3 { return 3 }
49 if st==4 { return 4 } if st==5 { return 6 } if st==6 { return 8 } if st==7 { return 8 }
50 if st==8 { return 0 } if st==9 { return 0 }
51 return (st - 12) / 2 // text(odd>=13) + blob(even>=12) both floor to the byte length
52}
53
54func main(argc: i64, argv: *i64) -> i64 {
55 if argc < 3 { ff_w(1, "usage: nx_ff_cookies <cookies.sqlite> <domain>\n" as *u8); sys_exit(2); return 2 }
56 let path: *u8 = argv[1] as *u8
57 let domain: *u8 = argv[2] as *u8
58
59 let fd: i64 = sys_openat_rd(path)
60 if fd < 0 { ff_w(1, "ERR open cookies.sqlite\n" as *u8); sys_exit(1); return 1 }
61 let cap: i64 = K_MAGIC_16777216 // 16 MB
62 let buf: *u8 = sys_mmap(cap)
63 var n: i64 = 0; var go: i64 = 1
64 while go == 1 { if n >= cap { go = 0 } else { let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } } }
65 sys_close(fd)
66 if n < 100 { ff_w(1, "ERR cookies.sqlite too small\n" as *u8); sys_exit(1); return 1 }
67
68 var pagesize: i64 = sq_be(buf, 16, 2); if pagesize == 1 { pagesize = K_MAGIC_65536 }
69 let npages: i64 = n / pagesize
70 ff_w(1, "FF-COOKIES pagesize=" as *u8); ff_wn(1, pagesize); ff_w(1, " pages=" as *u8); ff_wn(1, npages); ff_w(1, " domain=" as *u8); ff_w(1, domain); ff_w(1, "\n" as *u8)
71
72 var found: i64 = 0
73 var pg: i64 = 0
74 while pg < npages {
75 let base: i64 = pg * pagesize
76 var hdroff: i64 = base; if pg == 0 { hdroff = base + 100 }
77 let ptype: i64 = buf[hdroff] as i64
78 if ptype == 13 { // 0x0D leaf table page
79 let ncell: i64 = sq_be(buf, hdroff + 3, 2)
80 let cparr: i64 = hdroff + 8
81 var c: i64 = 0
82 while c < ncell {
83 if c < K_MAGIC_4096 {
84 let cellptr: i64 = sq_be(buf, cparr + c*2, 2)
85 let celloff: i64 = base + cellptr
86 if celloff > 0 { if celloff < n {
87 let pp: *i64 = sys_mmap(16) as *i64; pp[0] = celloff
88 sq_varint(buf, pp) // payload_len
89 sq_varint(buf, pp) // rowid
90 let recstart: i64 = pp[0]
91 let hp: *i64 = sys_mmap(16) as *i64; hp[0] = recstart
92 let hdrlen: i64 = sq_varint(buf, hp)
93 let hdrend: i64 = recstart + hdrlen
94 var dataoff: i64 = hdrend
95 var col: i64 = 0
96 var name_off: i64=0; var name_len: i64=0; var val_off: i64=0; var val_len: i64=0; var host_off: i64=0; var host_len: i64=0
97 let sp: *i64 = sys_mmap(16) as *i64; sp[0] = hp[0]
98 var guard: i64 = 0
99 while sp[0] < hdrend {
100 if guard > 64 { sp[0] = hdrend } else {
101 guard = guard + 1
102 let st: i64 = sq_varint(buf, sp)
103 let clen: i64 = sq_collen(st)
104 if col==2 { name_off=dataoff; name_len=clen }
105 if col==3 { val_off=dataoff; val_len=clen }
106 if col==4 { host_off=dataoff; host_len=clen }
107 dataoff = dataoff + clen
108 col = col + 1
109 }
110 }
111 if host_len > 0 { if host_len < 512 { if dataoff <= n {
112 if sq_contains(buf, host_off, host_len, domain) == 1 {
113 ff_wbuf(1, buf, name_off, name_len); ff_w(1, "=" as *u8); ff_wbuf(1, buf, val_off, val_len)
114 ff_w(1, " | host=" as *u8); ff_wbuf(1, buf, host_off, host_len); ff_w(1, "\n" as *u8)
115 found = found + 1
116 }
117 } } }
118 } }
119 }
120 c = c + 1
121 }
122 }
123 pg = pg + 1
124 }
125 ff_w(1, "FF-COOKIES found=" as *u8); ff_wn(1, found); ff_w(1, "\n" as *u8)
126 if found > 0 { sys_exit(0); return 0 }
127 sys_exit(1); return 1
128}