Compiled

Strings can only help you so far. - by nerrorsec

For this challenge, we get a compiled binary, which we have to analyze to find the flag. On the first attempt, we just used strings and got mocked that "Strings is for Noob", but we also got some other interesting printable strings like "Password", "DoYouEven%sCTF", "__dso_handle", "_init", "Correct!" and "Try again!". Somewhere here lies the password, which will also be the flag.

The next step is to use Ghidra to analyze the source of the file.

We see that the program prompts the user for a password and checks if it matches the exact string "_init" and is not equal to the string "__dso_handle". If the input meets these conditions, it prints "Correct!"; otherwise, it prints "Try again!".

Let's check out the manpage of scanf:

   The format string consists of a sequence of directives which 
   describe how to process the sequence of input characters. If 
   processing of a directive fails, no further input is read, and 
   scanf() returns. A "failure" can be either of the following: 
   input failure, meaning that input characters were unavailable, or 
   matching failure, meaning that the input was inappropriate (see 
   below)

   A directive is one of the following:

   •      A sequence of white-space characters (space, tab, newline,
          etc.; see isspace(3)).  This directive matches any amount
          of white space, including none, in the input.

   •      An ordinary character (i.e., one other than white space or
          '%').  This character must exactly match the next
          character of input.

   •      A conversion specification, which commences with a '%'
          (percent) character.  A sequence of characters from the
          input is converted according to this specification, and
          the result is placed in the corresponding pointer
          argument.  If the next item of input does not match the
          conversion specification, the conversion fails—this is a
          matching failure.

Recalling __isoc99_scanf("DoYouEven%sCTF",local_28); we have to provide a string matching the ordinary character sequence "DoYouEven" followed by an arbitrary sequence of characters "%s". The format requires ending with "CTF" after the arbitrary sequence of characters. Meeting the correct input conditions to resolve to the value "_init" implies the password.

Lets use a simple C program to check the behaviour of __isoc99_scanf:

test.c
#include <stdio.h>
#include <string.h>

int main()
{ 
    char input [32];
    
    printf("Enter your input: ");
    int a = __isoc99_scanf("DoYouEven%sCTF",input);
    printf("The input is: %s\n", input);
    
    int iVar1 = strcmp(input,"__dso_handle");
    printf("iVar: %d\n", iVar1);
    printf("strcmp __dsohandle > -1: %d\n", (-1 < iVar1));    
    printf("strcmp __dso_handle: %d\n", strcmp(input,"__dso_handle"));
    printf("strcmp _init: %d\n", strcmp(input,"_init"));
    printf("%d",a);
    return 0;
}

Matching failure, the input is empty because the directive fails and the input is not further processed:

We have a match without "CTF" as an ending, by looking at the return value of scanf we get a 1. By recalling the manpage: "If processing of a directive fails, no further input is read, and scanf() returns" does this not appear to happen here. There is a successful match. Maybe %s contradicts with the following sequence of ordinary characters after. However, now we know how to build our password to pass:

Running the provided binary on our machine with the correct password we get the desired respones:

Last updated