Challenge example

Code example

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void secret() {
  char *filename = "./.passwd";
  FILE *file = fopen(filename, "r");
  if (file == NULL) {
    printf("Error opening file.\n");
    return;
  }

  char line[256];
  while (fgets(line, sizeof(line), file)) {
    printf("%s", line);
  }

  fclose(file);
}

char *authenticate() {
  char password[16];
  printf("Enter password: ");
  scanf("%15s", password);

  if (strcmp(password, "secret") == 0) {
    return "admin";
  } else {
    return "guest";
  }
}

void menu(char *user_type) {
  int choice;
  char header[32] = "Hello World !";
  while (1) {
    printf("\n--- Menu ---\n");
    printf(header);
    printf("\n");
    printf("1. Change header\n");
    if (strcmp(user_type, "admin") == 0) {
      printf("2. Read secret\n");
    }
    printf("0. Exit\n");
    printf("Enter your choice: ");
    scanf("%1d", &choice);

    if (choice == 1) {
      // Change the header string
      printf("Enter new header: ");
      scanf("%30s", header);
    } else if (choice == 0) {
      // Exit
      break;
    } else if (choice == 2 && strcmp(user_type, "admin") == 0) {
      // Call the secret() function
      secret();
    } else {
      printf("Invalid choice. Try again.\n");
    }
  }
}


int main() {
  char *user_type = malloc(16);
  strcpy(user_type, authenticate());
  printf("Welcome, %s!\n", user_type);
  menu(user_type);
}

The objective is to rewrite the user_type value to "admin" in order to read the secret file

Exploitation

The first step is to identify the offset between the user input used to exploit the format string and the "user_type" variable into the stack.

Retrieving offset

Retrieving user input

Using the stack command, it's possible to retrieve the user input location on the stack :

circle-check

Retrieving "user_type"

Using the find command it's possible to search a specific value into the memory :

Due to the malloc the value is stored into the heap. Here the location address is 0x804d1a0

Still Using the find command, it's possible to locate this pointer into the stack :

Offset calculation

Then ([pointer stack address] - [user_input stack address]) / 4 = offset

Editing value

In order to validate the objective, it's possible to directly edit the "user_type" variable directly ans see the repercussion on the program execution !

When the process is continued, the "3. read secret" option apear into the menu :

circle-info

It's also possible to overwrite the value of the saved instruction pointer into the stack to jump directly into the "secret" function when closing the menu instead of return to the main function.

Exercice

If you want to try this exploit by yourself, you can pull this docker imagearrow-up-right :

Deploy the image using the followed command :

Access to the web shell with your browser at the address : http://localhost:3000/

Last updated