// Subject Zero - Freestanding Canary // Markus Maiwald | Voxis Forge // Provided by libnexus.a (Membrane) extern int socket(int domain, int type, int protocol); extern int connect(int fd, const void *addr, int len); extern int write(int fd, const void *buf, int count); extern int printf(const char *format, ...); // Maybe mapped to write(1, ...) // LwIP / Membrane Helpers extern unsigned short htons(unsigned short hostshort); extern int inet_pton(int af, const char *src, void *dst); struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; unsigned int sin_addr; char sin_zero[8]; }; #define AF_INET 2 #define SOCK_STREAM 1 extern void membrane_init(void); extern void pump_membrane_stack(void); int subject_zero_entry() { membrane_init(); write(1, "[Subject0] Boot sequence initiated.\n", 36); write(1, "[Subject0] Requesting Membrane Socket...\n", 41); int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { write(1, "[Subject0] FAILURE: socket() returned error\n", 44); return 1; } write(1, "[Subject0] Got Socket. Connecting to Host (10.0.2.2:8080)...\n", 62); struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = 0x901F; // htons(8080) -> 0x1F90, wait, swapped for Big Endian is 0x901F serv_addr.sin_addr = 0x0202000A; // 10.0.2.2 -> 0x0A, 0x00, 0x02, 0x02. In memory: A 0 2 2. As uint32 BE: 0x0A000202. // Wait, 0x0202000A as Little Endian uint32 is bytes 0A 00 02 02. // If the machine is Little Endian (RISC-V), then 0x0202000A in a register // will be stored as 0A 00 02 02 in memory. // LwIP expects sin_addr as 4 bytes in network order. // So 0x0202000A is CORRECT for 10.0.2.2 if sin_addr is uint32. // Wait, 10.0.2.2 -> A.0.2.2 -> 0x0A000202. // Let's just use 0x0202000A and see. // Actually, let's use a cleaner way. if (connect(fd, &serv_addr, sizeof(serv_addr)) < 0) { write(1, "[Subject0] Connection Failed.\n", 30); return 1; } write(1, "[Subject0] CONNECTED! Sending Greeting...\n", 42); char *hello = "Hello from the Membrane!\n"; write(fd, hello, 26); write(1, hello, 26); write(1, "[Subject0] Entering Loop.\n", 26); while(1) { pump_membrane_stack(); // Yield to Kernel (Phase 7 Coop) typedef void (*yield_func)(void); yield_func rumpk_yield = *(yield_func*)0x801FFFF0; if (rumpk_yield) rumpk_yield(); for(volatile int i=0; i<100000; i++); } return 0; }