vuln.c (4428B)
1#include <limits.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <sys/mman.h> 6#include <unistd.h> 7 8#define MAX_NOTES 16 9 10extern char edata; 11extern char data_start; 12 13static inline char *read_line(char **line_buf, size_t *size) { 14 *size = getdelim(line_buf, size, '\n', stdin); 15 if (*size == 0) { 16 puts("Invalid line"); 17 exit(EXIT_FAILURE); 18 } 19 return *line_buf; 20} 21 22void add_note(size_t *sizes, char **notes) { 23 printf("Note: "); 24 for (size_t i = 0; i < MAX_NOTES; i++) { 25 if (sizes[i] == 0) { 26 notes[i] = NULL; 27 sizes[i] = getdelim(¬es[i], &sizes[i], '\n', stdin); 28 printf("Added note: %ld\n", i); 29 return; 30 } 31 } 32 puts("Too many notes"); 33 exit(EXIT_FAILURE); 34} 35 36void remove_note(char **line_buf, size_t *size, size_t *sizes, char **notes) { 37 printf("Index: "); 38 char *line = read_line(line_buf, size); 39 unsigned long index = strtoul(line, NULL, 0); 40 if (index >= MAX_NOTES) { 41 puts("Invalid index"); 42 exit(EXIT_FAILURE); 43 } 44 free(notes[index]); 45 sizes[index] = 0; 46} 47 48void edit_note(char **line_buf, size_t *size, size_t *sizes, char **notes) { 49 printf("Index: "); 50 char *line = read_line(line_buf, size); 51 unsigned long index = strtoul(line, NULL, 0); 52 if (index >= MAX_NOTES || sizes[index] == 0) { 53 puts("Invalid index"); 54 exit(EXIT_FAILURE); 55 } 56 printf("Note: "); 57 line = read_line(line_buf, size); 58 if (*size - 2 > sizes[index]) { 59 puts("Invalid size"); 60 exit(EXIT_FAILURE); 61 } 62 memcpy(notes[index], line, *size - 1); 63} 64 65void flip_bit(char **line_buf, size_t *size, char **notes, int *flips) { 66 if (*flips == 0) { 67 puts("The laser malfunctions and kills the program!"); 68 exit(EXIT_FAILURE); 69 } 70 printf("Index: "); 71 unsigned long index = strtoul(read_line(line_buf, size), NULL, 0); 72 if (index >= MAX_NOTES || notes[index] == NULL) { 73 puts("Invalid index"); 74 exit(EXIT_FAILURE); 75 } 76 printf("Offset: "); 77 char offset = (char)strtol(read_line(line_buf, size), NULL, 0); 78 size_t byte = offset / 8; 79 size_t bit = offset & 0b111; 80 81 puts("The laser is positioned and shoots at the selected memory location!"); 82 notes[index][byte] ^= 0b1 << bit; 83 *flips = *flips - 1; 84} 85 86void exit_handler() { 87 mprotect(&data_start, (size_t)&edata - (size_t)&data_start, 88 PROT_READ | PROT_WRITE); 89} 90 91int main() { 92 93 char *notes[MAX_NOTES]; 94 size_t sizes[MAX_NOTES]; 95 char *line_buf = NULL; 96 size_t size = 0; 97 98 int flips = 2; 99 100 char buf[0x80]; 101 102 memset(buf, 0, sizeof(buf)); 103 memset(notes, 0, sizeof(notes)); 104 memset(sizes, 0, sizeof(sizes)); 105 106 setvbuf(stdin, buf, _IOFBF, sizeof(buf)); 107 setvbuf(stdout, NULL, _IONBF, 0); 108 setvbuf(stderr, NULL, _IONBF, 0); 109 110 mprotect(&data_start, (size_t)&edata - (size_t)&data_start, PROT_READ); 111 on_exit(&exit_handler, NULL); 112 113 if (setuid(0)) { 114 puts("Not running as root :("); 115 } 116 117 puts("╭────────────────────────────────────────────────────╮"); 118 puts("│ FlipNote │"); 119 puts("│ │"); 120 puts("│ Instructions: │"); 121 puts("│ - Type 'a' or 'A' to add a note │"); 122 puts("│ - Type 'e' or 'E' to edit a note │"); 123 puts("│ - Type 'f' or 'F' to use a laser to flip a bit │"); 124 puts("│ - Type 'r' or 'R' to remove a note │"); 125 puts("│ - Type 'q' or 'Q' to quit the program │"); 126 puts("│ │"); 127 puts("╰────────────────────────────────────────────────────╯"); 128 for (;;) { 129 printf("> "); 130 switch (read_line(&line_buf, &size)[0]) { 131 case 'a': 132 case 'A': 133 add_note(sizes, notes); 134 break; 135 case 'e': 136 case 'E': 137 edit_note(&line_buf, &size, sizes, notes); 138 break; 139 case 'f': 140 case 'F': 141 flip_bit(&line_buf, &size, notes, &flips); 142 break; 143 case 'r': 144 case 'R': 145 remove_note(&line_buf, &size, sizes, notes); 146 break; 147 case 'q': 148 case 'Q': 149 exit(EXIT_SUCCESS); 150 default: 151 printf("Invalid option: "); 152 puts(line_buf); 153 break; 154 } 155 } 156 157 free(line_buf); 158 return 0; 159}