Protostar net3
About
This level introduces the concept that memory can be accessed outside of its allocated region, how the stack variables are laid out, and that modifying outside of the allocated memory can modify program execution.
This level is at /opt/protostar/bin/net3
Source code
1#include "../common/common.c" 2 3#define NAME "net3" 4#define UID 996 5#define GID 996 6#define PORT 2996 7 8/* 9 * Extract a null terminated string from the buffer 10 */ 11 12int get_string(char **result, unsigned char *buffer, u_int16_t len) 13{ 14 unsigned char byte; 15 16 byte = *buffer; 17 18 if(byte > len) errx(1, "badly formed packet"); 19 *result = malloc(byte); 20 strcpy(*result, buffer + 1); 21 22 return byte + 1; 23} 24 25/* 26 * Check to see if we can log into the host 27 */ 28 29int login(unsigned char *buffer, u_int16_t len) 30{ 31 char *resource, *username, *password; 32 int deduct; 33 int success; 34 35 if(len < 3) errx(1, "invalid login packet length"); 36 37 resource = username = password = NULL; 38 39 deduct = get_string(&resource, buffer, len); 40 deduct += get_string(&username, buffer+deduct, len-deduct); 41 deduct += get_string(&password, buffer+deduct, len-deduct); 42 43 success = 0; 44 success |= strcmp(resource, "net3"); 45 success |= strcmp(username, "awesomesauce"); 46 success |= strcmp(password, "password"); 47 48 free(resource); 49 free(username); 50 free(password); 51 52 return ! success; 53} 54 55void send_string(int fd, unsigned char byte, char *string) 56{ 57 struct iovec v[3]; 58 u_int16_t len; 59 int expected; 60 61 len = ntohs(1 + strlen(string)); 62 63 v[0].iov_base = &len; 64 v[0].iov_len = sizeof(len); 65 66 v[1].iov_base = &byte; 67 v[1].iov_len = 1; 68 69 v[2].iov_base = string; 70 v[2].iov_len = strlen(string); 71 72 expected = sizeof(len) + 1 + strlen(string); 73 74 if(writev(fd, v, 3) != expected) errx(1, "failed to write correct amount of bytes"); 75 76} 77 78void run(int fd) 79{ 80 u_int16_t len; 81 unsigned char *buffer; 82 int loggedin; 83 84 while(1) { 85 nread(fd, &len, sizeof(len)); 86 len = ntohs(len); 87 buffer = malloc(len); 88 89 if(! buffer) errx(1, "malloc failure for %d bytes", len); 90 91 nread(fd, buffer, len); 92 93 switch(buffer[0]) { 94 case 23: 95 loggedin = login(buffer + 1, len - 1); 96 send_string(fd, 33, loggedin ? "successful" : "failed"); 97 break; 98 99 default: 100 send_string(fd, 58, "what you talkin about willis?"); 101 break; 102 } 103 } 104} 105 106int main(int argc, char **argv, char **envp) 107{ 108 int fd; 109 char *username; 110 111 /* Run the process as a daemon */ 112 background_process(NAME, UID, GID); 113 114 /* Wait for socket activity and return */ 115 fd = serve_forever(PORT); 116 117 /* Set the client socket to STDIN, STDOUT, and STDERR */ 118 set_io(fd); 119 120 /* Don't do this :> */ 121 srandom(time(NULL)); 122 123 run(fd); 124}