code wiki / (root) / nx_pe_compile_win_wsa.nx

nx_pe_compile_win_wsa.nx source

↩ module page · 221 lines · 11183 B

1// nx_pe_compile_win_wsa.nx -- W-NET-0: a Nishi organ initializes Winsock (2-DLL PE import table). 2// 3// The network arc's foundation. Every prior organ imported ONLY kernel32; TCP sockets live in 4// ws2_32.dll, so a serving container needs a PE that imports from TWO DLLs. This rung proves the 5// 2-DLL import table + the first ws2_32 call (WSAStartup) -- native, no VM. Unlocks socket/bind/ 6// listen/accept/recv/send (W-NET-1..) toward an HTTP server organ serving Elder UI on :5173. 7// 8// The keystone-linker redirects the genuine shim `nx_wsa_startup()` to a thunk that calls 9// ws2_32!WSAStartup. The thunk provides its OWN stack WSADATA buffer (so no allocator import needed): 10// nx_wsa_startup_thunk: 11// sub rsp, 0x228 ; 0x200 WSADATA + 0x28 shadow/align (rsp 8 mod16 -> 0x230 -> 0 mod16) 12// mov ecx, 0x0202 ; wVersionRequested = MAKEWORD(2,2) 13// lea rdx, [rsp+0x28] ; &WSADATA (above shadow) 14// call [rip+ws2_32!WSAStartup] ; rax = 0 on success 15// add rsp, 0x228 / ret 16// 17// 2 DLLs: kernel32 { ExitProcess } (entry-stub exit) + ws2_32 { WSAStartup }. IAT: ExitProcess 0x205C, 18// WSAStartup 0x206C. 19// 20// NO-FALSE-GREEN: source `{ let r = nx_wsa_startup(); return r + 70 }`. WSAStartup returns 0 on 21// success -> exit 70. If ws2_32 failed to bind, the OS loader fails (0xC0000139, exe won't run). So 22// exit 70 = Winsock genuinely initialized via the 2nd-DLL import. Tamper "WSAStartup"/"ws2_32.dll" -> 23// 0xC0000139 (proves the 2nd DLL is bound by the real OS). 24// 25// PIPELINE (build WSL sovereign, run native): src.nx -> nx_compile_x86_native.elf > /tmp/nxwin.s 26// -> nx_sov_build_run.elf nx_pe_compile_win_wsa -> _offc/nx_win_compiled_wsa.exe -> run native. 27// 28// HONEST SCOPE: WSAStartup only (Winsock init); socket/bind/listen/accept/recv/send are the next 29// W-NET rungs. Replicates keystone assemble (reuses axc_pass; no shared edit). 30// lineage_id: substrate_pe_compile_win_wsa_v1 31 32import "nx_syscalls.nx" 33import "nxasm_x86.nx" 34import "nx_pe_writer.nx" 35 36const NXWSA_CODE_CAP: i64 = 1048576 37const NXWSA_FILE_SIZE: i64 = 0x600 38const NXWSA_STUB_LEN: i64 = 18 39const NXWSA_THUNK_LEN: i64 = 31 40const NXWSA_TEXT_CAP: i64 = 0x200 41const NXWSA_RVA_TEXT: i64 = 0x1000 42const NXWSA_RVA_IDATA: i64 = 0x2000 43const NXWSA_FOFF_TEXT: i64 = 0x200 44const NXWSA_FOFF_IDATA:i64 = 0x400 45const NXWSA_IAT_EXIT: i64 = 0x205C 46const NXWSA_IAT_WSA: i64 = 0x206C 47 48func nxwsa_assemble(src: *u8, n: i64, out: *u8, out_cap: i64, p_main: *i64, p_sh: *i64) -> i64 { 49 let lab_off: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 50 let lab_len: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 51 let lab_addr: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 52 let lab_sec: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64 53 let op0: *i64 = sys_mmap(72) as *i64 // 9 slots for SIB (matches nxasm_x86) 54 let op1: *i64 = sys_mmap(72) as *i64 55 let op2: *i64 = sys_mmap(72) as *i64 // API DRIFT FIX: axc_pass gained op2 56 let scratch: *u8 = sys_mmap(64) 57 let posbox: *i64 = sys_mmap(16) as *i64 58 let n_lab_box: *i64 = sys_mmap(16) as *i64 59 n_lab_box[0] = 0 60 let lh: *i64 = sys_mmap(ASM_LH_SIZE * 8) as *i64 61 62 let text_size: i64 = axc_pass(src, n, out, 0, 0, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox) 63 if text_size < 0 { return text_size } 64 let n_lab: i64 = n_lab_box[0] 65 66 var main_a: i64 = 0 - 1 67 var sh_a: i64 = 0 - 1 68 var k: i64 = 0 69 while k < n_lab { 70 if lab_sec[k] == 1 { lab_addr[k] = lab_addr[k] + text_size } 71 if axc_tok_is(src, lab_off[k], lab_len[k], "main") == 1 { main_a = lab_addr[k] } 72 if axc_tok_is(src, lab_off[k], lab_len[k], "nx_wsa_startup") == 1 { sh_a = lab_addr[k] } 73 k = k + 1 74 } 75 axc_lh_build(src, lab_off, lab_len, n_lab, lh) 76 77 let total: i64 = axc_pass(src, n, out, text_size, 1, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox) 78 if total < 0 { return total } 79 if total > out_cap { return 0 - 200 } 80 p_main[0] = main_a 81 p_sh[0] = sh_a 82 return total 83} 84 85func nxwsa_emit_pe(buf: *u8, code: *u8, code_len: i64, main_off: i64, sh_off: i64) -> i64 { 86 if (buf as i64) == 0 { return 0 - NX_PE_BAD_INPUT } 87 if sh_off < 0 { return 0 - NX_PE_BAD_INPUT } 88 let thunk_off: i64 = NXWSA_STUB_LEN + code_len 89 let text_vsize: i64 = thunk_off + NXWSA_THUNK_LEN 90 if text_vsize > NXWSA_TEXT_CAP { return 0 - NX_PE_BAD_INPUT } 91 92 _w16(buf, 0, 0x5A4D) 93 _w32(buf, 0x3C, FOFF_PE_SIG) 94 _w32(buf, FOFF_PE_SIG, 0x00004550) 95 _w16(buf, FOFF_COFF + 0, PE_MACHINE_AMD64) 96 _w16(buf, FOFF_COFF + 2, 2) 97 _w16(buf, FOFF_COFF + 16, 0xF0) 98 _w16(buf, FOFF_COFF + 18, PE_CHAR_EXEC | PE_CHAR_LARGE_ADDR) 99 _w16(buf, FOFF_OPT + 0, PE_OH_MAGIC_PEPLUS) 100 _w8(buf, FOFF_OPT + 2, 1) 101 _w32(buf, FOFF_OPT + 4, 0x200) 102 _w32(buf, FOFF_OPT + 8, 0x200) 103 _w32(buf, FOFF_OPT + 16, NXWSA_RVA_TEXT) 104 _w32(buf, FOFF_OPT + 20, NXWSA_RVA_TEXT) 105 _w64(buf, FOFF_OPT + 24, IMG_BASE_LO, IMG_BASE_HI) 106 _w32(buf, FOFF_OPT + 32, 0x1000) 107 _w32(buf, FOFF_OPT + 36, 0x200) 108 _w16(buf, FOFF_OPT + 40, 6) 109 _w16(buf, FOFF_OPT + 48, 6) 110 _w32(buf, FOFF_OPT + 56, 0x3000) 111 _w32(buf, FOFF_OPT + 60, 0x200) 112 _w16(buf, FOFF_OPT + 68, PE_SUBSYSTEM_CONSOLE) 113 _w64(buf, FOFF_OPT + 72, 0x100000, 0) 114 _w64(buf, FOFF_OPT + 80, 0x1000, 0) 115 _w64(buf, FOFF_OPT + 88, 0x100000, 0) 116 _w64(buf, FOFF_OPT + 96, 0x1000, 0) 117 _w32(buf, FOFF_OPT + 108, 16) 118 _w32(buf, FOFF_OPT + 112 + 8, NXWSA_RVA_IDATA) 119 _w32(buf, FOFF_OPT + 112 + 12, 0x3C) // Import Table size = 3 descriptors (kernel32 + ws2_32 + null) 120 _emit_section_header(buf, FOFF_SECT_TBL, 46, 116, 101, 120, 116, 0, 0, 0, text_vsize, NXWSA_RVA_TEXT, 0x200, NXWSA_FOFF_TEXT, PE_SECT_CODE_X_R) 121 _emit_section_header(buf, FOFF_SECT_TBL + 40, 46, 105, 100, 97, 116, 97, 0, 0, 0xB0, NXWSA_RVA_IDATA, 0x200, NXWSA_FOFF_IDATA, PE_SECT_DATA_R) 122 123 // ===== .text: entry stub (call main; exit with its return) ===== 124 let t: i64 = NXWSA_FOFF_TEXT 125 _w8(buf, t+0, 0x48); _w8(buf, t+1, 0x83); _w8(buf, t+2, 0xEC); _w8(buf, t+3, 0x28) 126 _w8(buf, t+4, 0xE8); _w32(buf, t+5, 0x9 + main_off) 127 _w8(buf, t+9, 0x89); _w8(buf, t+10, 0xC1) 128 _w8(buf, t+11, 0xFF); _w8(buf, t+12, 0x15); _w32(buf, t+13, NXWSA_IAT_EXIT - (NXWSA_RVA_TEXT + 17)) 129 _w8(buf, t+17, 0xCC) 130 var i: i64 = 0 131 while i < code_len { buf[t + NXWSA_STUB_LEN + i] = code[i]; i = i + 1 } 132 133 // ===== LINKER STEP: WSAStartup thunk (own stack WSADATA) + redirect nx_wsa_startup ===== 134 let thunk_rva: i64 = NXWSA_RVA_TEXT + thunk_off 135 let th: i64 = NXWSA_FOFF_TEXT + thunk_off 136 _w8(buf, th+0, 0x48); _w8(buf, th+1, 0x81); _w8(buf, th+2, 0xEC); _w32(buf, th+3, 0x228) // sub rsp,0x228 137 _w8(buf, th+7, 0xB9); _w32(buf, th+8, 0x0202) // mov ecx,0x0202 138 _w8(buf, th+12, 0x48); _w8(buf, th+13, 0x8D); _w8(buf, th+14, 0x54); _w8(buf, th+15, 0x24); _w8(buf, th+16, 0x28) // lea rdx,[rsp+0x28] 139 _w8(buf, th+17, 0xFF); _w8(buf, th+18, 0x15); _w32(buf, th+19, NXWSA_IAT_WSA - (thunk_rva + 23)) // call [rip] WSAStartup 140 _w8(buf, th+23, 0x48); _w8(buf, th+24, 0x81); _w8(buf, th+25, 0xC4); _w32(buf, th+26, 0x228) // add rsp,0x228 141 _w8(buf, th+30, 0xC3) // ret 142 // OVERWRITE nx_wsa_startup's first 5 bytes with `jmp rel32` -> thunk 143 let sh_rva: i64 = NXWSA_RVA_TEXT + NXWSA_STUB_LEN + sh_off 144 let sh: i64 = NXWSA_FOFF_TEXT + NXWSA_STUB_LEN + sh_off 145 _w8(buf, sh+0, 0xE9); _w32(buf, sh+1, thunk_rva - (sh_rva + 5)) 146 147 // ===== .idata: 2 DLLs (kernel32 {ExitProcess} + ws2_32 {WSAStartup}) ===== 148 let d: i64 = NXWSA_FOFF_IDATA 149 // Import Descriptor[0] kernel32 150 _w32(buf, d + 0x00, 0x203C) // OFT -> INT_k 151 _w32(buf, d + 0x0C, 0x2097) // Name -> "kernel32.dll" 152 _w32(buf, d + 0x10, 0x205C) // FT -> IAT_k 153 // Import Descriptor[1] ws2_32 154 _w32(buf, d + 0x14, 0x204C) // OFT -> INT_w 155 _w32(buf, d + 0x20, 0x20A4) // Name -> "ws2_32.dll" 156 _w32(buf, d + 0x24, 0x206C) // FT -> IAT_w 157 // Descriptor[2] null (d+0x28..0x3C) -- already zero 158 // INT_k @ 0x203C 159 _w64(buf, d + 0x3C, 0x207C, 0) // -> ExitProcess name 160 _w64(buf, d + 0x44, 0, 0) // null 161 // INT_w @ 0x204C 162 _w64(buf, d + 0x4C, 0x208A, 0) // -> WSAStartup name 163 _w64(buf, d + 0x54, 0, 0) // null 164 // IAT_k @ 0x205C 165 _w64(buf, d + 0x5C, 0x207C, 0) // ExitProcess (IAT 0x205C) 166 _w64(buf, d + 0x64, 0, 0) 167 // IAT_w @ 0x206C 168 _w64(buf, d + 0x6C, 0x208A, 0) // WSAStartup (IAT 0x206C) 169 _w64(buf, d + 0x74, 0, 0) 170 // IMAGE_IMPORT_BY_NAME ExitProcess @ 0x207C 171 _w16(buf, d + 0x7C, 0) 172 _w8(buf,d+0x7E,69);_w8(buf,d+0x7F,120);_w8(buf,d+0x80,105);_w8(buf,d+0x81,116) // Exit 173 _w8(buf,d+0x82,80);_w8(buf,d+0x83,114);_w8(buf,d+0x84,111);_w8(buf,d+0x85,99) // Proc 174 _w8(buf,d+0x86,101);_w8(buf,d+0x87,115);_w8(buf,d+0x88,115);_w8(buf,d+0x89,0) // ess\0 175 // IMAGE_IMPORT_BY_NAME WSAStartup @ 0x208A 176 _w16(buf, d + 0x8A, 0) 177 _w8(buf,d+0x8C,87);_w8(buf,d+0x8D,83);_w8(buf,d+0x8E,65);_w8(buf,d+0x8F,83) // WSAS 178 _w8(buf,d+0x90,116);_w8(buf,d+0x91,97);_w8(buf,d+0x92,114);_w8(buf,d+0x93,116) // tart 179 _w8(buf,d+0x94,117);_w8(buf,d+0x95,112);_w8(buf,d+0x96,0) // up\0 180 // "kernel32.dll\0" @ 0x2097 181 _w8(buf,d+0x97,107);_w8(buf,d+0x98,101);_w8(buf,d+0x99,114);_w8(buf,d+0x9A,110) // kern 182 _w8(buf,d+0x9B,101);_w8(buf,d+0x9C,108);_w8(buf,d+0x9D,51);_w8(buf,d+0x9E,50) // el32 183 _w8(buf,d+0x9F,46);_w8(buf,d+0xA0,100);_w8(buf,d+0xA1,108);_w8(buf,d+0xA2,108);_w8(buf,d+0xA3,0) // .dll\0 184 // "ws2_32.dll\0" @ 0x20A4 185 _w8(buf,d+0xA4,119);_w8(buf,d+0xA5,115);_w8(buf,d+0xA6,50);_w8(buf,d+0xA7,95) // ws2_ 186 _w8(buf,d+0xA8,51);_w8(buf,d+0xA9,50);_w8(buf,d+0xAA,46);_w8(buf,d+0xAB,100) // 32.d 187 _w8(buf,d+0xAC,108);_w8(buf,d+0xAD,108);_w8(buf,d+0xAE,0) // ll\0 188 189 return NX_PE_OK 190} 191 192func main() -> i64 { 193 let lenbox: *i64 = sys_mmap(16) as *i64 194 let src: *u8 = sys_read_file("/tmp/nxwin.s" as *u8, lenbox) 195 if (src as i64) == 0 { return 1 } 196 let n: i64 = lenbox[0] 197 if n <= 0 { return 2 } 198 199 let code: *u8 = sys_mmap(NXWSA_CODE_CAP) 200 let mainbox: *i64 = sys_mmap(16) as *i64 201 let shbox: *i64 = sys_mmap(16) as *i64 202 mainbox[0] = 0 - 1 203 shbox[0] = 0 - 1 204 let code_len: i64 = nxwsa_assemble(src, n, code, NXWSA_CODE_CAP, mainbox, shbox) 205 if code_len < 0 { return 3 } 206 let main_off: i64 = mainbox[0] 207 if main_off < 0 { return 4 } 208 let sh_off: i64 = shbox[0] 209 if sh_off < 0 { return 6 } 210 211 let buf: *u8 = sys_mmap(NXWSA_FILE_SIZE) 212 let rc: i64 = nxwsa_emit_pe(buf, code, code_len, main_off, sh_off) 213 if rc != NX_PE_OK { return 5 } 214 215 let outp: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/_offc/nx_win_compiled_wsa.exe" as *u8 216 if nx_pe_write_to_file(outp, buf, NXWSA_FILE_SIZE) != NX_PE_OK { return 70 } 217 218 let msg: *u8 = "[substrate] nxc2-compiled native Winsock-init PE (2-DLL) written: nx_win_compiled_wsa.exe\n" as *u8 219 sys_write(1, msg, 89) 220 return 0 221}