Everytime i’m about to participate on a new ctf, the first thing i do is to search for the past edition challenges, here is my writeup on the LA-CTF 2024 aplet321 reversing challenge

Challenge description

The challenge provides the following description:

Unlike Aplet123, Aplet321 might give you the flag if you beg him enough.


After poking with the binary for a bit, it wouldn’t do anything apart from that:

lactf-archive/2024/rev/aplet321$ ./aplet321 
hi, i'm aplet321. how can i help?
test
so rude


So it was time for some static analysis.

Understanding the logic

After opening the binary on ghidra and doing some basic variable renaming, we are going to have the following pseudo-code:

// DISPLAY WARNING: Type casts are NOT being printed

int main(void)

{
  int success;
  size_t input_len;
  char *input_ptr;
  int please_count;
  int pretty_count;
  char user_input [512];
  
  setbuf(stdout,NULL);
  puts("hi, i\'m aplet321. how can i help?");
  fgets(user_input,0x200,stdin);
  input_len = strlen(user_input);
  if (5 < input_len) {
    please_count = 0;
    pretty_count = 0;
    input_ptr = user_input;
    do {
      success = strncmp(input_ptr,"pretty",6);
      pretty_count += success == 0;
      success = strncmp(input_ptr,"please",6);
      please_count += success == 0;
      input_ptr = input_ptr + 1; // skip space
    } while (input_ptr != user_input + (input_len - 6) + 1);
    if (please_count != 0) {
      input_ptr = strstr(user_input,"flag");
      if (input_ptr == NULL) {
        puts("sorry, i didn\'t understand what you mean");
        return 0;
      }
      if ((pretty_count + please_count == 54) && (pretty_count - please_count == -24)) {
        puts("ok here\'s your flag");
        system("cat flag.txt");
        return 0;
      }
      puts("sorry, i\'m not allowed to do that");
      return 0;
    }
  }
  puts("so rude");
  return 0;
}

The first thing that catches my attention are the strncmp for “pretty” and “please”, if the comparison is successful, the counter for the respective word is incremented, by that we already know what the program is expecting. There is also a reference to strstr, which basically only checks for the presence of some string.

The following while condition may seem confusing at first

 while (input_ptr != user_input + (input_len - 6) + 1)

But after poking it for a while, its simply iterates through each word until both the original user_input and the input_ptr points at the same address, meaning the whole input was processed.

For comparison purposes, here is a python snippet with the same function:

for word in user_input

Solving

We already know what the program is expecting, but how much of each?

The following condition is the one to decide if we are going to get the flag:

if ((pretty_count + please_count == 54) && (pretty_count - please_count == -24))

We can solve this simple equation and discover how much of each word we need to satisfy the condition.

x + y = 54
x - y = -24
(x, y) = (15, 39)

Being x = pretty and y = please, we just concatenate everything with a space to separate, adding flag to the end to satisty the strstr condition.

Our final payload would be:

pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please flag

And after running it, we get the flag:

lactf-archive/2024/rev/aplet321$ ./aplet321 
hi, i'm aplet321. how can i help?
pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty pretty please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please please flag
ok here's your flag
lactf{next_year_i'll_make_aplet456_hqp3c1a7bip5bmnc}