Examine code below to see if it helps. Main point is that badf00d is the trigger in existing code (the exploit) and the malicious program is loaded via the read call.
Usually, the goal is to discover the correct value for other_value and to fuzz the input to discover the vulnerability in read.
The read input is where the exploit inserts malicioius code. 1000 bytes is too much for the local heap allocated by buffer which has only 24 bytes.
Notice that adding 0xffff to protector puts the address way way far away from after_buffer that is where the exploit trigger exist and the exploit wants to execute. The exploit is hoping at trigger address there is some specific value badf00d.
A couple of possible outcomes from here:
Knowing that value exist confirms that when the function returns the malicious code will have taking control of the program counter.
Knowing that value exist confirms that some trigger can be invoked to load the malicious code.
Once execution is redirected by the badf00d any code on the stack can execute.
read_char=0x0c999c
other_value=0x0c9998
protector=0x0c9990
buffer=0x0c99a0
after_buffer=0x0c998f
protector+offset=0x149988
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct node_t {
int x;
char y;
float z;
} node_p;
void unsafe() {
int read_char;
int other_value = 0xFFFF;
int* protector = (int *)malloc(sizeof(node_p)*33);
char buffer[24];
char after_buffer;
printf(" read_char=%p\n", &read_char);
printf(" other_value=%p\n", &other_value);
printf(" protector=%p\n", &protector);
printf(" buffer=%p\n", &buffer);
printf("after_buffer=%p\n", &after_buffer);
printf("\n");
printf("protector+offset=%p\n", (&protector + other_value) );
return;
}
int main(int argc, char* argv[]){
unsafe();
return 0;
}