nishi_spawn_probe.nx source
↩ module page · 83 lines · 3628 B
1// nishi_spawn_probe.nx -- verify the GUI keystone's process-spawn imports (IAT slots 20-23):
2// CreateFileA, CreateProcessA, WaitForSingleObject, CloseHandle + generic ReadFile (19).
3// Spawns nishi_fetch.exe with stdout -> a temp file, waits, reads the file back, dumps it.
4// If this prints example.com's rendered text, in-process navigation is unblocked.
5
6import "nx_syscalls.nx"
7
8func win32(id: i64, args: *i64) -> i64 { return id }
9
10const W_ReadFile: i64 = 19
11const W_CreateFileA: i64 = 20
12const W_CreateProcessA: i64 = 21
13const W_WaitForSingleObject: i64 = 22
14const W_CloseHandle: i64 = 23
15
16func w32(p: *u8, o: i64, v: i64) -> i64 {
17 p[o]=(v&0xff) as u8; p[o+1]=((v>>8)&0xff) as u8; p[o+2]=((v>>16)&0xff) as u8; p[o+3]=((v>>24)&0xff) as u8; return 0
18}
19func wp(p: *u8, o: i64, v: i64) -> i64 { w32(p,o,v); w32(p,o+4, v / 4294967296); return 0 }
20func rd32(p: *u8, o: i64) -> i64 { return (p[o]&0xff)|((p[o+1]&0xff)<<8)|((p[o+2]&0xff)<<16)|((p[o+3]&0xff)<<24) }
21func rp(p: *u8, o: i64) -> i64 { return rd32(p,o) | (rd32(p,o+4) * 4294967296) }
22func scopy(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[o+i]=s[i]; i=i+1 } return o+i }
23
24func main() -> i64 {
25 let a: *i64 = sys_mmap(256) as *i64
26
27 let cmd: *u8 = sys_mmap(1024)
28 var cl: i64 = scopy(cmd, 0, "_offc/nishi_fetch.exe https://example.com/" as *u8)
29 cmd[cl] = 0 as u8
30 let app: *u8 = "_offc/nishi_fetch.exe" as *u8
31 let fname: *u8 = "_nav_page.txt" as *u8
32
33 // SECURITY_ATTRIBUTES: nLength=24, lpSD=0, bInheritHandle=1
34 let sa: *u8 = sys_mmap(32)
35 w32(sa, 0, 24); wp(sa, 8, 0); w32(sa, 16, 1)
36
37 // CreateFileA(temp, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, NORMAL, 0)
38 a[0]=fname as i64; a[1]=0x40000000; a[2]=1; a[3]=sa as i64; a[4]=2; a[5]=0x80; a[6]=0
39 let hout: i64 = win32(W_CreateFileA, a)
40 if hout == 0 { sys_exit(101); return 1 }
41 if hout == (0 - 1) { sys_exit(102); return 1 }
42
43 // STARTUPINFOA (104B): cb@0, dwFlags@60=USESTDHANDLES, hStdInput@80, hStdOutput@88, hStdError@96
44 let si: *u8 = sys_mmap(128)
45 w32(si, 0, 104); w32(si, 60, 0x100); wp(si, 80, 0); wp(si, 88, hout); wp(si, 96, hout)
46 let pi: *u8 = sys_mmap(32) // PROCESS_INFORMATION: hProcess@0, hThread@8
47
48 // CreateProcessA(app, cmd, 0, 0, bInherit=1, CREATE_NO_WINDOW, 0, 0, si, pi)
49 a[0]=app as i64; a[1]=cmd as i64; a[2]=0; a[3]=0; a[4]=1; a[5]=0x08000000; a[6]=0; a[7]=0; a[8]=si as i64; a[9]=pi as i64
50 win32(W_CreateProcessA, a)
51 let hproc: i64 = rp(pi, 0)
52 if hproc == 0 { sys_exit(103); return 1 }
53
54 a[0]=hproc; a[1]=0xFFFFFFFF; win32(W_WaitForSingleObject, a)
55 a[0]=hproc; win32(W_CloseHandle, a)
56 a[0]=rp(pi,8);win32(W_CloseHandle, a)
57 a[0]=hout; win32(W_CloseHandle, a)
58
59 // CreateFileA(temp, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, NORMAL, 0)
60 a[0]=fname as i64; a[1]=0x80000000; a[2]=1; a[3]=0; a[4]=3; a[5]=0x80; a[6]=0
61 let hin: i64 = win32(W_CreateFileA, a)
62 if hin == (0 - 1) { sys_exit(104); return 1 }
63
64 let buf: *u8 = sys_mmap(1048576)
65 let got: *u8 = sys_mmap(16)
66 var total: i64 = 0
67 var go: i64 = 1
68 while go == 1 {
69 w32(got, 0, 0)
70 a[0]=hin; a[1]=(buf as i64)+total; a[2]=1048576-total; a[3]=got as i64; a[4]=0
71 win32(W_ReadFile, a)
72 let n: i64 = rd32(got, 0)
73 if n <= 0 { go = 0 } else { total = total + n }
74 if total >= 1048576 { go = 0 }
75 }
76 a[0]=hin; win32(W_CloseHandle, a)
77
78 sys_write(1, buf, 90)
79 sys_write(1, "\n" as *u8, 1)
80 if total <= 0 { sys_exit(105); return 1 }
81 sys_exit(0)
82 return 0
83}