exit(0); } else { printf("Looks like everything is still secure!\n"); printf("\nNo flage for you :(\n"); fflush(stdout); } }
voidprint_menu() { printf("\n1. Print Heap:\t\t(print the current state of the heap)" "\n2. Write to buffer:\t(write to your own personal block of data " "on the heap)" "\n3. Print safe_var:\t(I'll even let you look at my variable on " "the heap, " "I'm confident it can't be modified)" "\n4. Print Flag:\t\t(Try to print the flag, good luck)" "\n5. Exit\n\nEnter your choice: "); fflush(stdout); }
voidinit() { printf("\nThislcome to heap1!\n"); printf( "I put my data on the heap so it should be safe from any tampering.\n"); printf("Since my data isn't on the stack I'll even let you write whatever " "info you want to the heap, I already took care of using malloc for " "you.\n\n"); fflush(stdout); input_data = malloc(INPUT_DATA_SIZE); strncpy(input_data, "pico", INPUT_DATA_SIZE); safe_var = malloc(SAFE_VAR_SIZE); strncpy(safe_var, "bico", SAFE_VAR_SIZE); }
voidwrite_buffer() { printf("Data for buffer: "); fflush(stdout); scanf("%s", input_data); }
The program allocates memory on the heap for two variables: input_data and safe_var, each being 5 bytes in size.
strncpy copies initial values into these buffers.
The write_buffer function allows us to write to the input_data var using scanf.
The check_win function verifies that the safe_var var has been changed from bico to pico. If it is, then we get our flag.
Vulnerabilities
There’s several vulnerabilities to note:
The buffer for size for input_data and safe_var are only 5 bytes, meaning they should be easy to overflow.
The scanf library function does not limit our input size, meaning we can enter strings longer than 5 characters (this should be an instant giveaway that it will be a buffer overflow challenge).
Thislcome to heap1! I put my data on the heap so it should be safe from any tampering. Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.
1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit
Enter your choice:
To clarify, pico and bico are the values inside the variables (input_data & safe_var respectively) that were declared at the start. The reason that the variables are allocated with 5 bytes, despite only containing 4 characters, is because we need a null character.
To understand the distance between each variables, we subtract the address of pico with the address of bico (or vice verse).
0x63c3882552b0 - 0x63c3882552d0 = -0x20. If we run -0x20 through cyber chef (from hex to decimal) we get a value of 32. Because our initial hex value was negative, that means that safe_var is 32 bytes behind input_data.
Solution
This now know that safe_var is 32 bytes behind input_data so we just need to overflow the buffer with 32 characters, and then write ‘pico’ to get our flag.
For the sake of simplicity, it’s more efficient to use numbers for our characters. So instead of typing 32 A’s followed by ‘pico’: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApico. This can just count in multiples of 5’s (or whatever you prefer) and then write pico: