The Chef's Secret Recipe


Reversing Challenge Writeup: The Chef’s Secret Recipe

Overview

This challenge involves a binary that validates a flag based on a hardcoded “recipe.” The program generates a secret string internally and compares it against the argument provided by the user. The goal is to statically analyze the code to reconstruct the generated string.

Static Analysis

1. The “Ingredient” Functions

The binary contains a large number of small, seemingly unrelated functions (e.g., bake, perfect, sift, flour).

Upon inspection, we see that each of these functions is a pure function that immediately returns a constant 64-bit integer value. These integer values are, in fact, the hexadecimal representation of the ASCII characters that make up the flag.

Example:

004011a9 int64_t bake() __pure
004011b3 return 0x48 // Hex 48 is 'H' in ASCII

2. The parse_recipe Function

This function (starting at 00401417) is responsible for constructing the final flag string:

  1. It copies the hardcoded “recipe” text from main and tokenizes it (splits it into individual words).
  2. It uses normalize_word to convert each token to lowercase and likely filter non-alphanumeric characters.
  3. It enters a double loop: an outer loop iterating through the words (i), and a crucial inner loop iterating through an array of ingredient names, indexed by j (from 0 to 40).
  4. The key logic is:
    // Simplified Pseudocode
    for (int64_t j = 0; j <= 0x28; j += 1) {
    if (strcmp(current_word, ingredients[j]) == 0) {
    // Store the result of the function call into the j-th position of the flag buffer
    flag_buffer[j] = ingredient_functions[j]();
    break;
    }
    }

3. The Construction Mechanism

The critical observation is that the code uses the index j of the matching ingredient to determine the position in the output buffer (flag_buffer[j]).

Since the “recipe” text provided in main contains all the ingredient keywords, the program successfully executes every function and places its character in the buffer based on its sequential index in the function list. The flag is therefore the concatenation of the return values in the order they appear in the binary’s address space.

Solution

By mapping the return value of each function (in the order they are defined) to its corresponding ASCII character, we reconstruct the flag:

IndexFunction NameReturn (Hex)ASCII Character
0bake0x48H
1perfect0x65e
2sift0x72r
3flour0x6fo
4sugar0x7b{
5crack0x300
6eggs0x68h
7melt0x5f_
8butter0x4eN
9blend0x300
10vanilla0x5f_
(Continued mapping)
28parchment0x5f_
29timer0x43C
30light0x344
31candle0x6bk
32plate0x333
33garnish0x5f_
34frosting0x52R
35pinch0x333
36salt0x63c
37crushed0x311
38nuts0x70p
39touch0x65e
40sweetness0x7d}

The Flag

The concatenated string forms the solution:

Hero{0h_N0_y0u_60T_My_S3cReT_C4k3_R3c1pe}