#include #include #include struct node { struct node *prev; struct node *next; char const *data; }; [[noreturn]] void die(char const *s) { fputs(s, stderr); exit(EXIT_FAILURE); } struct node *list_new(char const *data) { struct node *node = malloc(sizeof(struct node)); if (node == NULL) { die("malloc failed in list_new\n"); } node->prev = NULL; node->next = NULL; node->data = data; return node; } void list_insert_after(struct node *insertion_point, char const *data) { struct node *node = malloc(sizeof(struct node)); if (node == NULL) { die("malloc failed in list_insert_after\n"); } node->prev = insertion_point; node->data = data; if (insertion_point->next) { insertion_point->next->prev = node; } node->next = insertion_point->next; insertion_point->next = node; } void list_remove(struct node *node) { if (node->prev) { node->prev->next = node->next; } if (node->next) { node->next->prev = node->prev; } free(node); } void list_remove_safe(struct node *node); static char authenticated = 0; int main(void) { struct node *first_node = list_new("first node"); list_insert_after(first_node, "second node"); struct node *second_node = first_node->next; list_insert_after(second_node, "third node"); // Begin "vulnerability" printf("LEAK: &authenticated is %p\n", &authenticated); char buf[2 + 0x10 + 1] = {}; read(STDIN_FILENO, buf, sizeof(buf) - 1); second_node->prev = (void *)strtoull(buf, NULL, 16); read(STDIN_FILENO, buf, sizeof(buf) - 1); second_node->next = (void *)strtoull(buf, NULL, 16); // End "vulnerability" list_remove_safe(second_node); if (authenticated) { puts("You win!"); } }