77 lines
2.8 KiB
C
77 lines
2.8 KiB
C
// 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;
|
|
}
|