Filter invalid sizes to make it secure!
Backup: nc 167.99.78.201 9001
nc filtered.chal.acsc.asia 9001
Solution
First, the user is asked for the data length. If the length is more than 0x100, the program exits.
int length;char buf[0x100];/* Read and check length */length =readint("Size: ");if (length >0x100) {print("Buffer overflow detected!\n");exit(1);}/* Read data */readline("Data: ", buf, length);print("Bye!\n");
The length is read using atoi():
/* Print `msg` and read an integer value */intreadint(constchar*msg) {char buf[0x10];readline(msg, buf,0x10);returnatoi(buf);}
I came across this thread. Using 2147483648, an integer overflow is caused since the largest unsigned int is 2147483647. Therefore, length will be a negative signed integer, passing the length check.
However, when calling readline(), the length is passed to a size_t argument.
/* Print `msg` and read `size` bytes into `buf` */voidreadline(constchar*msg,char*buf,size_t size) {char c;print(msg);for (size_t i =0; i < size; i++) {if (read(0,&c,1)<=0) {print("I/O Error\n");exit(1); } elseif (c =='\n') { buf[i] ='\0';break; } else { buf[i] = c; } }}
Now, size_t is unsigned, so the permitted size would instead become a large positive integer. We can try this experiment ourselves: